java 设计模式之建造者模式
模式定义 :
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。。
java 建造者模式
建造者模式的核心就是为同一个对象赋予不同的属性,
问题思考:
假设有这样一个复杂对象, 在对其进行构造时需要对诸多成员变量和嵌套对象进行繁复的初始化工作。 这些初始化代码通常深藏于一个包含众多参数且让人基本看不懂的构造函数中;
问题解决:
方案【1】:最简单的方法是扩展产品基类,让不同的子类去实现不同个性化的产品类(创建一系列涵盖所有参数组合的子类)。 但最终你将面对相当数量的子类。 任何新增的参数或删除参数都会让程序结构更多复杂.
方案【2】:另一种方法则无需生成子类。 可以在产品基类中创建一个包括所有可能参数的超级构造函数, 并用它来控制产品属性。 这种方法确实可以避免生成子类, 但它却会造成另外一个问题。绝大部分的参数都没有使用(不同的实例化对象,需要不同的参数),(或是一时间还无法明确参数值), 这使得对于构造函数的调用十分不简洁。
问题解决:
建造模式将对象构造代码从产品类中抽取出来, 并将其放在一个名为建造者的独立对象中。
建造者模式与工厂模式的比较:
当我们创建一个复杂对象时,可能大家的第一反应就是使用工厂模式。但是如果构建一个对象非常复杂,而且有些比如说属性之类的是可选的,而且需要支持我们自己随意的动态搭配,那么这时候如果要用工厂设计模式就不太好实现了,所以这就需要配合我们的建造者模式来实现
1、建造者模式更加注重方法的调用顺序,工厂模式注重于创建完整对象
2、建造者模式根据不同的产品零件和顺序可以创造出不同的产品,而工厂模式创建出来的产品都是一样的
3、建造者模式使用者需要知道这个产品有哪些零件组成,而工厂模式的使用者不需要知道,直接创建就行
建造者模式的使用场景
1 >相同的方法,不同的执行顺序,产生不同的事件结果时;
2 >多个部件或零件,都可以装配到一个对象中,但是产生的运行结果又不相同时;
3 >产品类非常复杂,或者产品类中的调用顺序不同产生了不同的效能,这个时候使用建造者模式非常合适;
建造者模式优点
方便用户创建复杂的对象(不需要知道实现过程)
代码复用性&封装性(将对象构建过程和细节进行封装&复用)
建造者模式角色
建造者模式的设计中,主要有4个角色。
建造者模式角色
产品(Product):要创建的产品对象
抽象建造者(Builder):建造者的抽象类,规范产品对象的各个组成部分的建造,一般由子类实现具体建造过程
建造者(ConcreteBuilder):具体的Builder类,根据不同的业务逻辑,具体到各个对象的各个组成部分的建造
主管(Director)(可选角色):调用具体的建造者来创建各个对象的各个部分
建造者模式并不一定需要主管类。 客户端代码可直接以特定顺序调用创建步骤。 不过, 主管类中非常适合放入各种例行构造流程, 以便在程序中反复使用(将不同建造者创建产品封装成不同方法,方便客户端直接调用,可反复使用)。
此外, 对于客户端代码来说, 主管类完全隐藏了产品构造细节。 客户端只需要将一个生成器与主管类关联, 然后使用主管类来构造产品, 就能从生成器处获得构造结果了。生成
代码示例:
/** * * @author androidos.net * 产品类 */ public class Phone { public String cpu; public String screen; public String speaker; public String camera; public String battery; public String vibrater; public String getCpu() { return cpu; } public void setCpu(String cpu) { this.cpu = cpu; } public String getScreen() { return screen; } public void setScreen(String screen) { this.screen = screen; } public String getSpeaker() { return speaker; } public void setSpeaker(String speaker) { this.speaker = speaker; } public String getCamera() { return camera; } public void setCamera(String camera) { this.camera = camera; } public String getBattery() { return battery; } public void setBattery(String battery) { this.battery = battery; } public String getVibrater() { return vibrater; } public void setVibrater(String vibrater) { this.vibrater = vibrater; } }
/** * * @author androidos.net * 建造者抽象类 * */ public abstract class Builder { Phone phone = new Phone(); abstract void buildCpu(); abstract void buildScreen(); abstract void buildSpeaker(); abstract void buildCamera(); abstract void buildVibrater(); abstract Phone getCompletePhone(); }
/** * * @author androidos.net * 具体建造者类,可以由此类或是父类中关联产品类 */ public class ConcrectBuild extends Builder { @Override void buildCpu() { // TODO Auto-generated method stub phone.setCpu("组装CPU"); System.out.println("组装CPU"); } @Override void buildScreen() { // TODO Auto-generated method stub phone.setCpu("组装屏幕"); System.out.println("组装屏幕"); } @Override void buildSpeaker() { // TODO Auto-generated method stub phone.setCpu("组装喇叭"); System.out.println("组装喇叭"); } @Override void buildCamera() { // TODO Auto-generated method stub phone.setCpu("组装摄像头"); System.out.println("组装摄像头"); } @Override void buildVibrater() { // TODO Auto-generated method stub phone.setCpu("组装电池"); System.out.println("组装电池"); } @Override public Phone getCompletePhone() { // TODO Auto-generated method stub System.out.println("组装完成"); return phone; } }
/** * * @author androidos.net * 主管类,此类并不直接与产品类交互 * 只负责产品类的构建,并由具体建造者类返回具体产品 * 此类是可选的,可有可无,作用是封装构造流程,可反复使用 */ public class Director { Builder builder; public void setBuilder(Builder builder) { this.builder = builder; } public Phone buildPhone1() { builder.buildCpu(); builder.buildCamera(); builder.buildSpeaker(); return builder.getCompletePhone(); } public Phone buildPhone2() { builder.buildVibrater(); builder.buildCamera(); builder.buildScreen(); return builder.getCompletePhone(); } }
客户端测试类 public class Client { public static void main(String[] args) { Builder builder = new ConcrectBuild(); Director director = new Director(); director.setBuilder(builder); Phone phone = director.buildPhone1(); //---- System.out.println("---------------组装第二台-----------------"); Phone phone2 = director.buildPhone2(); } }
程序打印:
方式二:
一般情况下,我们更习惯使用静态内部类的方式实现建造者模式,即一个产品类内部自动带有一个具体建造者,由它负责该产品的组装创建,不再需要Builder和Director,这样,产品表示与创建之间的联系更加紧密,结构更加紧凑,同时使得建造者模式的形式更加简洁。如果采用静态内部类形式实现建造者模式,则前面的案例可以改写如下。
/** * * @author androidos.net * 产品类 */ public class Phone { //此时 可以将所有的属性与行为都隐藏起来,public改为private private String cpu; private String screen; private String speaker; private String camera; private String battery; private String vibrater; private String getCpu() { return cpu; } private void setCpu(String cpu) { this.cpu = cpu; } private String getScreen() { return screen; } private void setScreen(String screen) { this.screen = screen; } private String getSpeaker() { return speaker; } private void setSpeaker(String speaker) { this.speaker = speaker; } private String getCamera() { return camera; } private void setCamera(String camera) { this.camera = camera; } private String getBattery() { return battery; } private void setBattery(String battery) { this.battery = battery; } private String getVibrater() { return vibrater; } private void setVibrater(String vibrater) { this.vibrater = vibrater; } public static class Builde{ Phone phone = new Phone(); public Builde addPhoneCpu(String cpu) { phone.setCpu(cpu); System.out.println("组装cpu"); return this; } public Builde addPhoneScreen(String screen) { phone.setScreen(screen); System.out.println("组装screen"); return this; } public Builde addPhoneSpeaker(String speaker) { phone.setSpeaker(speaker); System.out.println("组装speaker"); return this; } public Builde addPhoneCamera(String camera) { phone.setCamera(camera); System.out.println("组装camera"); return this; } public Builde addPhoneBattery(String battery) { phone.setBattery(battery); System.out.println("组装battery"); return this; } public Builde addPhoneVibrator(String vibrator) { phone.setVibrater(vibrator); System.out.println("组装vibrator"); return this; } public Phone buildPhone() { System.out.println("组装完成"); return phone; } } }
public class Client { public static void main(String[] args) { //方式二 Phone.Builde builder =new Phone.Builde().addPhoneBattery(null) .addPhoneScreen(null) .addPhoneSpeaker(null) .addPhoneCamera(null) .addPhoneVibrator(null); Phone phone = builder.buildPhone(); } }
程序打印:
评论