学习设计模式 - 建造者模式
一、是什么
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。(Spearate the construction of a compolex object from its representation so that the same construction process can create different representations.)
二、为什么
1. 如果一个对象的组成过于复杂,可以通过建造者模式,将构造过程抽离出来,一步步构造对象
2. 可以更精细的控制生成对象
3. 由于对象构造过程过于复杂, 使用建造者模式可以屏蔽对象的内部复杂性, 减少客户端对复杂对象的了解
三、怎么样
3.1) Product产品类:
需要构建复杂的产品类
3.2) Builder构建接口
可定义了构建部分构建的接口方法, 以及构建整个对象的方法.
3.3) ConreteBuilder具体构建者
实现了Builder接口.
3.3) Direct导演类
导演类一方面封装导演了构建组件的构成, 另一方面屏蔽客户端对构建过程的深入了解.
四、举例
1. 产品类
public class Computer { private String cpu; private String memory; private String hardDisk; public String getCpu() { return cpu; } public void setCpu(String cpu) { this.cpu = cpu; } public String getMemory() { return memory; } public void setMemory(String memory) { this.memory = memory; } public String getHardDisk() { return hardDisk; } public void setHardDisk(String hardDisk) { this.hardDisk = hardDisk; } @Override public String toString() { return "computer= { cpu: "+cpu+", memory: "+memory+", hardDisk: "+hardDisk+"} "; } }
2. 定义建造者接口
public interface ComputerBuilder { ComputerBuilder setCpu(); ComputerBuilder setMemory(); ComputerBuilder setHardDisk(); Computer build(); }
3. 实现多种具体建造者
public class HighConfComputerBuilder implements ComputerBuilder { // 高配电脑建造者 private Computer computer; public HighConfComputerBuilder() { this.computer=new Computer(); } @Override public ComputerBuilder setCpu() { this.computer.setCpu("i7处理器"); return this; } @Override public ComputerBuilder setMemory() { this.computer.setMemory("16G内存"); return this; } @Override public ComputerBuilder setHardDisk() { this.computer.setHardDisk("1T固态硬盘"); return this; } @Override public Computer build() { return this.computer; } }
public class LowConfComputerBuilder implements ComputerBuilder { // 低配电脑建造者 private Computer computer; public LowConfComputerBuilder() { this.computer=new Computer(); } @Override public ComputerBuilder setCpu() { this.computer.setCpu("i3处理器"); return this; } @Override public ComputerBuilder setMemory() { this.computer.setMemory("4G内存条"); return this; } @Override public ComputerBuilder setHardDisk() { this.computer.setHardDisk("500G机械硬盘"); return this; } @Override public Computer build() { return this.computer; } }
4. 导演类
/** * 导演类, 避免客户端代码深入建造过程 * @author TimFruit * @date 2019/7/2 14:28 */ public class ComputerDirector { public Computer buildHighConfigComputer(){ ComputerBuilder cb=new HighConfComputerBuilder(); // 封装构建过程, 按照"蓝图"导演构造产品 cb.setCpu() .setMemory() .setHardDisk(); return cb.build(); } public Computer buildLowConfigComputer(){ ComputerBuilder cb=new LowConfComputerBuilder(); // 封装构建过程, 按照"蓝图"导演构造产品 cb.setHardDisk() .setCpu() .setMemory(); return cb.build(); } }
5. 测试类
public class Client { public static void main(String[] args) { ComputerDirector cd=new ComputerDirector(); Computer lowConfigComputer=cd.buildLowConfigComputer(); System.out.println(lowConfigComputer); Computer highConfigComputer=cd.buildHighConfigComputer(); System.out.println(highConfigComputer); } }
6. 结果
computer= { cpu: i3处理器, memory: 4G内存条, hardDisk: 500G机械硬盘}
computer= { cpu: i7处理器, memory: 16G内存, hardDisk: 1T固态硬盘}
五、注意事项
适用场景:
a. 构造复杂对象,如config,vo等
b. 构造部件的顺序不同, 产生的结果不同, 则可以使用该模式
vs工厂模式:
工厂模式关注的是使用什么工厂, 获得什么产品, 而建造者模式关注的是, 以什么样的顺序构建组装一个产品, 它的侧重点在于构建的过程.
六、变种建造者模式
1. 产品类
public class Person { private final String name; // 由于定义了不可变类型final private final int age; private final int height; private final String address; public Person(Builder builder) { this.name=builder.name; this.age=builder.age; this.height=builder.height; this.address=builder.address; } public String getName() { return name; } public int getAge() { return age; } public int getHeight() { return height; } public String getAddress() { return address; } public static class Builder{ // 建造者为内部类, 一般用于设置产品类的多种属性, 如果仅仅使用构造参数注入, 会使得程序易出错 private final String name; private int age; private int height; private String address; public Builder(String name) { this.name = name; } public Builder setAge(int age) { this.age = age; return this; } public Builder setHeight(int height) { this.height = height; return this; } public Builder setAddress(String address) { this.address = address; return this; } public Person build(){ return new Person(this); } } }
2. 测试类上下文
public class Client { public static void main(String[] args){ Person person=new Person.Builder("tim").setAge(11).setHeight(168).setAddress("中国好声音").build(); System.out.println("person: "); System.out.println("name: "+person.getName()); System.out.println("age: "+person.getAge()); System.out.println("height: "+person.getHeight()); System.out.println("address: "+person.getAddress()); } }
学习资料:
<设计模式之禅>