建造者模式:搭积木式设计的魔力
在软件开发中,设计模式是一种解决特定问题的可复用方案。设计模式帮助开发人员提高代码质量、提高可读性,并减少代码维护成本。设计模式是由前人在编写代码时总结出的经验教训和最佳实践,是在不断实践和验证中逐渐形成的。
设计模式有许多种类,每种都解决不同的问题。建造者模式是一种常见的设计模式,它主要用于构建复杂对象。它将对象的构造过程与其表示分离,使得相同的构造过程可以创建不同的表示。这样,我们可以更加灵活地创建对象,并且可以轻松地更改其构造过程而不影响其表示。
建造者模式的作用不仅限于简化对象构建过程。它还可以使得代码更加易于扩展和维护。通过使用建造者模式,我们可以将对象的创建过程从其他代码中隔离出来,这样就可以避免将对象创建的复杂性融入其他代码中。这样,我们可以轻松地扩展和修改对象构建过程,而不影响其他部分的代码。
建造者模式的基本结构
建造者模式由以下几个部分组成:
-
产品类(Product):表示需要被构建的复杂对象。产品类通常包含多个部分,每个部分都有不同的属性和行为。
-
抽象建造者类(Builder):定义了创建产品对象各个部分的抽象接口。抽象建造者类通常包含多个抽象方法,每个方法用于创建产品的一个部分。
-
具体建造者类(ConcreteBuilder):实现抽象建造者类中定义的抽象接口。具体建造者类负责实现产品的各个部分的具体构建过程,并返回构建好的产品对象。
-
指挥者类(Director):负责调用具体建造者类中的方法,按照特定的顺序构建产品对象。指挥者类通常包含一个指向抽象建造者类的引用,以便使用多态的方式构建产品。
-
客户端类(Client):使用建造者模式的主要接口。客户端类通常通过指挥者类调用具体建造者类的方法,构建需要的产品对象。
建造者模式的基本思想是将产品的构造过程分解成若干个步骤,并将这些步骤封装到抽象建造者类中。具体的构造过程由具体建造者类实现,而指挥者类则负责按照特定的顺序调用具体建造者类中的方法,构建需要的产品对象。这样,我们可以灵活地构建对象,并且可以轻松地扩展和修改构造过程。
经典类图
代码实现
比如我们要建一个房子,在建房子的过程中,可以使用建造者模式来实现。房子可以看作是复杂对象,由多个部分构成,例如墙壁、地板、屋顶、窗户等等。建造者模式将房子的建造过程与具体的表示形式(即房子的样式和装饰)分离,使得相同的建造过程可以创建不同风格和装饰的房子。
具体地说,可以定义一个House类作为要构建的复杂对象,其中包含多个属性,例如wall、floor、roof、window等等。然后,可以定义一个Builder接口,其中包含了多个抽象方法,例如buildWall、buildFloor、buildRoof、buildWindow等等,用于创建House对象的各个部分。接下来,可以定义一个ConcreteBuilder类,实现Builder接口中的所有抽象方法,以便创建House对象的不同部分。最后,可以定义一个Director类,负责使用Builder接口来构建House对象,具体地调用ConcreteBuilder类的方法,以构建出一个完整的House对象。
在实际的建造过程中,Client类可以使用Director类来构建不同风格和装饰的房子,例如简约风格、欧式风格、中式风格等等。通过使用建造者模式,可以方便地构建出多样化的房子,而不需要编写大量重复的代码。
首先,我们定义House类作为要构建的复杂对象
public class House {
private String wall;
private String floor;
private String roof;
private String window;
public void setWall(String wall) {
this.wall = wall;
}
public void setFloor(String floor) {
this.floor = floor;
}
public void setRoof(String roof) {
this.roof = roof;
}
public void setWindow(String window) {
this.window = window;
}
@Override
public String toString() {
return "House{" +
"wall='" + wall + '\'' +
", floor='" + floor + '\'' +
", roof='" + roof + '\'' +
", window='" + window + '\'' +
'}';
}
}
然后,我们定义Builder接口,并包含多个抽象方法用于创建House对象的各个部分:
public interface HouseBuilder {
void buildWall();
void buildFloor();
void buildRoof();
void buildWindow();
House getResult();
}
接下来,我们定义ConcreteBuilder类,实现Builder接口中的所有抽象方法,以便创建House对象的不同部分:
public class SimpleHouseBuilder implements HouseBuilder {
private House house;
public SimpleHouseBuilder() {
this.house = new House();
}
@Override
public void buildWall() {
house.setWall("Simple Wall");
}
@Override
public void buildFloor() {
house.setFloor("Simple Floor");
}
@Override
public void buildRoof() {
house.setRoof("Simple Roof");
}
@Override
public void buildWindow() {
house.setWindow("Simple Window");
}
@Override
public House getResult() {
return house;
}
}
接下来,我们定义Director类,负责使用Builder接口来构建House对象:
public class HouseDirector {
private HouseBuilder builder;
public HouseDirector(HouseBuilder builder) {
this.builder = builder;
}
public void construct() {
builder.buildWall();
builder.buildFloor();
builder.buildRoof();
builder.buildWindow();
}
}
最后,我们定义Client类,使用Director类来构建House对象,并输出构建结果:
public class Client {
public static void main(String[] args) {
HouseBuilder builder = new SimpleHouseBuilder();
HouseDirector director = new HouseDirector(builder);
director.construct();
House house = builder.getResult();
System.out.println(house);
}
}
总结
建造者模式的优点包括:
- 将对象的构建过程与其表示分离,使得同样的构建过程可以创建不同的表示。
- 代码易于扩展,可以根据需要添加新的Builder类和Director类来构建不同的对象。
- 客户端不需要知道具体的建造过程,可以通过Director来获得所需的对象。
建造者模式的缺点包括:
- 增加了代码的复杂度,需要定义多个类以及它们之间的关系。
- 在需要构建简单对象的情况下,建造者模式可能会显得过于冗余。
- 客户端需要知道具体的Builder类,否则无法使用该模式构建对象。
转载自:https://juejin.cn/post/7230468104617312316