結城浩氏著作「Java言語で学ぶデザインパターン入門」
Prototypeパターン 練習課題6-1の回答例です。
課題の概要
UnderLinePen、MessageBoxクラスのcreateClone()を共通化する。
Template Methodに変更する例
Productインターフェースを、抽象クラスに変更します。
そして、createClone()メソッドを具象メソッド化することで共通化させます。
変更前(interface)
1 2 3 4 5 6 7 8 9 |
package prototype.base; public interface Product extends Cloneable { public abstract void use(String s); public abstract Product createClone(); } |
変更後(abstract class)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
package prototype.byabstract; public abstract class Product implements Cloneable { public abstract void use(String s); public Product createClone() { Product p = null; try { p = (Product)clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return p; } } |
ProductクラスにcreateClone()を実装したため、
UnderLinePen、MessageBoxクラスのcreateClone()は削除します。
クラス図
concreteProductを作成する例
Productインターフェースはそのままにし、
新たに抽象クラス(ConcreteProduct)を作成します。
メソッドについては以下のようにします。
・use():継承先のクラス(UnderLinePen、MessageBox)で実装するため、抽象メソッドとする。
・createClone():共通化するために具象メソッドとする。
ConcreteProduct
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
package prototype.bycreateconcrete; public abstract class ConcreteProduct implements Product { @Override public abstract void use(String s); @Override public Product createClone() { Product p = null; try { p = (Product)clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return p; } } |
UnderLinePen、MessageBoxの変更
ConcreteProductを継承し、createCloneメソッドを削除します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
package prototype.bycreateconcrete; public class UnderLinePen extends ConcreteProduct { private char ulChar; public UnderLinePen(char ulChar) { this.ulChar = ulChar; } @Override public void use(String string) { int length = string.getBytes().length; System.out.println(string); System.out.print(""); for (int i = 0; i < length; i++) { System.out.print(ulChar); } System.out.println(""); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
package prototype.bycreateconcrete; public class MessageBox extends ConcreteProduct { private char decoChar; public MessageBox(char decoChar) { this.decoChar = decoChar; } @Override public void use(String string) { int length = string.getBytes().length; for (int i = 0; i < length + 4; i++) { System.out.print(decoChar); } System.out.println(""); System.out.println(decoChar + " " + string + " " + decoChar); for (int i = 0; i < length + 4; i++) { System.out.print(decoChar); } System.out.println(""); } } |
クラス図
まとめ
どちらであっても抽象クラスで処理を共通化していることがわかると思います。
抽象クラスに置き換えたケースでは単純に処理を共通化しました。
ConcreteProductを作成したケースでも処理の共通化という点では同じですが、
他のConcreteクラスを追加できるようにしてあるという点で拡張性があります。