導入
Interface Segregation Principle——「使わないメソッドを実装させない」。巨大なインターフェースは、それを実装するクラスに不要な負担を強います。小さく分けるのが正解です。
図解
flowchart TB
subgraph Before["肥大化"]
BIG["IMachine<br/>Print / Scan / Fax<br/>(単機能プリンタも全部実装させられる)"]
end
subgraph After["分離"]
P["IPrinter.Print()"]
S["IScanner.Scan()"]
end
Before -->|役割ごとに分割| After
サンプル
// ✅ 必要な契約だけを実装できるよう、小さく分ける
IPrinter printer = new SimplePrinter();
printer.Print("資料"); // 印刷: 資料
interface IPrinter { void Print(string doc); }
interface IScanner { void Scan(string doc); }
// 印刷しかできない機器は IPrinter だけ実装すればよい(Scan を強制されない)
class SimplePrinter : IPrinter
{
public void Print(string doc) => Console.WriteLine($"印刷: {doc}");
}
// 複合機は両方を実装する
class AllInOne : IPrinter, IScanner
{
public void Print(string doc) => Console.WriteLine($"印刷: {doc}");
public void Scan(string doc) => Console.WriteLine($"スキャン: {doc}");
}
- 大きな1つより、小さな複数のインターフェースに分ける
- 実装クラスは必要な契約だけを選んで実装できる
- 「このクラスにこのメソッドは本当に要るか?」が分割の判断基準
演習
IReadable file = new TextFile();
Console.WriteLine(file.Read()); // ファイルの中身
// TODO: IReadable(Read() → string)だけを実装する TextFile を定義してください
// (書き込み機能は今回のクラスには持たせない = 使わない契約を強制しない)
interface IReadable { string Read(); }
interface IWritable { void Write(string data); }
___
- 期待される出力:
ファイルの中身
ヒント1を見る
class TextFile : IReadable { public string Read() => "ファイルの中身"; }
ヒント2を見る
IWritableは実装せず、必要なIReadableだけを実装します
まとめ
- インターフェース分離の原則:使わないメソッドを強制しない
- 大きな契約は小さく分ける
- 実装クラスは必要な契約だけを選べる
次回: SOLIDの総仕上げ「依存性逆転の原則」です。