Adapter

あるクラスのインターフェースを、そのクラスを利用する側が求める他のインターフェースへ変換するパターン

  • インターフェースに互換性のないクラス同士を組み合わせることができる
  • ClientからはTargetインターフェースしか見えなくなり、その先にある処理の実装を気にする必要がなくなる

メリット・デメリット

メリット

  • 既存のクラス(Adapted)を修正しないので再テストが不要になる
  • 変換のためのコードをプログラムのビジネスロジックと分離できるので単一責任の原則に違反しない
  • インターフェースを介してアダプタと連携するのでオープンクローズドの原則に違反しない

デメリット

  • インターフェースやクラスが増えるので、小さなシステムなどではAdapteeを直接修正した方がいい場合もある

デザインパターンの種類

構造に関するデザインパターン

例(Mermaid)

例1

  • Client
    • あるクラスの機能を「利用する」側のクラス
  • Target
    • クライアントが必要とする機能のAPIを定義するインターフェース
  • Adaptee
    • 「利用される」側のクラス
    • クライアントクラスと互換性がない
  • Adapter
    • Targetを実装するクラス
    • Adapteeを継承する子クラス
    • TargetのAPIを実装して、Adapteeの機能をClientが利用できるようにする

この場合AdapterクラスはAdapteeクラスを継承してAdapteeクラスを隠蔽する

classDiagram
	class Client { }
	class Target {
		<<interface>>
		targetMethod1()
		targetMethod2()
	}
	class Adapter {
		targetMethod1()
		targetMethod2()
	}
	
	class Adaptee {
		methodA()
		methodB()
		methodC()
	}
	Target <-- Client
	Target <|-- Adapter
	Adaptee <|-- Adapter

例2

  • Adapterが自分のフィールドにAdapteeクラスのインスタンスを持っておきAdapteeの処理を呼び出す方法
    • この場合処理はAdapteeのインスタンスに「移譲」するという
classDiagram
	class Client {
	}
	class Target {
		<<interface>>
		targetMethod1()
		targetMethod2()
	}
	class Adapter {
		adaptee: Adaptee
		targetMethod1()
		targetMethod2()
	}
	class Adaptee {
		methodA()
		methodB()
		methodC()
	}
	Target <-- Client
	Target <|-- Adapter
	Adaptee <--o Adapter