本文へスキップ
BecomeCoder

C#デザインパターンコース · 第1章 デザインパターン · レッスン5

構造①:Adapter / Bridge

ブラウザで完結

導入

構造に関するパターンは「クラスの組み合わせ方」を工夫します。Adapterは「互換性のない既存クラスを、望む形に変換する変換プラグ」、Bridgeは「機能の階層と実装の階層を分離」して独立に拡張できるようにします。

図解

flowchart LR
    C["利用側が期待する形<br/>ITarget"] --> AD["Adapter<br/>変換"]
    AD --> OLD["既存の別インターフェース<br/>(そのままでは使えない)"]
    style AD fill:#e1f5fe

サンプル

// Adapter: 既存の OldPrinter を、新しい IPrinter として使えるよう変換
IPrinter printer = new PrinterAdapter(new OldPrinter());
printer.Print("資料");   // 旧式印刷: 資料

// Bridge: 「図形(抽象)」と「描画方法(実装)」を分離して独立に組み合わせる
var redCircle = new Circle(new RedRenderer());
redCircle.Draw();   // 赤で 円 を描画

interface IPrinter { void Print(string doc); }
class OldPrinter { public void PrintOldStyle(string s) => Console.WriteLine($"旧式印刷: {s}"); }
class PrinterAdapter : IPrinter
{
    private readonly OldPrinter _old;
    public PrinterAdapter(OldPrinter old) => _old = old;
    public void Print(string doc) => _old.PrintOldStyle(doc);   // 変換して委譲
}

interface IRenderer { string Color(); }
class RedRenderer : IRenderer { public string Color() => "赤"; }
class Circle
{
    private readonly IRenderer _renderer;   // 実装への「橋」
    public Circle(IRenderer renderer) => _renderer = renderer;
    public void Draw() => Console.WriteLine($"{_renderer.Color()}で 円 を描画");
}
  • Adapter: 既存クラスを望むインターフェースに「変換」して再利用する
  • Bridge: 抽象(図形)と実装(描画方法)を分け、両方を独立に拡張できる
  • どちらも「継承より委譲(has-a)」で柔軟性を得る

演習

ITemperature t = new CelsiusAdapter(new FahrenheitSensor());
Console.WriteLine(t.Celsius());   // 25

// TODO: 華氏で返す FahrenheitSensor を、摂氏で返す ITemperature に変換する
//       CelsiusAdapter を定義してください(摂氏 = (華氏 - 32) * 5 / 9、77°F→25℃)
interface ITemperature { int Celsius(); }
class FahrenheitSensor { public int Fahrenheit() => 77; }
___
  • 期待される出力: 25
ヒント1を見る

class CelsiusAdapter : ITemperature { private readonly FahrenheitSensor _s; public CelsiusAdapter(FahrenheitSensor s) => _s = s; public int Celsius() => (_s.Fahrenheit() - 32) * 5 / 9; }

ヒント2を見る

アダプタ内で華氏を摂氏に変換して返します

まとめ

  • Adapterは既存クラスを望む形に変換する変換プラグ
  • Bridgeは抽象と実装を分離し独立に拡張する
  • 継承ではなく委譲で組み合わせる

次回: 入れ子と機能追加のCompositeDecoratorです。

実際に動かしてみよう

本文のサンプルや演習のコードは、コードブロック右上の「コピー」ボタンでコピーして、下のエディタに貼り付ければそのまま実行できます。

C# — ブラウザ内で実行

ブラウザ内でC#を動かす環境を読み込みます(初回のみ数秒)。
スクロールして表示された時点でも自動で読み込まれます。