学习建造者模式前,我们来实现一个汉堡的制作流程
汉堡制作的大致流程:
首先是加入两个面包片加入肉饼加入蔬菜加热打包代码:
1 public class Builder1 { 2 public static void main(String[] args) { 3 Hamburger hamburger1 = new Hamburger("巨无霸", "吐司", "莴笋", "牛肉饼"); 4 hamburger1.setBread(); 5 hamburger1.setMeatPie(); 6 hamburger1.setVegetableLeaf(); 7 hamburger1.heating(10); 8 hamburger1.pack(); 9 }10 }11 12 class Hamburger {13 private String name;//汉堡包名字14 private String bread;//面包片15 private String vegetableLeaf;//菜叶名16 private String meatPie;//肉饼名17 18 Hamburger(String name, String bread, String vegetableLeaf, String meatPie) {19 this.name = name;20 this.bread = bread;21 this.vegetableLeaf = vegetableLeaf;22 this.meatPie = meatPie;23 }24 25 void setBread() {26 System.out.println("加入面包片:" + this.bread);27 }28 29 void setVegetableLeaf() {30 System.out.println("向汉堡加入" + this.vegetableLeaf);31 }32 33 void setMeatPie() {34 System.out.println("向汉堡加入" + this.meatPie);35 }36 37 38 void heating(int minute) {39 System.out.println("汉堡加热时间" + minute + "分钟");40 }41 42 void pack() {43 System.out.println(this.name + "汉堡加工完成,打包!");44 }45 }
运行的结果:
功能实现啦,看起来也像一个“面向对象”的程序,把汉堡抽象出来了,同时汉堡中封装他独有的方法和属性。
但是仔细看看客户端代码,我们在客户端新建了一个汉堡,然后对他进行了一系列的操作,最后完成了汉堡。
建造者模式就是将一些列操作封装起来的一种模式
但是出现了最大的问题:代码不可复用,每一次客户端需要汉堡的时候都需要加工一次不可复用的结果就可能导致每一次加工出来的汉堡都不一样,不是流水化作业比如工序的顺序颠倒了,比如多一个工序或者少一个工序,导致加工出来的汉堡都不是我们想要的汉堡,不是我们想要的对象。
让我们来看看建造者模式时怎么实现这段代码
1 public class Builder2 { 2 public static void main(String[] args) { 3 Hamburger1 hamburger1 = new KFCHamburger("鸡肉汉堡", "面包", "韭菜", "鸡肉饼"); 4 HamburgerBuilder hamburgerBuilder = new HamburgerBuilder(hamburger1); 5 hamburgerBuilder.buildHamburger(); 6 } 7 } 8 9 abstract class Hamburger1 {10 String name;11 String bread;//面包片12 String vegetableLeaf;//菜叶名13 String meatPie;//肉饼名14 private int heatingTime;//加热时间15 16 Hamburger1(String name, String bread, String vegetableLeaf, String meatPie) {17 this.name = name;18 this.bread = bread;19 this.vegetableLeaf = vegetableLeaf;20 this.meatPie = meatPie;21 this.heatingTime = 0;22 }23 24 abstract void setBread();25 26 abstract void setVegetableLeaf();27 28 abstract void setMeatPie();29 30 abstract void heating(int minute);31 32 abstract void pack();33 }34 35 class KFCHamburger extends Hamburger1 {36 public KFCHamburger(String name, String bread, String vegetableLeaf, String meatPie) {37 super(name, bread, vegetableLeaf, meatPie);38 }39 40 @Override41 void setBread() {42 System.out.println("加入面包片:" + this.bread);43 }44 45 @Override46 void setVegetableLeaf() {47 System.out.println("向汉堡加入" + this.vegetableLeaf);48 }49 50 @Override51 void setMeatPie() {52 System.out.println("向汉堡加入" + this.meatPie);53 }54 55 @Override56 void heating(int minute) {57 System.out.println("汉堡加热时间" + minute + "分钟");58 }59 60 @Override61 void pack() {62 System.out.println(this.name + "汉堡加工完成,打包!");63 }64 }65 66 class HamburgerBuilder {67 private Hamburger1 hamburger1;68 69 HamburgerBuilder(Hamburger1 hamburger1) {70 this.hamburger1 = hamburger1;71 }72 73 Hamburger1 buildHamburger() {74 hamburger1.setBread();75 hamburger1.setMeatPie();76 hamburger1.setVegetableLeaf();77 hamburger1.heating(10);78 hamburger1.pack();79 return this.hamburger1;80 }81 }
UML图
建造者模式UML
product:我们需要的产品对象
Builder:对产品对象的加工方法
Director:封装生产对象的过程,返回一个加工好的对象。
(类似于工厂模式,将对象的生产过程封装起来,只返回一个立即可用的对象)
更正一下:应该把生成对象的方法抽象到建造类中,而不是放在对象之中,所以看起会和建造者UML的图看起来有点点不一样
我写的HamburgerBuilder其实对应的Director导演的位置,而建造者的方法我全部封装在Product中了。
有时间会修改我的代码的
分析下:
解决了代码不能复用的问题了 (可复用)同时如果我们现在要把汉堡的的加热时间修改下,或者把肉片和蔬菜放置的顺序换一下。只需要到建造类中修改时间即可。如果我们将代码写在客户端,那么维护起来就是种灾难!(可维护)如果我们现在要加入一个巨无霸汉堡,他有三层肉片,2层蔬菜,加热20分钟怎么办呢我们只需要到建造类中加入生产巨无霸汉堡的代码即可(可谓可扩展,灵活性高)1 public static void main(String[] args) { 2 Hamburger1 hamburger1 = new KFCHamburger("巨无霸", "面包", "韭菜", "鸡肉饼"); 3 HamburgerBuilder hamburgerBuilder = new HamburgerBuilder(hamburger1); 4 hamburgerBuilder.buildBigBigBigHamburger();//修改建造的方法即可 5 } 6 7 Hamburger1 buildBigBigBigHamburger() { 8 hamburger1.setBread(); 9 hamburger1.setMeatPie();//肉片110 hamburger1.setVegetableLeaf();//蔬菜111 hamburger1.setMeatPie();//肉片212 hamburger1.setVegetableLeaf();//蔬菜213 hamburger1.setMeatPie();//肉片314 hamburger1.heating(20);15 hamburger1.pack();16 return this.hamburger1;17 }
我们来看看结果吧
建造者面膜是和工厂模式同属于创建型模式(创建型模式:负责对象的创建)
什么场景下使用建造者模式1.产品对象内部具有复杂的结构,产品对象包含多个成员属性,适用建造者模式可以隔离复杂对象的创建和适用,并使得相同的 创建过程可以创建不同的对象;
2.相同的方法,不同的执行顺序,产生不同的事件结果时;(汉堡的加工顺序) 简单来说,建造者模式就是一步步创建一个对象,它对用户屏蔽了里面构建的细节(顺序,调用次数...),但却可以精细地控制对象的构造过程。
代码地址:https://gitee.com/gang_bryant/DesignMode1