建造者模式
建造者模式是设计模式的一种,将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。分离了部件的构造(由Builder来负责)和装配(由Director负责)从而构建出复杂的对象,这个模式适用于:某个对象的构建过程复杂的情况。由于实现了构建和装配的解耦,不同的构建器,相同的装配可以创建出不同的对象。相同的构建器不同的装配顺序也可以创建不同对象。 建造者模式包含的角色:
- 产品类(Product):要创建的复杂的产品
- 抽象建造者类(Builder):这个接口规定要实现复杂对象的哪些部分的创建,并不涉及具体的部件对象的创建
- 具体建造者类(ConcreteBuilder):实现Builder的接口,完成复杂产品的各个部件的具体创建方法。在构造过程完成后提供产品的实例
- 指挥者类(Director):调用具体建造者来创建复杂对象的各个部分,在指导者中不涉及具体产品的信息,只负责保证对象各个部分完整创建或按照某种顺序创建
【案例】
生产自行车是一个复杂的过程,它包含了车架、车轮、车座等部件的生产。而不同的自行车配件又有不同的材质。对于自行车的生产就可以使用建造者模式
产品类
class Bike{ //产品类
private String frame; //车架
private String seat; //座位
private String wheel; //车轮
// setter and getter 方法
}
抽象建造者类
public abstract class Builder{ //抽象建造者
protected Bike bike = new Bike();
public abstract void builderFrame();//生产车架
public abstract void builderSeat();//生产车座
public abstract void builderWheel();//生产车轮
public abstract Bike createBike();
}
具体建造者类
public class MobileBuilder extends Builder{ //具体建造者
public void builderFrame() {bike.setFrame("碳纤维车架");}
public void builderSeat() {bike.setSeat("真皮车座");}
public void builderWheel() {bike.setWheel("镁合金车轮毂");}
public Bike createBike() {return bike;}
}
public class OfoBuilder extends Builder{ //具体建造者
public void builderFrame() {bike.setFrame("铝合金车架");}
public void builderSeat() {bike.setSeat("橡胶车座");}
public void builderWheel() {bike.setWheel("铝合金车轮毂");}
public Bike createBike() {return bike;}
}
指挥者类
class Director{ //指挥者类
private Builder builder;
public Director(Builder builder) {this.builder = builder;}
public Bike construct(){
builder.builderFrame();//组装车架
builder.builderSeat();//组装车座
builder.builderWheel();//组装车轮
return builder.createBike();
}
}
客户端
public class BuilderTest {
public static void main(String[] args) {
//Director director = new Director(new MobileBuilder());//创建指挥者对象
Director director = new Director(new OfoBuilder());//创建指挥者对象
Bike bike = director.construct();
System.out.println(bike.getFrame());
System.out.println(bike.getSeat());
System.out.println(bike.getWheel());
}
}
创建者模式的优缺点
- 优点:
1、封装性好
2、客户端不需要知道产品内部的细节,将产品与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象
3、将复杂的创建步骤分解在不同的方法中,使得创建过程更加清晰,也更方便使用程序开控制创建的过程
4、容易扩展,如果由新的需求,通过实现一个新的建造者类就可以完成 - 缺点:
建造者模式创建的产品一般具有较多的共同点,其组成成分相似,如果产品之间的差异性很大那么就不适合使用建造者模式
适用场景
- 创建的对象比较复杂,由多个部件组成,各个部件面临着复杂的变化 但其建造顺序是稳定的
- 创建复杂对象的算法独立于该对象的组成部分以及他们的装配方式,即产品的构建过程和最终的表示是独立的
建造者模式的扩展
建造者模式除了上面的写法外,还有一种常用的写法。当一个类的构造器需要传入很多参数时,如果创建这个类的实例,代码的可读就会变得很差,而且容易引起错误。这时就可以使用建造者模式进行重构
重构前的代码
public class Computer {
private String cpu;
private String screen;
private String memory;
private String mainboard;
public Computer(String cpu, String screen, String memory, String mainboard) {
this.cpu = cpu;
this.screen = screen;
this.memory = memory;
this.mainboard = mainboard;
}
/* setter and getter */
}
public class Client{
public static void main(String[] args) {
Computer computer = new Computer("intel","三星","金士顿内存条","华硕主板");
}
}
上面的代码只有4个属性,如果数十个或数百个属性代码的可读性就打打降低。建造者模式在应用过程中可以根据需要改变,如果创建的产品种类只有一种,只需要一个具体建造者,这时可以省略掉抽象建造者,甚至可以省略掉指挥者角色。
重构后
public class Client {
public static void main(String[] args) {
Computer computer = new Computer.Builder().cpu("intel")
.screen("三星")
.memory("金士顿内存条")
.cpu("华硕主板")
.build();
System.out.println(computer);
}
}
class Computer{
private String cpu;
private String screen;
private String memory;
private String mainboard;
/* setter and getter 方法*/
/*toString()方法*/
private Computer(Builder builder){ //私有构造函数
this.cpu = builder.cpu;
this.screen = builder.screen;
this.memory = builder.memory;
this.mainboard = builder.mainboard;
}
public static final class Builder{ //静态内部类
private String cpu;
private String screen;
private String memory;
private String mainboard;
public Builder cpu(String cpu){
this.cpu = cpu;
return this;
}
public Builder screen(String screen){
this.screen = screen;
return this;
}
public Builder memory(String memory){
this.memory = memory;
return this;
}
public Builder mainboard(String mainboard){
this.mainboard = mainboard;
return this;
}
public Computer build(){
return new Computer(this);
}
}
}
对比与new Computer(“intel”,“三星”,“金士顿内存条”,“华硕主板”)这种方式创建对象
1、构建组件时一目了然
2、将构建顺序交给客户端,new Computers这种方式构建顺序是由指挥者类来控制的
建造者模式、工厂模式、抽象工厂模式的对比
- 工厂方法模式VS建造者模式
工厂方法模式注重于整体对象的创建,而建造者模式注重的是部件构建的过程 - 抽象工厂模式VS建造者模式
抽象工厂模式实现的是产品家族的创建,是系列产品,采用抽象工厂模式者不需要关心构建过程,只要什么产品由什么工厂生产即可
建造者模式则是按照需求建造产品,它的目的通过组装零配件产生一个产品
如果将抽象工厂模式看作是汽车配件生产工厂,生产同一品牌的不同汽车配件,那么建造者模式就是汽车装配厂,通过对零部件的组装生产一辆完整的汽车