はじめに
本投稿はJava言語で学ぶデザインパターン入門のデザインパターンをまとめた記事です。今回はSingletonパターンになります。
まとめ一覧はこちら
Adapterパターン
Adapterとは
Adapterとは適合するという意味で、Wrapperパターンと呼ばれることもあります。
「すでに提供されているもの」を「利用できるもの」にするためのデザインパターンで、本書ではAC電源とノートパソコンの間のACアダプターを例として説明されています。
利用場面として以下が考えられます
- 関連性のないクラス通しを既存のクラスを変えずに関連付けする場合
- 既存のクラスをある新しいインターフェイスを通じて再利用したい場合
- 既存のクラス・インターフェイスをアプリケーション固有なものに(使いやすく)したい場合
Adapterパターンのクラス図
- 利用する側はAdapterを生成し、Target[インタフェースまたは抽象クラス]を利用する
- Adapterは継承または委譲を使ってAdapteeを利用する
具体例
今回はプロパティをストリームから読み書きするjava.util.Properties
クラスをAdapterパターンを使ってFilePropertiesクラスを作っていきます
- Target: FileIoインタフェース
- Adapter: FilePropertiesクラス
- Adaptee:
java.util.Properties
クラス
java.util.Properties
クラスは以下のメソッドが利用できます
- `void load(InputStream in) throws IOException`
- プロパティの集合をInputStreamから読み込む
- `void store(OutputStream out, String header) throws IOException`
- プロパティの集合をOutputStreamから書き込む(header: コメント文字列)
Mainクラス
以下のようにfile.txt
にプロパティを書き込んでnewfile.txt
で保存処理をしていきたいと思います
public static void main(String[] args) {
FileIo fileIo = new FileProperties();//※
try {
fileIo.readFromFile("file.txt");
fileIo.setValue("Apple", "iPhone");
fileIo.setValue("Google", "Android");
fileIo.setValue("Git", "Hub");
fileIo.setValue("DesignPattern", "Adapter");
fileIo.writeToFile("newfile.txt");
} catch (IOException e) {
e.printStackTrace();
}
}
※ fileIoインターフェイスのメソッドを用いることを強調するために、FileIo
型の変数に代入している
Target
- 基本的な読み書きの処理を宣言
import java.io.*;
public interface FileIo {
public void readFromFile(String filename) throws IOException;
public void writeToFile(String filename) throws IOException;
public void setValue(String key, String value);
public String getValue(String key);
}
Adapter
- FileIoインタフェースを実装
import java.util.*;
import java.io.*;
public class FileProperties extends Properties implements FileIo {
public void readFromFile(String filename) throws IOException {
load(new FileInputStream(filename));
}
public void writeToFile(String filename) throws IOException {
store(new FileOutputStream(filename), "Written by FileProperties");
}
public void setValue(String key, String value) {
setProperty(key, value);
}
public String getValue(String key) {
return getProperty(key, "");
}
}
実行結果
実行前
Apple=iPod
実行後
#Written by FileProperties
#Sun Feb 07 20:49:50 JST 2016
DesignPattern=Adapter
Apple=iPhone
Git=Hub
Google=Android
実行してみると、テキストが書き換えられているのがわかるかと思います
追記
- 既存のクラスを書き換えずにAdapterパターンを利用することのメリット
- 既存のクラス(Adaptee)をもう一度テストする必要がなくなる
- Adapterパターンによってバグが発生しても、既存のクラス(Adaptee)にバグがないことが保証される
- Adaptee役とTargetの機能がかけ離れてる場合は、Adapterパターンは非推奨
- Targetをクラスすることで、委譲を利用したAdapterパターンも可能(AdapterでAdapteeのインスタンスを保持)
サンプルコードについて
以下のレポジトリにソースコードをアップしてあります。
shoheiyokoyama/design-pattern_java
デザインパターン
- 生成に関するパターン
- Abstract factory
- Builder
- Factory Method
- Prototype
- Singleton
- 構造に関するパターン
- Adapter
- Bridge
- Composite
- Decorator
- Facade
- Flyweight
- Proxy
- 振る舞いに関するパターン
- Chain of responsibility
- Command
- Interpreter
- Iterator
- Mediator
- Memento
- Observer
- State
- Strategy
- Template Method
- Visitor