Index
以下の書籍を参考に本記事を書きました。
参考書では以下のように説明されています。
インスタンスの作り方をスーパークラスの側で定めますが、具体的なクラス名まではありません。
これによって、インスタンス生成のための枠組みと、実際のインスタンス生成のクラスを分けて考えることができます。
- 具体的なクラス名による束縛からスーパークラスを解放できる
詳細はサンプルプログラムを見た後に解説します。
クラス図は以下の通り
1 2 3 4 5 6 7 8 9 10 11 12 |
package framework; public abstract class Factory { public final Product create(final String maker) { final Product product = createProduct(maker); registerProduct(product); return product; } protected abstract Product createProduct(final String owner); protected abstract void registerProduct(final Product product); } |
このクラスでインスタンス生成の枠組みを定義します。
Facoryクラスは抽象クラスなので、コンストラクタはありません。
またこのクラスではtempalteMethodパターンが使われています。
templateMethodパターンの詳細は以下の記事を参照してください。
TemplateMethodパターン@Java言語で学ぶデザインパターン入門
1 2 3 4 5 |
package framework; public abstract class Product { public abstract void use(); } |
Factoryクラスによって作られる製品を表現したクラスです。
抽象メソッドuse()のみが定義されています。
具体的な処理はサブクラスにお任せします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
package television; import framework.Product; public class Television extends Product { private final String maker; private final int serialNum; Television(final String maker, final int serialNum) { System.out.println(maker); this.maker = maker; this.serialNum = serialNum; } @Override public void use() { System.out.println(this + "のテレビの電源をつけます。"); } @Override public String toString() { return maker; } } |
実際に作られる製品(テレビ)のクラスです。
メーカーとシリアルナンバーを変数としてもっています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
package television; import framework.Factory; import framework.Product; public class TelevisionFactory extends Factory { private int serialNum = 0; @Override protected Product createProduct(final String maker) { return new Television(maker, serialNum++); } @Override protected void registerProduct(final Product product) { System.out.println(product + "のテレビを作成しました。"); System.out.println("シリアルナンバー:" +serialNum ); } } |
実際にテレビを作成するFactoryクラスです。
コンストラクタでメーカーとシリアルナンバーを定義しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
import framework.Product; import television.TelevisionFactory; public class Main { public static void main(String[] args) { final TelevisionFactory telFactory = new TelevisionFactory(); final Product telPana = telFactory.create("panasonic"); final Product telSony = telFactory.create("sony"); telSony.use(); telPana.use(); } } |
出力は以下の通り
1 2 3 4 5 6 7 8 |
sony sonyのテレビを作成しました。 シリアルナンバー:1 panasonic panasonicのテレビを作成しました。 シリアルナンバー:2 sonyのテレビの電源をつけます。 panasonicのテレビの電源をつけます。 |
①具体的なクラス名による束縛からスーパークラスを解放できる
Mainクラスを見てみると、Televisionをnewしている箇所がありません。
全てTelevisionFactoryクラスから作られています。
MainクラスはTelevisionクラスのことを全く知りません。
これによってテレビ以外のProductを作成するのがとても簡単になります。
例えば、冷蔵庫を作りたければ、新たにpackage冷蔵庫、冷蔵庫クラス、冷蔵庫Factoryクラスを作るだけで良いです:)
javaにはFactoryMethodパターンに似たAPIがたくさん存在します。
・getInstanceメソッド
https://docs.oracle.com/javase/jp/8/docs/api/java/security/SecureRandom.html
・ofメソッド
https://docs.oracle.com/javase/jp/9/docs/api/java/util/List.html#of-E…-
などなど。。。