Factory Method ファクトリーメソッド-デザインパターンの勉強

Template Methodテンプレートメソッド-デザインパターンの勉強 - rderaログと似ています。Template Methodでは、スーパークラスで処理の流れを決めて、サブクラスで実装しました。
Factory Methodでは、スーパークラスインスタンスの作り方を決め、そのサブクラスで実際にクラス名を指定してインスタンスを作成します。

増補改訂版Java言語で学ぶデザインパターン入門からダウンロードできるサンプルプログラムは以下のようになっています。

クラス 説明
Product.java 抽象メソッドuseのみ定義されている抽象クラス
Factory.java メソッドcreateを実装している抽象クラス
IDCard.java メソッドuseを実装しているクラス
IDCardFactory.java メソッドcreateProduct,registerProductを実装しているクラス
Main.java テスト用
Product.java
  1 package framework;
  2 
  3 public abstract class Product {
  4     public abstract void use();
  5 }
Factory.java
  1 package framework;
  2 
  3 public abstract class Factory {
  4     public final Product create(String owner) {
  5         Product p = createProduct(owner);
  6         registerProduct(p);
  7         return p;
  8     }   
  9     protected abstract Product createProduct(String owner);
 10     protected abstract void registerProduct(Product product);
 11 }
IDCard.java
  1 package idcard;
  2 import framework.*;
  3 
  4 public class IDCard extends Product {
  5     private String owner;
  6     IDCard(String owner) {
  7         System.out.println(owner + "のカードを作ります。");
  8         this.owner = owner;
  9     }
 10     public void use() {
 11         System.out.println(owner + "のカードを使います。");
 12     }
 13     public String getOwner() {
 14         return owner;
 15     }
 16 }
IDCardFactory.java
  1 package idcard;
  2 import framework.*;
  3 import java.util.*;
  4 
  5 public class IDCardFactory extends Factory {
  6     private List owners = new ArrayList();
  7     protected Product createProduct(String owner) {
  8         return new IDCard(owner);
  9     }
 10     protected void registerProduct(Product product) {
 11         owners.add(((IDCard)product).getOwner());
 12     }
 13     public List getOwners() {
 14         return owners;
 15     }
 16 }
  1 import framework.*;
  2 import idcard.*;
  3 
  4 public class Main {
  5     public static void main(String[] args) {
  6         Factory factory = new IDCardFactory();
  7         Product card1 = factory.create("結城浩"); 
  8         Product card2 = factory.create("とむら");
  9         Product card3 = factory.create("佐藤花子");
 10         card1.use();
 11         card2.use();
 12         card3.use();
 13     }
 14 }

実行してみると、

$ java Main
結城浩のカードを作ります。
とむらのカードを作ります。
佐藤花子のカードを作ります。
結城浩のカードを使います。
とむらのカードを使います。
佐藤花子のカードを使います。

となる。


このサンプルプログラムでは、パッケージidcard内にクラスIDCardとクラスIDCardFactoryを作り、IDカードを作成していたが、
今度は、靴を作りたいとする。この目的を達成するためにパッケージshoes以下にクラスを作成する。

クラス 説明
Shoes.java メソッドuseを実装しているクラス
ShoesFactory.java メソッドcreateProduct,registerProductを実装しているクラス
Shoes.java
  1 package shoes;
  2 import framework.*;
  3 
  4 public class Shoes extends Product {
  5   private String owner;
  6   Shoes(String owner) {
  7     this.owner = owner;
  8   }   
  9       
 10   public void use() {
 11     System.out.println(owner +"の靴を使います。");
 12   }
 13   public String getOwner() {
 14     return owner;
 15   }
 16 }
ShoesFactory.java
  1 package shoes;
  2 import framework.*;
  3 import java.util.*;
  4 
  5 public class ShoesFactory extends Factory {
  6   private List<String> owners = new ArrayList<String>();
  7   protected Product createProduct(String owner) {
  8     return(new Shoes(owner));
  9   }   
 10   protected void registerProduct(Product product) {
 11     owners.add(((Shoes)product).getOwner());
 12   }
 13 }

Mainを書き換える。

Main.java
  1 import framework.*;
  2 //import idcard.*;
  3 import shoes.*;
  4 
  5 
  6 public class Main {
  7     public static void main(String[] args) {
  8       Factory factory = new ShoesFactory();
  9       Product shoes = factory.create("rdera");
 10       shoes.use();
 11     }
 12 } 


実行してみる。

$ java Main
rderaの靴を使います。


ここで、注目したいのがパッケージframework以下のクラスProductとクラスFactoryは一切、変更していないことである。
これ重要。
ふーん。