SOLID Principles (Series) [PART 4]
SOLID - make Object-Oriented designs more understandable, flexible and maintainable.
If get to know something new by reading my articles, don't forget to endorse me on LinkedIn
What is ISP?
Segregation means keeping things separated, and the Interface Segregation Principle is about separating the Interfaces
.
The principle states that many client-specific
interfaces
are better than one general-purposeinterface
.Clients should not be forced to
implement
afunction
they do no need.ISP splits
interfaces
that are very large into smaller and more specific ones so that clients will only have to know about thefunctions
that are of interest to them.
Things to remember
Don’t depend on things you don’t need.
Interfaces
containingmethods
that are not specific to it are called polluted or fatinterfaces
. We should avoid them.Many client-specific
interfaces
are better than one general-purposeinterface
. When we have non-cohesiveinterfaces
, the ISP guides us to create multiple, smaller, cohesiveinterfaces
.
Let's continue with the example from LSP.
interface MediaPlayer {
fun playAudio(mediaContent : MediaContent)
}
interface VideoMediaPlayer : MediaPlayer {
fun playVideo(mediaContent : MediaContent)
}
class VLCMediaPlayer : VideoMediaPlayer {
@override fun playAudio(mediaContent : MediaContent) {...}
@override fun playVideo(mediaContent : MediaContent) {...}
}
class WinampMediaPlayer : MediaPlayer {
@override fun playAudio(mediaContent : MediaContent) {...}
}
Above example is okay by following LSP. But what if we add another media player called VideoOnlyMediaPlayer
?.
class VideoOnlyMediaPlayer : VideoMediaPlayer {
@override fun playAudio(mediaContent : MediaContent) {...}
@override fun playVideo(mediaContent : MediaContent) {...}
}
And, That's where the problem occurs. VideoOnlyMediaPlayer
is forced to implement playAudio()
function.
Again what's the problem with this design from LSP?
New MediaPlayer
called VideoOnlyMediaPlayer
should support only video MediaContent
. It was not designed to play audio MediaContent
. Since VideoMediaPlayer
extends MediaPlayer
, all Classes
who implement VideoMediaPlayer
must implement
the playAudio()
function.
Which state that We're forcing client to implement unnecessary functions.
So, how do we solve this problem by following ISP?.
We can modify our VideoMediaPlayer
not to be extended from MediaPlayer
. In this case, clients who doesn't need support for audio MediaContent
won't be forced to implement playAudio()
function.
Clients who needs support for both audio & video MediaContent
must implements MediaPlayer
and VideoMediaPlayer
at their own.
Let's get into the solution.
interface AudioMediaPlayer {
fun playAudio(mediaContent : MediaContent)
}
interface VideoMediaPlayer {
fun playVideo(mediaContent : MediaContent)
}
class VLCMediaPlayer : VideoMediaPlayer, AudioMediaPlayer {
@override fun playAudio(mediaContent : MediaContent) {...}
@override fun playVideo(mediaContent : MediaContent) {...}
}
class WinampMediaPlayer : AudioMediaPlayer {
@override fun playAudio(mediaContent : MediaContent) {...}
}
class VideoOnlyMediaPlayer : VideoMediaPlayer {
@override fun playVideo(mediaContent : MediaContent) {...}
}
So, what's the changes here?
AudioMediaPlayer
andVideoMediaPlayer
is now independentInterface
, there is no dependency between them. [MediaPlayer
refactored toAudioMediaPlayer
]New introduced
VideoOnlyMediaPlayer
supports videoMediaContent
only. Thus,VideoOnlyMediaPlayer
is not forced to implmenetplayAudio()
function as there is no inter-connection betweenAudioMediaPlayer
andVideoMediaPlayer
.VideoOnlyMediaPlayer
support videoMediaContent
only.VLCMediaPlayer
support both audio & videoMediaContent
.WinampMediaPlayer
support only audioMediaContent
as we have expected.
Recap
The principle states that many client-specific
interfaces
are better than one general-purposeinterface
.Clients should not be forced to
implement
afunction
they do no need.ISP splits
interfaces
that are very large into smaller and more specific ones so that clients will only have to know about thefunctions
that are of interest to them.
In the next & last article of this series, we will talk about Dependency Inversion Principle.
That's it for today. Happy Coding...