概要
wikipediaには以下のように書かれていました。
Adapter パターンを用いると、既存のクラスに対して修正を加えることなく、インタフェースを変更することができる。
さすがWikipedia、簡潔で分かりやすいです。
仕組み自体は簡単で、意味も分かりやすいですが非常に有用なデザインパターンの一つだと思うので、是非これを機にマスターしてみてはどうでしょうか。
登場人物
名前 | 意味 |
---|---|
Adaptee | 既に用意されているメソッドを持っている役 |
Adapter | Target(目的のインターフェイス)の要件を満たすようにAdapteeを利用する役 |
Target | 必要とするインターフェイスを定義している役 |
継承を使ったパターン
Adapter
パターンには2つの手法があり、そのうちの一つが継承を使ったパターンになります。
ただ最初に言ってしまうと、こちらのやり方を用いる機会は非常に少なく、次に紹介する委譲を使ったパターンを利用することがほとんどのようです。
なぜかというと継承はクラス間に固い結びつきがあるのに対し,委譲はゆるやかな結びつきにすることができるからだと私は考えています。
class Client { private static void Main(string[] args) { Target target = new Adapter(); target.TargetMethod1(); target.TargetMethod2(); } } /// <summary> /// 既に実装されていて,テストも十分なされているようなクラス /// </summary> public class Adaptee { public void MethodA() { Console.WriteLine("Method A"); } public void MethodB() { Console.WriteLine("Method B"); } } /// <summary> /// Adapteeのインターフェイスを目的のインターフェイスへ変換するための変換装置 /// </summary> public class Adapter : Adaptee, Target { public void TargetMethod1() { // Adapteeに定義されているメソッド等を活用してTargetの要件満たすように実装 MethodA(); } public void TargetMethod2() { MethodB(); } } /// <summary> /// 目的とするインターフェイス /// </summary> public interface Target { void TargetMethod1(); void TargetMethod2(); }
委譲を使ったパターン
もう一つの手法は委譲を使ったパターンです。
class Client { private static void Main(string[] args) { Target target = new Adapter(); target.TargetMethod1(); target.TargetMethod2(); } } /// <summary> /// 既に実装されていて,テストも十分なされているようなクラス /// </summary> public class Adaptee { public void MethodA() { Console.WriteLine("Method A"); } public void MethodB() { Console.WriteLine("Method B"); } } /// <summary> /// Adapteeのインターフェイスを目的のインターフェイスへ変換するための変換装置 /// </summary> public class Adapter : Target { private Adaptee _adaptee; public Adapter() { _adaptee = new Adaptee(); } public void TargetMethod1() { // Adapteeに定義されているメソッド等を活用してTargetの要件満たすように実装 _adaptee.MethodA(); } public void TargetMethod2() { _adaptee.MethodB(); } } /// <summary> /// 目的とするインターフェイス /// </summary> public interface Target { void TargetMethod1(); void TargetMethod2(); }
クラス図ではTarget
が抽象クラスになっていますが,別にインターフェイスでもどちらでも大丈夫です。
さいごに
余談ですがGoFのデザインパターン本で用いられている「委譲」は実は誤用で,本当は転送というそうです。
qiita.com
私の記事でも委譲と書いておきながら、実は転送を指していることも多々あるので注意していただけると幸いです。(まあC#で委譲といったら、ほぼ転送を指すような気がしますが)
ではまた。