新人SEの学習記録

14年度入社SEの学習記録用に始めたブログです。気づけば社会人3年目に突入。

学習記録:デザインパターン

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

内容:第4章 FactoryMethodパターン

概要
サンプルプログラム
package 名前 内容
chap4.framework Product 抽象メソッドuseを定義する抽象クラス
chap4.framework Factory 抽象メソッドcreateProduct, registerProductとメソッドcreateを定義する抽象クラス
chap4.passport IDCard Productを拡張したクラス。メソッドuseを実装
chap4.passport IDCardFactory Factoryを拡張したクラス。create/registerProductを実装
chap4 Main テスト用クラス
  • Product
    • 製品を表現した抽象クラス。抽象メソッドuseのみ宣言。
    • 製品とは「何はともあれuseできるもの」と表現していることになる。
package chap4.framework;

public abstract class Product {
	public abstract void use();
}
  • Factory
    • TemplateMethodパターンを使用
    • 「製品を作って登録する」というcreateメソッドを実装
    • 製品を作る、登録するという実装はサブクラスにまかせている
package chap4.framework;

public abstract class Factroty {
	public final Product create(String name) {
		Product p = createProduct(name);
		registerProduct(p);
		return p;
	}
	
	protected abstract Product createProduct(String name);
	protected abstract void registerProduct(Product product);
}
  • Passport
    • Productを拡張、パスポートを表す
    • 所有者の名前を持つ。
package chap4.passport;

import chap4.framework.Product;

public class Passport extends Product {
	private String name;
	Passport(String name) {
		System.out.println("create Passport of " + name);
		this.name = name;
	}

	@Override
	public void use() {
		System.out.println("use Passport of " + name);
	}
	
	public String getName() {
		return name;
	}
}
  • PassportFactory
    • Factoryを拡張し、パスポートを生成する。
    • 生成と登録の実装を行う
package chap4.passport;

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

import chap4.framework.Factroty;
import chap4.framework.Product;

public class PassportFactory extends Factroty {
	private List<String> nameList = new ArrayList<String>();
	@Override
	protected Product createProduct(String name) {
		return new Passport(name);
	}

	@Override
	protected void registerProduct(Product product) {
		nameList.add(((Passport)product).getName());
	}
	
	public List<String> getNameList() {
		return Collections.unmodifiableList(nameList);
	}
}
  • Main
package chap4;

import chap4.framework.Factroty;
import chap4.framework.Product;
import chap4.passport.PassportFactory;

public class Main {

	public static void main(String[] args) {
		Factroty factory = new PassportFactory();
		Product p1 = factory.create("hoge1");
		Product p2 = factory.create("hoge2");
		
		p1.use();
		p2.use();
	}

}
create Passport of hoge1
create Passport of hoge2
use Passport of hoge1
use Passport of hoge2
登場人物
  • Product役
    • 生成されるインスタンスが持つべきインタフェースを定める抽象クラス。
  • Creator役
    • Product役を生成する抽象クラス。
    • 実際に生成するConcreteProduct役については何もしらない
    • Creator役が知っているのは、Product役と、その生成メソッドのみ
    • newによる実際のインスタンス生成を、インスタンス生成のメソッド呼び出しに代えている
    • =具体的なクラス名による束縛からスーパークラスを解放している
  • ConcreteProduct役
    • 具体的な製品を定めるクラス。
  • ConcreteCreator役
    • 具体的な製品を作るクラス。
まとめと補足
  • フレームワークと肉付け
    • frameworkパッケージを変更せずに、全く別の製品とその工場が作れる
    • frameworkパッケージの中では、passportパッケージをimportしていない=依存していない
  1. 抽象メソッドにする(サンプルの方法)
    • サブクラスは必ずこのメソッドを実装する必要がある。
  2. デフォルトの実装を用意
    • サブクラスで実装しなかった場合にはその実装が使われる。(実装し忘れに注意)
  3. エラーにする
    • デフォルトの実装の内容をエラーにしておくと、実行時に実装忘れがわかる
  • パターンの利用と開発者間の意思疎通
    • デザインパターンを利用すると、やっている操作の内容に比べて複雑に見える
    • 1つのクラスを読んだだけではわからず、スーパークラスに書かれた動作の骨組みを理解し、サブクラスで実装を読む必要があるため
    • 設計者の意図したデザインパターンが何であるか、うまく伝わるようにする必要がある
  • 関連しているパターン
    • TemplateMethodパターン(3章):説明済み。
    • Singletonパターン(5章):多くの場合Creator役はSingletonパターンとして作ることができる。次章で解説。
    • Compositeパターン(11章):Product役にCompositeパターンを当てはめることができる場合がある。
    • Iteratorパターン(1章):iteratorメソッドIteratorインスタンスを生成するときにFactoryMethodパターンが使用されることがある。