建造者模式(构建者模式)
是将一个复杂对象的构建和它的表示分离,使得同样的构建过程可以创建不同的表示。建造者模式隐藏了复杂对象的创建过程,把复杂对象的创建过程加以抽象,通过子类继承或重载的方式,动态的创建具有复合属性的对象。
使用场景
- 隔离复杂对象的创建和使用,相同的方法,不同执行顺序,产生不同事件结果。
- 产品类非常复杂或者产品类因为调用顺序不同而产生不同作用。
- 初始化一个对象时,参数过多,或者很多参数具有默认值。
- 需要生成的产品对象有复杂的内部结构,这些产品对象具备共性。
优点
- 方便用户创建复杂的对象(用户只需要给出指定复杂对象的类型和内容,建造者模式就会按顺序创建复杂对象)。
- 代码复用性、封装性(将对象构建过程和细节进行封装和复用)。
- 使用建造者模式可以使客户端不必知道产品内部组成的细节。
- 具体的建造者类之间是相互独立的,这有利于系统的扩展。
- 具体的建造者相互独立,因此可以对建造的过程逐步细化,而不会对其他模块产生任何影响。
缺点
- 建造者模式所创建的产品一般具有较多的共同点,其组成部分相似;如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围受到一定的限制。
- 如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大。
UML图
- Director:指挥者,用于构建一个使用Builder接口的对象。有两个作用:①隔离了客户与对象的生产过程。②负责控制产品对象的生产过程。
- Builder:建造者,声明了具体建造者的公共接口(产品的建造过程)和返回产品的方法。
- ConcreteBuilder:具体建造者,实现Builder接口来创建具体产品。
- Product:具体产品,即创建后的对象。
建造者模式和抽象工厂模式的比较
- 与抽象工厂模式相比,建造者模式返回一个组装好的完整产品,而抽象工厂模式返回一系列相关的产品,这些产品位于不同的产品等级结构,构成了一个产品族。
- 在抽象工厂模式中,客户端实例化工厂类,然后调用工厂方法获取所需产品对象,而在建造者模式中,客户端可以不直接调用建造者的相关方法,而是通过指挥者类来指导如何生成对象,包括对象的组装过程和建造步骤,它侧重于一步步构建一个复杂的对象,返回一个完整的对象。
- 如果将抽象工厂模式看成汽车配件生产工厂,生产一个产品族的产品,那么建造者模式就是一个汽车组装工厂,通过对部件的组装可以返回一辆完整的汽车
实例:
目标Computer类:
public class Computer {
private String cpu;//必须
private String ram;//必须
private int usbCount;//可选
private String keyboard;//可选
private String display;//可选
public Computer(String cpu, String ram) {
this.cpu = cpu;
this.ram = ram;
}
public void setUsbCount(int usbCount) {
this.usbCount = usbCount;
}
public void setKeyboard(String keyboard) {
this.keyboard = keyboard;
}
public void setDisplay(String display) {
this.display = display;
}
@Override
public String toString() {
return "Computer{" +
"cpu='" + cpu + '\'' +
", ram='" + ram + '\'' +
", usbCount=" + usbCount +
", keyboard='" + keyboard + '\'' +
", display='" + display + '\'' +
'}';
}
}
抽象构建者类:
public abstract class ComputerBuilder {
public abstract void setUsbCount();
public abstract void setKeyboard();
public abstract void setDisplay();
public abstract Computer getComputer();
}
苹果电脑构建者类:
public class MacComputerBuilder extends ComputerBuilder {
private Computer computer;
public MacComputerBuilder(String cpu, String ram) {
computer = new Computer(cpu, ram);
}
@Override
public void setUsbCount() {
computer.setUsbCount(2);
}
@Override
public void setKeyboard() {
computer.setKeyboard("苹果键盘");
}
@Override
public void setDisplay() {
computer.setDisplay("苹果显示器");
}
@Override
public Computer getComputer() {
return computer;
}
}
联想电脑构建这类:
public class LenovoComputerBuilder extends ComputerBuilder {
private Computer computer;
public LenovoComputerBuilder(String cpu, String ram) {
computer=new Computer(cpu,ram);
}
@Override
public void setUsbCount() {
computer.setUsbCount(4);
}
@Override
public void setKeyboard() {
computer.setKeyboard("联想键盘");
}
@Override
public void setDisplay() {
computer.setDisplay("联想显示器");
}
@Override
public Computer getComputer() {
return computer;
}
}
指导者类:
public class ComputerDirector {
public void makeComputer(ComputerBuilder builder){
builder.setUsbCount();
builder.setDisplay();
builder.setKeyboard();
}
}
调用:
public static void main(String[] args) {
ComputerDirector director=new ComputerDirector();//1
ComputerBuilder builder=new MacComputerBuilder("I5处理器","三星125");//2
director.makeComputer(builder);//3
Computer macComputer=builder.getComputer();//4
System.out.println("mac computer:"+macComputer.toString());
ComputerBuilder lenovoBuilder=new LenovoComputerBuilder("I7处理器","海力士222");
director.makeComputer(lenovoBuilder);
Computer lenovoComputer=lenovoBuilder.getComputer();
System.out.println("lenovo computer:"+lenovoComputer.toString());
}
输出结果:
mac computer:Computer{cpu='I5处理器', ram='三星125', usbCount=2, keyboard='苹果键盘', display='苹果显示器'}
lenovo computer:Computer{cpu='I7处理器', ram='海力士222', usbCount=4, keyboard='联想键盘', display='联想显示器'}