设计者模式 -- 建造者模式(builder)
建造者模式定义:
讲一个复杂对象的构造与其表示进行分离,使同样的构建过程可以创建不同的表示。其实就是将一个复杂对象分解为多个简单的对象,然后一步一步构建而成,将变与不变进行分析,也就是说产品的组成部分不变,但每一部分都可以进行灵活选择。
其优点:
- 每个具体的建造着相对独立,这样有利于系统扩展
- 客户端不必知道产品内部的组成细节,便于控制细节风险
其缺点:
- 产品的组成部分必须相同,使用范围会受限
- 如果产品内部变化较为复杂,这样会增加很多的建造着类。
建造者模式注重的就是零部件的组装过程。
结构:
- 产品角色(Product):包含多个组成组件的复杂对象,有具体的建造者来创建其各个部件
- 抽象建造者(Builder):一个包含创建产品各个自组件的抽象方法的接口,通常包含一个返回复杂产品的方法getResult()
- 具体建造者(Concrete Builder):实现Builder接口,完成复杂产品的各个部件的具体创建方法
- 指挥者(Director):调用建造者对象中的部件构造与装配方法完成复杂对象的创建,在指挥者中不涉及具体产品的信息。
上述图就是鉴照着模式的结构图,看一下代码的具体实现
产品角色:包含多个组成部件
package builder.module; /** * 产品角色 */ public class Product { private String part1; private String part2; private String part3; public void setPart1(String part1) { this.part1 = part1; } public void setPart2(String part2) { this.part2 = part2; } public void setPart3(String part3) { this.part3 = part3; } /** * 显示产品特性 */ public void show(){ System.out.println(part1); System.out.println(part2); System.out.println(part3); } }
抽象构建者:包含创建产品各个不见得抽象方法
package builder.module; /** * 抽象构建者 */ public abstract class Builder { protected Product product = new Product(); public abstract void buildPart1(); public abstract void buildPart2(); public abstract void buildPart3(); /** * 返回产品对象 * * @return 产品对象 */ public Product getResult() { return product; } }
具体建造者:实现抽象建造着的方法,完成复杂对象的创建
/** * 具体建造者 需要实现抽象建造着接口 */ public class ConcreteBuilder extends Builder{ @Override public void buildPart1() { product.setPart1("建造 part1"); } @Override public void buildPart2() { product.setPart2("建造 part2"); } @Override public void buildPart3() { product.setPart3("建造 part3"); } }
指挥者:调用建造着中的方法完成复杂对象的创建
package builder.module; /** * 指挥者 */ public class Director { private Builder builder; public Director(Builder builder){ this.builder = builder; } /** * 产品构建以及组装方法 * @return 完成构建的产品 */ public Product construct(){ builder.buildPart1(); builder.buildPart2(); builder.buildPart3(); return builder.getResult(); } }
客户端:客户端根据需求选定指定指定建造着
package builder.module; public class Client { public static void main(String[] args) { // 使用具体的建造者 Builder builder = new ConcreteBuilder(); // 指挥者实例话,指定具体的建造着 Director director = new Director(builder); // 通过指挥者根据对应的具体构建者创建产品 Product product = director.construct(); // 展示产品 product.show(); } }
建造者模式通常的应用场景:
创建的对象比较复杂,可能会有多个部件构成,各个部件面临着复杂的变化,但组成部分的建造顺序是稳定的
创建复杂对象的算法独立于该对象的组成部分以及他们的装配方式,也就是说产品的构建过程和最终的表示是相对独立的。
接下来搞个简单的demo:
比如所有的车的工序都是一样的只需要轮子,logo,价格,那么做一个汽车模型Car,这个就是产品,接下来抽象一个工厂Factory,这个就是抽象建造着,然后实现比亚迪工厂BYDFactory,宝马工厂BMWFactory,特斯拉工厂TESLAFactory,这个就是具体建造着,一个4s店的代理商Agent,这个就是指挥者,然后客户就可以科举需求来购买指定的汽车
产品Car
package builder.demo; public class Car { private String wheel; private String logo; private String price; public void setWheel(String wheel) { this.wheel = wheel; } public void setLogo(String logo) { this.logo = logo; } public void setPrice(String price) { this.price = price; } public void show() { System.out.println("我是:" + logo + ",有" + wheel + "个轮子,我的售价" + price + "万元"); } }
抽象建造者Factory
package builder.demo; /** * 抽象工厂 */ public abstract class Factory { // 创建产品对象 protected Car car = new Car(); public abstract void buildWheel(); public abstract void buildLogo(); public abstract void buildPrice(); /** * 返回产品对象 * @return 汽车产品 */ public Car getResult(){ return car; } }
具体建造者BMWFactory
package builder.demo; /** * 宝马工厂 */ public class BMWFactory extends Factory { @Override public void buildWheel() { car.setWheel("4"); } @Override public void buildLogo() { car.setLogo("BMW"); } @Override public void buildPrice() { car.setPrice("40"); } }
剩下两个具体建造者类似
指挥者Agent
package builder.demo; /** * 4s销售点 */ public class Agent { private Factory factory; public Agent(Factory factory){ this.factory = factory; } public Car construct(){ factory.buildWheel(); factory.buildLogo(); factory.buildPrice(); return factory.getResult(); } }
客户端
package builder.demo; /** * 客户 */ public class Client { public static void main(String[] args) { Factory factory; // 通过指定的厂商获取具体工厂实例 factory = (Factory) Util.getObject("BMWFactory"); // 获取经销商实例 Agent agent = new Agent(factory); // 经销商订货 Car car = agent.construct(); // 展示 car.show(); } }
一个小工具类,就是通过类名实例化类
package builder.demo; public class Util { public static Object getObject(String name){ String cName = "builder.demo.." + name; System.out.println("新类名:"+cName); Class<?> c = null; try { // 根据名称获取类 c = Class.forName(cName); // 调用该类的无参构造方法并获取实例 return c.getDeclaredConstructor().newInstance(); } catch (Exception e) { // 异常 e.printStackTrace(); return c; } } }
源码地址:https://github.com/yang-shixiong/design/tree/master/src/builder
适用场景:
- 创建的对象较复杂,由多个部件构成,各部件面临着复杂的变化,但构件间的建造顺序是稳定的。
- 创建复杂对象的算法独立于该对象的组成部分以及它们的装配方式,即产品的构建过程和最终的表示是独立的。