1 概要
ビルダー パターン (Builder Pattern) は、主に「複雑なオブジェクトをステップバイステップで構築する」ために使用されます。「ステップバイステップ」は安定したアルゴリズムですが、複雑なオブジェクトのさまざまな部分は頻繁に変更されます。したがって、ビルダーパターンは主に「オブジェクト部分」の変化する要件を解決するために使用されます。 これにより、オブジェクト構築プロセスをよりきめ細かく制御できるようになります。
2 例
携帯電話の製造を例に挙げます。各携帯電話は画面、CPU、バッテリーに分かれています。現在、Apple と Samsung の 2 種類の携帯電話が生産されています。
アップル:
りーサムスン:
えーテストクライアント:
package org.scott.builder.before.use; import java.util.ArrayList; import java.util.List; /** * @author Scott * @version 2013-11-20 * @description */ public class ApplePhone { List<String> parts = new ArrayList<String>(); public void createCPU() { parts.add("CUP: Qualcomm"); } public void createScreen() { parts.add("SCREEN: JDI"); } public void createBattery() { parts.add("BATTERY: DeSai"); } public void show(){ System.out.print("产品部件信息:"); for(String part : parts){ System.out.print(part + "\t"); } } }
問題は見つかりましたか?つまり、携帯電話を製造するすべてのプロセスは同じです。プロセスの名前は同じですが、各プロセスの具体的なプロセスは変わりません。各工程の処理が変化する中から、「あらゆる変化に対応できる変わらないもの」を抽出し、変化するものを特定の製品に引き継ぐことができます。
具体的にはどうすればいいですか?今回はビルダーモードが便利です。
まず、電話のインターフェイスを見てみましょう:
package org.scott.builder.before.use; import java.util.ArrayList; import java.util.List; /** * @author Scott * @version 2013-11-20 * @description */ public class SamsungPhone { List<String> parts = new ArrayList<String>(); public void createCPU() { parts.add("CUP: MTK"); } public void createScreen() { parts.add("SCREEN: Samsung"); } public void createBattery() { parts.add("BATTERY: DeSai"); } public void show(){ System.out.print("产品部件信息:"); for(String part : parts){ System.out.print(part + "\t"); } } }
Apple 携帯電話カテゴリ:
package org.scott.builder.before.use; /** * @author Scott * @version 2013-11-20 * @description */ public class BuilerTest { private static ApplePhone iphone = new ApplePhone(); private static SamsungPhone samPhone = new SamsungPhone(); public static void main(String args[]){ iphone.createCPU(); iphone.createScreen(); iphone.createBattery(); iphone.show(); samPhone.createCPU(); samPhone.createScreen(); samPhone.createBattery(); samPhone.show(); } }
Samsung 携帯電話カテゴリ:
package org.scott.builder.after.use; import java.util.ArrayList; import java.util.List; /** * @author Scott * @version 2013-11-20 * @description */ public abstract class Phone { protected List<String> parts = new ArrayList<String>(); public void add(String part){ parts.add(part); } public void show(){ System.out.print("产品部件信息:"); for(String part : parts){ System.out.print(part + "\t"); } } }
次に、実稼働ステップのインターフェース Builder を定義します:
package org.scott.builder.after.use; /** * @author Scott * @version 2013-11-20 * @description */ public class ApplePhone extends Phone{ }
iPhone 用ビルダー:
package org.scott.builder.after.use; /** * @author Scott * @version 2013-11-20 * @description */ public class SamsungPhone extends Phone{ }
Samsung 携帯電話用ビルダー:
package org.scott.builder.after.use; /** * @author Scott * @version 2013-11-20 * @description */ public interface Builder { public void buildCPU(); public void buildScreen(); public void buildBattery(); public Phone getPhone(); }
携帯電話の具体的な制作を指導するディレクター:
package org.scott.builder.after.use; /** * @author Scott * @version 2013-11-20 * @description */ public class ApplePhoneBuilder implements Builder{ private Phone phone = new ApplePhone(); @Override public void buildCPU() { phone.add("CUP: Qualcomm"); } @Override public void buildScreen() { phone.add("SCREEN: JDI"); } @Override public void buildBattery() { phone.add("BATTERY: DeSai"); } @Override public Phone getPhone() { return phone; } }
最後にテストクラスを作成します:
package org.scott.builder.after.use; /** * @author Scott * @version 2013-11-20 * @description */ public class SamsungPhoneBuilder implements Builder{ private Phone phone = new SamsungPhone(); @Override public void buildCPU() { phone.add("CUP: MTK"); } @Override public void buildScreen() { phone.add("SCREEN: Samsung"); } @Override public void buildBattery() { phone.add("BATTERY: DeSai"); } @Override public Phone getPhone() { return phone; } }
実行結果:
package org.scott.builder.after.use; /** * @author Scott * @version 2013-11-20 * @description */ public class Director { private Builder builder; public Director(Builder builder){ this.builder = builder; } public void construct(){ builder.buildCPU(); builder.buildScreen(); builder.buildBattery(); } }
この場合、これらの 2 つの Phone エンティティ クラスは空になります。Phone インターフェイスも省略できる場合は、最終的には Director、Builder、および特定の Bulider 実装クラスのみが残ります。さらに、ApplePhone クラスと SamsungPhone クラスは、異なる携帯電話ブランドであるため、あまり関連性のないクラスが 2 つ以上ある場合は、現時点ではパブリック インターフェイス Phone が存在する必要はありません。 , では、Builder インターフェイスで指定された getPhone() メソッドの戻り値を確認するにはどうすればよいでしょうか。
戻り値の型が ApplePhone か SamsungPhone かに関係なく、返される結果の型が統一されていないため、問題が発生します。このとき、Phone を空のインターフェイス (メソッドを含まないインターフェイス) として定義し、相互に関係のないこれらの特定の製品クラスにこのインターフェイスを実装させることができます。その後、 getPhone(. ) Builder インターフェイスで指定されたメソッド これはまだ Phone タイプであるため、問題は解決されます。ただし、この場合、ビルダー モードを使用する必要はありません。
Java デザイン パターンのビルダー パターンの学習に関連するその他の記事については、PHP 中国語 Web サイトに注目してください。