こんにちは。サイオステクノロジーの川田です。
今回はAdapterパターンについて調べてみました。
参考☞「増補改訂版Java言語で学ぶデザインパターン入門」
Adapterとは
「Adapt」とは適応させるという意味です。
適応させると言葉で言われてもパッとしません。
よく例に出てくるのがACアダプタです。簡単に言うとズバリ仲介人です。
ACアダプタはコンセントからくる電気をパソコンで使える電気に変換する役割をしてくれます。
クラス図で考える
先ほどはACアダプタを使って例えてみました。
ではプログラミングではどのように考えるのかクラス図で見てみます。
Target :必要とされるメソッド
Adapter:Adapteeのメソッドを使ってTargetの役割を満たすためのクラス
Adaptee:すでに用意されているメソッドを持っているクラス
AdapterとなるPrintHumanクラスはHumanクラスを継承(extends)し、Printインターフェースを実装(implements)しています。
実装してみる
Adapteeの部分です。
- Human.java
public class Human { private String name; private int birthday; public Human(String name, int birthday){ this.name = name; this.birthday = birthday; } public void showName(){ System.out.println(name); } public void showBirthday(){ System.out.println(birthday); } }
Targetで必要とされているメソッドを定めています。
- Print.java
public interface Print { public abstract void printName(); public abstract void printAge(); }
本日の主役、Adapterの役割です。
HumanクラスをextendsしてshowNameとshowBirthdayメソッドを継承しています。
Printインターフェースをimplementsし、printNameとprintBirthdayを実装しています。
- PrintHuman.java
public class PrintHuman extends Human implements Print{ public PrintHuman(String name, int birthday){ super(name, birthday); } public void printName(){ showName(); } public void printBirthday(){ showBirthday(); } }
これらのクラスやインターフェースを利用するmainメソッドは以下の通りです。
- Main.java
public class Main { public static void main(String[] agrs){ Print p = new PrintHuman("taro", 19990101); p.printName(); p.printBirthday(); } }
実行結果はこちらです。
taro 19990101
MainクラスはPrintインターフェースのprintNameとprintBirthdayメソッドを使っています。
Adapterがどんな実装になっているかなんてMainクラスは知らないのです!
既に提供されているもの、それがHumanクラスだとします。
PrintHumanクラスはHumanクラスの実装を利用できるように変換する役割を担ってくれました。
委譲
先ほどのは継承を使ったAdapterパターンでした。
実はもう一つ、委譲を使ったAdapterパターンもあります。
委譲とは他にゆだね、ゆずるという意味になります。
今回の委譲の表現は「あるメソッドの処理を他のクラスのインスタンスにお任せする」という考えになります。
クラス図(委譲)
右上は先ほど出てきた「継承を使った」クラス図です。
比べてみると赤丸の部分が変わっていることがわかりますね。
実装で確認してみましょう!
実装してみる
Print.javaとPrintHuman.javaを修正します。
- Print.java
public abstract class Print { public abstract void printName(); public abstract void printBirthday(); }
Printはインターフェースではなく、クラスに修正します。
- PrintHuman.java
public class PrintHuman extends Print{ private Human human; public PrintHuman(String name, int age){ human = new Human(name, age); } public void printName(){ human.showName(); } public void printAge(){ human.showBirthday(); } }
1行目ではPrintをextendsしています。
そして2行目でHumanクラスのインスタンスを保持しています。
showNameとshowBirthdayの呼び出し方がhumanフィールドを経由して呼び出していることがわかりますね!
printNameやprintBirthdayメソッドが呼ばれたらHumanクラスのインスタンスにお任せしているということです。
実行結果は変わりません。
taro 19990101
まとめ
今回はAdapterパターンの継承と委譲について学びました。
既存のソースをいじらずに修正ができればテストの手間も省けますね!