โ† Back to OOP Concepts
โœ‚๏ธ
Principles

Interface Segregation

Clients should not be forced to depend on interfaces or methods they do not use โ€” prefer many small, focused interfaces over one large general-purpose one.

The Problem

A "fat" interface with many unrelated methods forces every implementing class to provide (or stub out) methods it doesn't need, leading to empty or throwing implementations and tight coupling between unrelated clients.

How It Works

  • โ€บSplit large interfaces into smaller, role-specific ones (e.g., Printable, Scannable instead of one Machine interface)
  • โ€บClasses implement only the interfaces relevant to their behavior
  • โ€บClients depend only on the methods they actually call
  • โ€บReduces ripple effects โ€” changes to an unused method no longer force changes in unrelated classes

When to Use

โœ“An interface has methods that only some implementers need
โœ“Implementing classes throw "not supported" for some interface methods
โœ“Designing plugin/capability systems (e.g., a printer that can print but not scan)

Real-World Examples

๐ŸŽ
iOS

Separate protocols like UITableViewDataSource and UITableViewDelegate instead of one giant protocol

๐Ÿค–
Android

Separate listener interfaces like OnClickListener and OnLongClickListener

๐ŸŒ
Web

Splitting a generic Repository interface into separate Readable and Writable interfaces

Code Examples

Swift
// โŒ Fat interface forces SimplePrinter to implement scan()/fax() too
// protocol Machine { func print(); func scan(); func fax() }

// โœ… Segregated interfaces โ€” implement only what you support
protocol Printer {
    func print(_ document: String)
}

protocol Scanner {
    func scan() -> String
}

struct SimplePrinter: Printer {
    func print(_ document: String) {
        print("Printing: \(document)")
    }
}

struct AllInOnePrinter: Printer, Scanner {
    func print(_ document: String) { print("Printing: \(document)") }
    func scan() -> String { "Scanned document" }
}