什么是建造者模式
建造者模式是一种创建型设计模式,它提供了一种创建对象的最佳方式。这种模式将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。
举一个简单的例子:假设我们要创建一个复杂的对象,例如一辆汽车,它由多个部分组成,包括引擎、车身、轮胎等。如果我们使用传统的创建方式,我们需要在代码中定义一个汽车类,并在其中定义各个部分的方法和属性。但是,这种方式会使得代码变得非常复杂和难以维护。
而使用建造者模式,我们可以将汽车的创建过程分解为多个步骤,每个步骤由一个独立的建造者类负责。首先,我们可以定义一个汽车接口,它规范了汽车对象的各个组成部分的建造。然后,我们可以定义具体的建造者类,它们实现了汽车接口,并具体化复杂对象各部分的创建。最后,我们可以定义一个指挥者类,它调用具体建造者来创建复杂对象的各个部分。
在上面的例子中,建造者模式将汽车的创建过程分解为多个简单的步骤,每个步骤由一个独立的建造者类负责。这样可以使得代码更加清晰和易于维护,并且可以灵活地控制对象的创建过程。
建造者模式UML类图
- Builder(抽象建造者):创建一个Product对象的各个部件指定的抽象接口。
- ConcreteBuilder(具体建造者):实现抽象接口,构建和装配各个部件。
- Product(产品角色):一个具体的产品对象,包含各个部件。
- Director(指挥者):构建一个使用Builder接口的对象,主要负责隔离了客户与对象的生产过程,控制产品对象的生产过程。
建造者模式的实现
下面以一个汽车制造为示例演示一下建造者模式的使用工厂,UML类图如下:
1、Car:小汽车的抽象接口;
2、SmallCar:小汽车的实体类,实现了Car接口;
3、Engine、Tyre、CarBody:汽车的零件,如发动机、轮胎、车身等;
4、CarBuilder:定义了汽车制造的过程;
5、GeelyCarBuilder:是CarBuilder的具体实现,实际的汽车的建造过程在这里实现;
6、CarDirector:汽车制造过程的指挥协调者,负责指挥整个汽车制造过程的顺序;
Car.java
public interface Car {/*** 展示* @return*/String show();/*** 启动*/void start();/*** 熄火*/void stop();
}
SmallCar.java
@Data
public class SmallCar implements Car {private String brand;//品牌private Engine engine;//发动机private Tyre tyre;//轮胎private CarBody carBody;//车身@Overridepublic String show() {String msg = "品牌:%s,发动机:%s,轮胎:%s,车身:%s";return String.format(msg, this.brand, this.engine.getType(), this.tyre.getType(), this.carBody.getColor());}@Overridepublic void start() {System.out.println("启动->" + this.show());}@Overridepublic void stop() {System.out.println("熄火->" + this.show());}
}
Engine.java
@Data
public class Engine {private String type;public Engine(String type) {this.type = type;System.out.println("制造发动机:"+type);}
}
Tyre.java
/*** 轮胎*/
@Data
public class Tyre {private String type;public Tyre(String type) {this.type = type;System.out.println("制造轮胎:"+type);}
}
CarBody.java
@Data
public class CarBody {private String color;public CarBody(String color) {this.color = color;System.out.println("制造车身:"+color);}
}
CarBuilder.java
public interface CarBuilder {/*** 生产发动机* @return*/Engine buildEngine(String type);/*** 生产轮胎* @return*/Tyre buildTyre(String type);/*** 生产车身* @return*/CarBody buildCarBody(String color);/*** 组装小汽车* @return*/Car build();
}
GeelyCarBuilder.java
/*** 吉利汽车厂*/
public class GeelyCarBuilder implements CarBuilder {@Overridepublic Engine buildEngine(String type) {return new Engine(type);}@Overridepublic Tyre buildTyre(String type) {return new Tyre(type);}@Overridepublic CarBody buildCarBody(String color) {return new CarBody(color);}@Overridepublic Car build() {SmallCar smallCar = new SmallCar();return smallCar;}
}
CarDirector.java
@Data
@AllArgsConstructor
public class CarDirector {private CarBuilder carBuilder;public Car constructSmallCar(String brand,String engineType,String tyreType,String carBodyColor){Engine engine = carBuilder.buildEngine(engineType);Tyre tyre = carBuilder.buildTyre(tyreType);CarBody carBody = carBuilder.buildCarBody(carBodyColor);SmallCar car = ((SmallCar) carBuilder.build());car.setEngine(engine);car.setTyre(tyre);car.setCarBody(carBody);car.setBrand(brand);System.out.println("汽车组装完成");return car;}
}
测试类
public class Test {public static void main(String[] args) {CarBuilder carBuilder=new GeelyCarBuilder();CarDirector carDirector = new CarDirector(carBuilder);Car car = carDirector.constructSmallCar("吉利汽车","国产发动机","马牌轮胎","白色");car.start();car.stop();Car car1 = carDirector.constructSmallCar("沃尔沃汽车", "沃尔沃发动机", "米其林轮胎", "黑色");car1.start();car1.stop();}
}
建造者模式的适用场景
下面总结一下建造者模式的一些适用场景:
- 相同的方法,不同的执行顺序,产生不同的事件结果时。
- 多个部件或零件,都可以装配到一个对象中,但是产生的运行结果又不相同时。
- 产品类非常复杂,或者产品类中调用顺序不同产生了不同的效果。
- 在对象创建过程中会使用到系统中的一些其他对象,这些对象在产品对象的创建过程中不易得到时。
总之,建造者模式是一种通过将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示的设计模式。它可以将对象的创建过程分解为多个简单的步骤,每个步骤由一个独立的建造者类负责。这样可以使得代码更加清晰和易于维护,并且可以灵活地控制对象的创建过程。
总结
优点
- 封装性好,创建和使用分离。
- 扩展性好,建造类之间独立、一定程度上解耦。
- 客户端不必知道产品内部组成的细节,建造者可以对创建过程逐步细化,而不对其它模块产生任何影响,便于控制细节风险。
缺点
- 产品的组成部分必须相同,这限制了其使用范围。
- 如果产品的内部变化复杂,如果产品内部发生变化,则建造者也要同步修改,后期维护成本较大。
- 可能会产生多余的Builder对象。