読者です 読者をやめる 読者になる 読者になる

感謝のプログラミング 10000時間

たどり着いた結果(さき)は、感謝でした。

プログラムは拡張に対しては開かれていなければならず、修正に対しては閉じていなければならない。

<スポンサーリンク>

ことば

OCP(Open/Closed Principle:開放/閉鎖原則)とは、クラスなどのプログラム単位は、拡張に対して開いて(open)いなくてはならず、
反対に修正に対しては閉じて(close)いなくてはならない、という原則です。
この原則はDRY原則が守られている場合にのみ有効です。
スティーブ・スミス(Steve Smith)
プログラマが知るべき97のこと

デザインパターンを復習する

けっこう忘れてきたので、もう一度イチから復習していく。
デザインパターンはクラスの再利用化を促進するもの。
再利用化を促進するとは、クラスを部品として使えるようにするということであり、1つの部品を修正しても他の部品の修正が少なくてすむ、ということ。

具体的なクラスだけでプログラミングするのではなく、抽象クラスやインターフェースを使ってプログラミングすること。
具体的なクラスだけ使うと、クラス間の結合が強くなってしまい、部品として再利用しづらくなる。

デザインパターンの目標の1つはプログラムを再利用可能にすること。
プログラムは「完成品」として見るのではなく、今後「機能を拡張していくもの」「変更を加えていくもの」として見るようにする。
実際現場では、一度作ったものはけっこう長く使われて、ちょこちょこと変更が要求される。

Iteratorパターン

Iteratorは反復子とも呼ばれる。iterate「何かを繰り返す」という意味。配列の要素を数え上げるデザインパターン
実装と切り離して数え上げができる。

Iteratorパターンの全体図

Iteratorパターンを使ってみる
・全体図はこんな感じ。

Iteratorインターフェース

package pattern.iterator;

public interface Iterator {
	public abstract boolean hasNext();
	public abstract Object next();
}

・Aggregateインターフェース

package pattern.iterator;

public interface Aggregate {
	public abstract Iterator iterator();
}

・ペンを表すクラス

package pattern.iterator;

public class Pen {
	private String name;
	public Pen(String name) {
		this.name = name;
	}
	public String getName() {
		return name;
	}
}

・ペンの集合体を表すペンケースクラス

package pattern.iterator;

import java.util.ArrayList;
import java.util.List;

public class PenCase implements Aggregate{
	private List pens;
	//インスタンス化するときに、ペンの収容数を指定する
	public PenCase() {
		this.pens = new ArrayList();
	}
	public void appendPen(Pen pen) {
		pens.add(pen);
	}
	public Pen getPenAt(int index) {
		return (Pen) pens.get(index);
	}
	
	public int getSize() {
		return pens.size();
	}
	
	public Iterator iterator() {
		return new PenCaseIterator(this);
	}
}

・ペンケースの中を数え上げるIterator

package pattern.iterator;

public class PenCaseIterator implements Iterator {
	private PenCase penCase;
	private int index;
	public PenCaseIterator(PenCase penCase) {
		this.penCase = penCase;
		this.index = 0;
	}
	public boolean hasNext() {
		if (index < penCase.getSize()) {
			return true;
		} else {
			return false;
		}
	}
	public Object next() {
		Pen pen = penCase.getPenAt(index);
		index++;
		return pen;
	}

}

・それで、ペンの中身を数え上げてみる

package pattern.iterator;

public class Main {
	public static void main(String[] args) {
		PenCase penCase = new PenCase();
		penCase.appendPen(new Pen("シャープペン"));
		penCase.appendPen(new Pen("ボールペン"));
		penCase.appendPen(new Pen("ロケットペン"));
		penCase.appendPen(new Pen("消せるペン"));
		penCase.appendPen(new Pen("俺の名はルペン"));
		
		Iterator it = penCase.iterator();
		while (it.hasNext()) {
			Pen pen = (Pen)it.next();
			System.out.println(pen.getName());
		}
		
		Iterator it2 = penCase.iterator();
		while (it2.hasNext()) {
			Pen pen2 = (Pen)it2.next();
			if ("俺の名はルペン".equals(pen2.getName())) {
				System.out.println(pen2.getName() + "よ、お前はペンじゃない");
			}
		}
	}
}

Iteratorを使うことによって、

while(it.hasNext()) {
	//〜
}

この部分にpenCaseが全く入らずにロジックを組むことができる。
つまり、数え上げの部分がpenCaseの実装に依存しなくなり、
「おいpenCase、数え上げるIteratorよこせ!」
と、

Iterator it = penCase.iterator();

とやってIteratorをもらえば、あとは数え上げのロジックをpenCaseとは別途に実装できることになる。

勉強した本

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

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

感謝のプログラミング

今回で感謝のプログラミングは【220時間目】
10000時間まで、あと【9780時間】