建造者模式
定义
Separate the construction of a complex object from its representation so that the same construction process can create different representations.
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
建造者模式示意图
流程
客户想要对象实例,需要知会指挥者,给指挥者提需求。
指挥者获取到客户需求(需要创建对象实例),将需求解构,分配给相应的建造者进行建造。
建造者之间相互独立,建造各自的需求,最终组装成具体的产品。
产品就是最终的对象实例,返回给客户。
需求
现在客户需要订购东风,奔驰,宝马三种汽车各100辆。四种车的生产顺序是一样的。
客户的需求给指挥者,指挥者将这四种车分别分配给四个建造者建造。
代码实现
先通过模板方法模式创建出三种汽车实例,这里先创建汽车模板
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 27 28 29 30 31 32 33 34 35 36 37 38 public abstract class Car { private ArrayList<String> sequence = new ArrayList<>(); protected abstract void start () ; protected abstract void stop () ; protected abstract void alarm () ; protected abstract void engineBoom () ; final public void run () { for (int i=0 ; i<sequence.size() ; i++){ String name = this .sequence.get(i); if ("start" .equals(name)){ this .start(); }else if ("stop" .equalsIgnoreCase(name)){ this .stop(); }else if ("alarm" .equalsIgnoreCase(name)){ this .alarm(); }else if ("engineBoom" .equalsIgnoreCase(name)){ this .engineBoom(); } } } final public void setSequence (ArrayList<String> sequence) { this .sequence = sequence ; } }
然后通过汽车模板创建出三个以这个模板构建的功能相同的不同种类的汽车类
奔驰汽车
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public class Benz extends Car { @Override protected void start () { System.out.println("奔驰是这样启动的" ); } @Override protected void stop () { System.out.println("奔驰是这样停下来的" ); } @Override protected void alarm () { System.out.println("奔驰的喇叭声音是这样的" ); } @Override protected void engineBoom () { System.out.println("奔驰的引擎声音是这样的" ); } }
宝马汽车
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public class BMW extends Car { @Override protected void start () { System.out.println("宝马是这样启动的" ); } @Override protected void stop () { System.out.println("宝马是这样停下来的" ); } @Override protected void alarm () { System.out.println("宝马的喇叭声音是这样的" ); } @Override protected void engineBoom () { System.out.println("宝马的引擎声音是这样的" ); } }
东风汽车
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public class Dongfeng extends Car { @Override protected void start () { System.out.println("东风是这样启动的" ); } @Override protected void stop () { System.out.println("东风是这样停下来的" ); } @Override protected void alarm () { System.out.println("东风的喇叭声音是这样的" ); } @Override protected void engineBoom () { System.out.println("东风的引擎声音是这样的" ); } }
根据不同的汽车类,为它们分配不同的建造者
奔驰汽车的建造者
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public class BenzBuilder extends CarBuilder { private Benz benz = new Benz(); @Override public void setSequense (ArrayList<String> sequense) { this .benz.setSequence(sequense); } @Override public Car getCar () { return this .benz; } }
宝马汽车的建造者
1 2 3 4 5 6 7 8 9 10 11 12 public class BMWBuilder extends CarBuilder { private BMW bmw = new BMW(); @Override public void setSequense (ArrayList<String> sequense) { this .bmw.setSequence(sequense); } @Override public Car getCar () { return this .bmw; } }
东风汽车的建造者
1 2 3 4 5 6 7 8 9 10 11 12 public class DongFengBuilder extends CarBuilder { private Dongfeng dongfeng = new Dongfeng(); @Override public void setSequense (ArrayList<String> sequense) { this .dongfeng.setSequence(sequense); } @Override public Car getCar () { return this .dongfeng; } }
建造者要建造汽车,需要有总指挥分配需求,进行调度,这里需要有一个总指挥
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 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 public class Director { private ArrayList<String> sequense = new ArrayList<>(); private BenzBuilder benzBuilder = new BenzBuilder(); private BMWBuilder bmwBuilder = new BMWBuilder(); private DongFengBuilder dongFengBuilder = new DongFengBuilder(); public BMW getBMW () { this .sequense.clear(); this .sequense.add("start" ); this .sequense.add("stop" ); this .bmwBuilder.setSequense(this .sequense); return (BMW) this .bmwBuilder.getCar(); } public Benz getBenz () { this .sequense.clear(); this .sequense.add("start" ); this .sequense.add("alarm" ); this .sequense.add("stop" ); this .benzBuilder.setSequense(this .sequense); return (Benz) this .benzBuilder.getCar(); } public Dongfeng getDongFeng () { this .sequense.clear(); this .sequense.add("start" ); this .sequense.add("engineBoom" ); this .sequense.add("stop" ); this .dongFengBuilder.setSequense(this .sequense); return (Dongfeng) this .dongFengBuilder.getCar(); } }
最后,任务分配成功,开始为我们的客户建造需要的产品,场景实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 public class Test { public static void main (String[] args) { Director director = new Director(); for (int i=0 ; i<100 ; i++){ director.getBenz().run(); } for (int i=0 ; i<100 ; i++){ director.getBMW().run(); } for (int i=0 ; i<100 ; i++){ director.getDongFeng().run(); } } }
应用场景
相同的功能,不同的执行顺序,产生不同结果。
多个部件或零件,可以装配到一个对象,但产生结果又不相同。
产品类非常复杂,调用其顺序不同会产生不同结果。
在创建对象时会使用系统的其他对象,这些对象在产品创建过程中不易得到。
建造者模式的优点和注意事项
优点
建造者模式可以使客户不需要知道生产产品的细节,只需要将需求给指挥者就行了,指挥者会让建造者根据产品模型进行建造。这就使得封装性很好。
一个建造者对应一个产品类型,建造者之间是互相独立的,如果需要新增一个产品类型,只需要新增一个建造者就能扩展。这使得其扩展性很好。
由于产品对象实例是由建造者建造,我们可以对建造过程进行细化,而不对其他模块产生影响。
注意事项
建造者注重工艺顺序,与工厂模式的注重点不同。