The open closed principle is the O in the SOLID principles. It was created by Bertrand Meyer and states:
Software entities should be open for extension, but closed for modification
Let's dive deeper with an example.
We've been tasked with creating a platform that merges all video streaming sites. The platform will be able to add a platform to its list of platforms, search for a video on all platforms and play a video from the search results. The class can look like so:
interface Video{ | |
public void play(); | |
} | |
class Netflix{ | |
public Video search(String searchQuery){ | |
//.. implement search function | |
} | |
} | |
class Hulu{ | |
public Video search(String searchQuery){ | |
//.. implement search function | |
} | |
} | |
class AmazonVideo{ | |
public Video search(String searchQuery){ | |
//.. implement search function | |
} | |
} | |
class Hbo{ | |
public Video search(String searchQuery){ | |
//.. implement search function | |
} | |
} | |
class CentralVideoStreamingPlatform{ | |
public void add(Netflix netflix){} | |
public void add(Hulu hulu){} | |
public void add(AmazonVideo amazonVideo){} | |
public void add(Hbo hbo){} | |
public Video searchVideo(String searchQuery){ | |
//.. implement search fucntion | |
} | |
public void play(Video selectedVideo){} | |
private ArrayList<VideoStreamingPlatform> platforms = new ArrayList<VideoStreamingPlatform>(); | |
} |
CentralVideoStreamingPlatform
covers most mainstream video streaming platforms. However, if we were to add another platform, say DisneyPlus
, another #add()
would be created. This directly violates the open for extension aspect of OCP.CentralVideoStreamingPlatform
must be open to accept different details without needing to change code that's already written. By overloading #add()
again, we are needlessly changing CentralVideoStreamingPlatform
. Who's to say how many #add()
CentralVideoStreamingPlatform
would have as more streaming platforms are added?
To ensure CentralVideoStreamingPlatform
's extensibility, we can refactor the video streaming classes to implement a VideoStreamingPlatform
interface and use one #add()
.
interface Video{ | |
public void play(); | |
} | |
interface VideoStreamingPlatform{ | |
public Video search(String searchQuery); | |
} | |
class Netflix implements VideoStreamingPlatform{ | |
public Video search(String searchQuery){ | |
//.. implement search function | |
} | |
} | |
class Hulu implements VideoStreamingPlatform{}{ | |
public Video search(String searchQuery){ | |
//.. implement search function | |
} | |
} | |
class AmazonVideo implements VideoStreamingPlatform{}{ | |
public Video search(String searchQuery){ | |
//.. implement search function | |
} | |
} | |
class Hbo implements VideoStreamingPlatform{}{ | |
public Video search(String searchQuery){ | |
//.. implement search function | |
} | |
} | |
class CentralVideoStreamingPlatform{ | |
CentralVideoStreamingPlatform(){} | |
public void addPlatform(VideoStreamingPlatform streamingPlatform){ | |
platforms.add(streamingPlatform); | |
} | |
public Video searchVideo(String searchQuery){ | |
//.. implement search function | |
} | |
public void play(Video selectedVideo){ | |
selectedVideo.play(); | |
} | |
private ArrayList<VideoStreamingPlatform> platforms = new ArrayList<VideoStreamingPlatform>(); | |
} |
In Conclusion
The open closed principle is a great principle to keep in mind when writing classes.
Top comments (1)
Umm... Is it just me or you switched examples 1 and 2 around? I think it should be 1 then 2 and now its 2 then 1.