新人SEの学習記録

14年度入社SEの学習記録用に始めたブログです。もう新人じゃないかも…

学習記録:デザインパターン、今後の予定

[学習記録] デザインパターン

参考書籍

増補改訂版Java言語で学ぶデザインパターン入門

増補改訂版Java言語で学ぶデザインパターン入門

内容:1章 Iteratorパターン

概要
  • 配列arrの要素を全て表示するプログラム
for (int i = 0; i < arr.length; i++) {
	System.out.println(arr[i]);
}
  • 配列は添字を増やしていくことで、arrの要素全体をスキャンできる
    • ここで使われている添字iの働きを抽象化し、一般化したものをIteratorパターンと呼ぶ
サンプルプログラム

※書籍の内容を一部変更・アレンジしてます

  • クラスとインタフェース一覧
名前 内容
Aggregate 集合体を表すインタフェース
Iterator スキャンを行うインタフェース
CD CDを表すクラス
CDRack CDラックを表すクラス
CDRackIterator CDラックをスキャンするクラス
Main 動作テスト用クラス
public interface Aggregate<T> {
	public abstract Iterator<T> iterator();
}
  • Iteratorインタフェース
    • 次の要素があるか調べるhasNext()と次の要素を得るnext()を持つ
public interface Iterator<T> {
	public abstract boolean hasNext();
	public abstract T next();
}
  • CDクラス
public class CD {
	String name;

	public CD(String name) {
		this.name = name;
	}
	
	public String getName() {
		return name;
	}
}
  • CDRackクラス
    • 集合体として扱うためAggregateインタフェースを実装
    • CDの配列(リストでもいいけど)と現在格納されているCDの数を所持
public class CDRack implements Aggregate<CD> {
	private CD[] cds;
	private int last = 0;

	public CDRack(int maxSize) {
		cds = new CD[maxSize];
	}
	
	public CD getCDAt(int index) {
		return cds[index];
	}
	
	public void appendCD(CD cd) {
		this.cds[last++] = cd;
	}
	
	public int getLength() {
		return last;
	}
	
	@Override
	public Iterator<CD> iterator() {
		return new CDRackIterator(this);
	}
}
  • CDRackIteratorクラス
    • CDRackクラスのスキャンを行うクラス、Iteratorインタフェースを実装
    • スキャンするCDRackと、現在の添字を保持
public class CDRackIterator implements Iterator<CD> {
	private CDRack cdRack;
	private int index;
	
	public CDRackIterator(CDRack cdRack) {
		this.cdRack = cdRack;
		this.index = 0;
	}

	@Override
	public boolean hasNext() {
		return (index < cdRack.getLength());
	}

	@Override
	public CD next() {
		return cdRack.getCDAt(index++);
	}
}
  • Mainクラス
    • 出力はhoge1, hoge2, hoge3と出る
public class Main {

	public static void main(String[] args) {
		CDRack cdRack = new CDRack(3);
		cdRack.appendCD(new CD("hoge1"));
		cdRack.appendCD(new CD("hoge2"));
		cdRack.appendCD(new CD("hoge3"));

		Iterator<CD> it = cdRack.iterator();
		
		while (it.hasNext()) {
			System.out.println(it.next().getName());
		}
	}
}
Iteratorパターンの登場人物
  • Iterator
    • 要素を順にスキャンしていくインタフェース(API)を定める役。
  • ConcreteIterator
    • Iterator役が定めたAPIを実際に実装する役。サンプルのCDRackIteratorにあたる。
    • スキャンするために必要な情報を保持する必要。サンプルではCDRackのインスタンスと添字。
  • Aggregate
    • Iterator役を作り出すインタフェース(API)を定める役。
    • APIは「私が持っている要素を順番にスキャンしてくれる人」を作り出すメソッドということになる。
  • ConcreteAggregate
    • Aggregate役が定めたAPIを実際に実装する役。
    • ConcreteIterator役のインスタンスを生成する。
補足
  • 配列をfor文で回せばいいんじゃない?
    • Iteratorを使うことで、Mainの実装(while文の部分)がCDRackの実装に依存しない
    • 例えば、CDRackの実装でCDの配列をリストに変えてもOK
    • ただし、CDRackの実装をがらりと変えた場合(getCDAtメソッドを削除するなど)、CDRackIteratorの修正は必要
  • イテレータの種類いろいろ
    • スキャンには逆方向、順逆両方、番号指定などいろいろなバリエーションがある
    • 1つのConcreteAggregateに対して複数のConcreteIteratorを作ることもできる
関連パターン
  • Visitorパターン(13章)
    • Iteratorは集合体から一つずつ要素を取り出す
    • 取り出すのは、要素に対して何らかの処理をするためだが、Iteratorインタフェースではその処理までは記述しない
    • Visitorパターンは、たくさんの要素に対して同じ処理を繰り返し適用していくというもの
  • Compositeパターン(11章)
    • 再帰的な構造を持ったパターン。これにIteratorを適用するのは難しい。

[今後の予定] 今後の学習予定

  • ひとまずデザインパターン本を読み切る(昔読んだ気もするけど…)。一日1パターン。
  • 下の本も面白そうなので買ってみた。ぼちぼち読む。

関数プログラミング 珠玉のアルゴリズムデザイン

関数プログラミング 珠玉のアルゴリズムデザイン