• 设计模式之建造者模式


     

    什么是建造者模式

    建造者模式是一种创建型设计模式,它提供了一种创建对象的最佳方式。这种模式将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。

    举一个简单的例子:假设我们要创建一个复杂的对象,例如一辆汽车,它由多个部分组成,包括引擎、车身、轮胎等。如果我们使用传统的创建方式,我们需要在代码中定义一个汽车类,并在其中定义各个部分的方法和属性。但是,这种方式会使得代码变得非常复杂和难以维护。

    而使用建造者模式,我们可以将汽车的创建过程分解为多个步骤,每个步骤由一个独立的建造者类负责。首先,我们可以定义一个汽车接口,它规范了汽车对象的各个组成部分的建造。然后,我们可以定义具体的建造者类,它们实现了汽车接口,并具体化复杂对象各部分的创建。最后,我们可以定义一个指挥者类,它调用具体建造者来创建复杂对象的各个部分。

    在上面的例子中,建造者模式将汽车的创建过程分解为多个简单的步骤,每个步骤由一个独立的建造者类负责。这样可以使得代码更加清晰和易于维护,并且可以灵活地控制对象的创建过程。

    建造者模式UML类图

    1. Builder(抽象建造者):创建一个Product对象的各个部件指定的抽象接口。
    2. ConcreteBuilder(具体建造者):实现抽象接口,构建和装配各个部件。
    3. Product(抽象产品角色)
    4. ConcreteProduct:一个具体的产品对象,包含各个部件。
    5. Director(指挥者):构建一个使用Builder接口的对象,主要负责隔离了客户与对象的生产过程,控制产品对象的生产过程。

    建造者模式的实现

    下面以一个汽车制造为示例演示一下建造者模式的使用工厂,UML类图如下:

    1、Car:小汽车的抽象接口;

    2、SmallCar:小汽车的实体类,实现了Car接口;

    3、Engine、Tyre、CarBody:汽车的零件,如发动机、轮胎、车身等;

    4、CarBuilder:定义了汽车制造的过程;

    5、GeelyCarBuilder:是CarBuilder的具体实现,实际的汽车的建造过程在这里实现;

    6、CarDirector:汽车制造过程的指挥协调者,负责指挥整个汽车制造过程的顺序;

    Car.java

    1. public interface Car {
    2. /**
    3. * 展示
    4. * @return
    5. */
    6. String show();
    7. /**
    8. * 启动
    9. */
    10. void start();
    11. /**
    12. * 熄火
    13. */
    14. void stop();
    15. }

    SmallCar.java

    1. @Data
    2. public class SmallCar implements Car {
    3. private String brand;//品牌
    4. private Engine engine;//发动机
    5. private Tyre tyre;//轮胎
    6. private CarBody carBody;//车身
    7. @Override
    8. public String show() {
    9. String msg = "品牌:%s,发动机:%s,轮胎:%s,车身:%s";
    10. return String.format(msg, this.brand, this.engine.getType(), this.tyre.getType(), this.carBody.getColor());
    11. }
    12. @Override
    13. public void start() {
    14. System.out.println("启动->" + this.show());
    15. }
    16. @Override
    17. public void stop() {
    18. System.out.println("熄火->" + this.show());
    19. }
    20. }

    Engine.java

    1. @Data
    2. public class Engine {
    3. private String type;
    4. public Engine(String type) {
    5. this.type = type;
    6. System.out.println("制造发动机:"+type);
    7. }
    8. }

    Tyre.java

    1. /**
    2. * 轮胎
    3. */
    4. @Data
    5. public class Tyre {
    6. private String type;
    7. public Tyre(String type) {
    8. this.type = type;
    9. System.out.println("制造轮胎:"+type);
    10. }
    11. }

    CarBody.java

    1. @Data
    2. public class CarBody {
    3. private String color;
    4. public CarBody(String color) {
    5. this.color = color;
    6. System.out.println("制造车身:"+color);
    7. }
    8. }

    CarBuilder.java

    1. public interface CarBuilder {
    2. /**
    3. * 生产发动机
    4. * @return
    5. */
    6. Engine buildEngine(String type);
    7. /**
    8. * 生产轮胎
    9. * @return
    10. */
    11. Tyre buildTyre(String type);
    12. /**
    13. * 生产车身
    14. * @return
    15. */
    16. CarBody buildCarBody(String color);
    17. /**
    18. * 组装小汽车
    19. * @return
    20. */
    21. Car build();
    22. }

    GeelyCarBuilder.java

    1. /**
    2. * 吉利汽车厂
    3. */
    4. public class GeelyCarBuilder implements CarBuilder {
    5. @Override
    6. public Engine buildEngine(String type) {
    7. return new Engine(type);
    8. }
    9. @Override
    10. public Tyre buildTyre(String type) {
    11. return new Tyre(type);
    12. }
    13. @Override
    14. public CarBody buildCarBody(String color) {
    15. return new CarBody(color);
    16. }
    17. @Override
    18. public Car build() {
    19. SmallCar smallCar = new SmallCar();
    20. return smallCar;
    21. }
    22. }

    CarDirector.java

    1. @Data
    2. @AllArgsConstructor
    3. public class CarDirector {
    4. private CarBuilder carBuilder;
    5. public Car constructSmallCar(String brand,String engineType,String tyreType,String carBodyColor){
    6. Engine engine = carBuilder.buildEngine(engineType);
    7. Tyre tyre = carBuilder.buildTyre(tyreType);
    8. CarBody carBody = carBuilder.buildCarBody(carBodyColor);
    9. SmallCar car = ((SmallCar) carBuilder.build());
    10. car.setEngine(engine);
    11. car.setTyre(tyre);
    12. car.setCarBody(carBody);
    13. car.setBrand(brand);
    14. System.out.println("汽车组装完成");
    15. return car;
    16. }
    17. }

    测试类

    1. public class Test {
    2. public static void main(String[] args) {
    3. CarBuilder carBuilder=new GeelyCarBuilder();
    4. CarDirector carDirector = new CarDirector(carBuilder);
    5. Car car = carDirector.constructSmallCar("吉利汽车","国产发动机","马牌轮胎","白色");
    6. car.start();
    7. car.stop();
    8. Car car1 = carDirector.constructSmallCar("沃尔沃汽车", "沃尔沃发动机", "米其林轮胎", "黑色");
    9. car1.start();
    10. car1.stop();
    11. }
    12. }

    建造者模式的适用场景

    下面总结一下建造者模式的一些适用场景:

    1. 相同的方法,不同的执行顺序,产生不同的事件结果时。
    2. 多个部件或零件,都可以装配到一个对象中,但是产生的运行结果又不相同时。
    3. 产品类非常复杂,或者产品类中调用顺序不同产生了不同的效果。
    4. 在对象创建过程中会使用到系统中的一些其他对象,这些对象在产品对象的创建过程中不易得到时。

    总之,建造者模式是一种通过将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示的设计模式。它可以将对象的创建过程分解为多个简单的步骤,每个步骤由一个独立的建造者类负责。这样可以使得代码更加清晰和易于维护,并且可以灵活地控制对象的创建过程。

    总结

    优点

    1. 封装性好,创建和使用分离。
    2. 扩展性好,建造类之间独立、一定程度上解耦。
    3. 客户端不必知道产品内部组成的细节,建造者可以对创建过程逐步细化,而不对其它模块产生任何影响,便于控制细节风险。

    缺点

    1. 产品的组成部分必须相同,这限制了其使用范围。
    2. 如果产品的内部变化复杂,如果产品内部发生变化,则建造者也要同步修改,后期维护成本较大。
    3. 可能会产生多余的Builder对象。

  • 相关阅读:
    linux - 文件利用率快满了 - mongo日志
    【OpenGL ES】渲染管线
    10分钟Apache Kylin快速入门
    基于nodejs+vue校园失物招领平台设计与实现
    vue3脚手架运行各种报错汇总(持续收集)
    没有哪件事比可视化运维大屏上线更有意义了!这一天等了好久
    基于SSM框架的人力资源管理系统毕业设计源码060936
    Spring MVC源码详解
    JVM指令手册
    嵌入式Linux八股(三)——计算机基础
  • 原文地址:https://blog.csdn.net/fox9916/article/details/133967750