OSSのデザインパターン解説シリーズ:Iteratorパターンの活用と悪いコード例
1. はじめに
このシリーズでは、オープンソースソフトウェア(OSS)のソースコードを通じて、GoF(Gang of Four)デザインパターンの活用方法を解説します。
特に悪い例と良い例を見ることで、デザインパターンのメリットを考えていきます。
なお、OSSやデザインパターンの詳しい解説は書きません。
最小限のコード例と解説を書いていきます。
2. Iteratorパターンとは
Iteratorパターンとは、「"ものの集まり"の要素を全てたどること」を抽象化することです。
Javaの場合、"ものの集まり"に当たるクラスは以下が挙げられます:
- 配列
- ArrayList
- LinkedList
- HashSet
- HashMapのkeySet()やvalues()メソッド(の戻り値)
もちろん、データ構造の数だけ他にも"ものの集まり"が存在します。
Iteratorパターンでは、このデータ構造を気にせずに「要素をたどる」方法を提供してくれるパターンです。
3. 悪いコードの例
以下は、Iteratorパターンを使用せずに書かれたJavaのコードの例です。
//配列の場合
String[] strs={"one", "two", "three"};
for(int i=0; i < strs.length; i++){
System.out.println(strs[i]);
}
//Listの場合
List<String> list=new LinkedList(List.of("four", "five", "six"));
for(int i=0; i < list.size(); i++){
System.out.println(list.get(i));
}
//Setの場合
Set<String> set=new HashSet(List.of("seven", "eight", "nine"));
String[] strSet=set.toArray(new String[0]);
for(int i=0; i < strSet.length; i++){
System.out.println(strSet[i]);
}
この悪いコード例では、データ構造に依存してfor文を書き換える必要があります。
やりたい事は同じなのに、やり方が異なるのは少し不便ですね。
特に、Setは一度配列に変換しないと値を取り出すことができません。
4. デザインパターンの適用
Iteratorパターンは、Javaや他のOSSプロジェクトで広く活用されています。
以下は、Iteratorパターンの実装例です。(実装というより利用者側のコード)
//配列の場合
String[] strs={"one", "two", "three"};
for(String str: strs){
System.out.println(str);
}
//Listの場合
List<String> list=new LinkedList(List.of("four", "five", "six"));
for(String str: list){
System.out.println(str);
}
//Setの場合
Set<String> set=new HashSet(List.of("seven", "eight", "nine"));
for(String str: set){
System.out.println(str);
}
この例では、配列・List・Setに依らず、全て同じ方法で値を取り出すことができています。
拡張for構文を使用していますが、裏では共通の処理としてIteratorパターンが使われています。
5. 改善されたコードの比較
Iteratorパターンを適用することで、「"ものの集まり"から値を取り出す」操作を共通の処理で行うことができるようになりました。
これは利用者側からとても便利ですね。
6. まとめ
今回はIteratorパターンを利用する/しない場合のコードを基に、Iteratorパターンのメリットを考えました。
このデザインパターンは「利用者が使いやすくなるパターン」と考えられますね。
7. 参考文献
- Java言語で学ぶデザインパターン入門第3版 結城 浩 SBクリエイティブ
- Oracle Help Center
- paiza.io ※コード例の実行環境
Discussion