OSSのデザインパターン解説シリーズ:Adapter(Wrapper)パターンの活用と悪いコード例
1. はじめに
このシリーズでは、オープンソースソフトウェア(OSS)のソースコードを通じて、GoF(Gang of Four)デザインパターンの活用方法を解説します。
特に悪い例と良い例を見ることで、デザインパターンのメリットを考えていきます。
なお、OSSやデザインパターンの詳しい解説は書きません。
最小限のコード例と解説を書いていきます。
2. Adapterパターンとは
Adapterパターンとは、既にある機能を別の場所/用途/インターフェースでも使えるようにするパターンです。
既存のコードを別のコードに適用するので、Adapterパターンと言います。
実装では、既存のクラスを包む(Wrapperする)ようなコードになるので、Wrapperパターンとも呼ばれています。
今回は、Javaの以下のクラスを例に考えていきます:
- HashMap
- HashSet
3. 悪いコードの例
以下は、Adapterパターンを使用せずに書かれたJavaのコードの例です。
以下は、HashMapとHashSetの実装の一部です。説明のために、省略/変更しています。
※例えば、実際にはnullチェックやハッシュ値の衝突等を考える必要があります。
public class HashMap<K,V> implements Map<K,V> {
Node<K,V>[] table;
public V put(K key, V value){
int n = table.length;
int hash = hash(key);
table[ hash % n ] = new Node(hash, key, value);
return null;
}
//その他のメソッド
static class Node<K,V> implements Map.Entry<K,V> {
final int hash;
final K key;
V value;
//実装
}
}
public class HashSet<E> implements Set<E> {
Node<E>[] table;
public boolean add(E e) {
int n = table.length;
int hash = hash(key);
table[ hash % n ] = new Node(hash, e);
return null;
}
//その他のメソッド
static class Node<E> {
final int hash;
E element;
//実装
}
}
このコードを比べると、共通部分が多そうです。
特にハッシュの計算や値の格納方法が似ています。
共通処理をまとめる方法としてユーティリティクラスが思いつきますが、今回の例ではAdapterパターンが適用できます。
4. デザインパターンの適用
以下は、Adapterパターンの実装例です。公式のJavaのソースコードも同じ構造になっています。
今回の場合は、HashMapをHashSetに適用(Adapter)しています。
HashMapの実装はそのままですが、HashSetのコードがかなりシンプルになっています。
public class HashMap<K,V> implements Map<K,V> {
Node<K,V>[] table;
public V put(K key, V value){
int n = table.length;
int hash = hash(key);
table[ hash % n ] = new Node(hash, key, value);
return null;
}
//その他のメソッド
static class Node<K,V> implements Map.Entry<K,V> {
final int hash;
final K key;
V value;
//実装
}
}
public class HashSet<E> implements Set<E> {
HashMap<E,Object> map;
static final Object PRESENT = new Object();//mapに格納するダミーの値
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
//その他のメソッド
}
5. 改善されたコードの比較
Adapterパターンを適用することで、HashMapとHashSetに散らばっていた共通処理をまとめることができました。これにより、保守性が上がりそうですね。
また、HashSetの実装はHashMapを利用するだけなので、簡単なコードになりました。
6. まとめ
今回はAdapterパターンを利用する/しない場合のコードを基に、Adapterパターンのメリットを考えました。
このデザインパターンは「実装がシンプルになり、保守性が上がることがメリット」と考えられますね。
7. 参考文献
- Java言語で学ぶデザインパターン入門第3版 結城 浩 SBクリエイティブ
- JDKソースコード
3. JDK HashMap
3. JDK HashSet
Discussion