Interface Segregation Principle (ISP)
Clients should not be forced to depend upon interfaces they do not use.
Split large interfaces into smaller, focused ones.
Problem
A BasicPlayer is forced to implement record and stream it doesn't support:
// ❌ Fat interface
interface MediaPlayer {
play(file: string): void;
record(source: string): void;
stream(url: string): void;
}
class BasicPlayer implements MediaPlayer {
play(file: string) { /* ok */ }
record() { throw new Error('Not supported'); } // forced!
stream() { throw new Error('Not supported'); } // forced!
}
Solution
Split into role-specific interfaces:
interface Playable { play(file: string): void; }
interface Recordable { record(source: string): void; }
interface Streamable { stream(url: string): void; }
class BasicPlayer implements Playable {
play(file: string) { /* ... */ }
}
class ProRecorder implements Playable, Recordable {
play(file: string) { /* ... */ }
record(src: string) { /* ... */ }
}
Key Insight
Each class implements only what it physically supports. No more throwing NotSupportedException from required methods.
Real-world Example
Printer management:
Printable,Scannable,Faxable,Stapleable- An inkjet implements
Printable+Scannable; a laser-only printer justPrintable