设计模式——复杂对象之生成器模式

手撕设计模式——复杂对象之生成器模式

1.业务需求

​ 大家好,我是菠菜啊,好久不见,今天给大家带来的是创建型模式——生成器模式。老规矩,在介绍这期生成器模式前,我们先来看看这样的需求:现在有一个汽车装配的流水线,要支持轮胎、座椅、发动机等配件客户的定制,我们该怎么设计?

生成器模式之装配汽车

2.代码实现

实现初步思路:

​ 上一章我们学习了工厂方法模式(看这篇文章前可以先回顾《设计模式——工厂三兄弟之工厂方法》这篇),我们首先会想到用工厂模式实现。但是仔细一想,工厂是侧重一系列对象创建的方式,而上述需求是注重对象内部的创建细节、组成部分、创建步骤等。这样显然不合适,所以初级版本如下。

初始版本:


public class Car {
    //发动机
    private Engine engine;
    //轮胎
    private Tyre tyre;
    //座椅
    private Chair chair;

    public void setEngine(Engine engine) {
        this.engine = engine;
    }

    public void setTyre(Tyre tyre) {
        this.tyre = tyre;
    }

    public void setChair(Chair chair) {
        this.chair = chair;
    }

    public Engine getEngine() {
        return engine;
    }

    public Tyre getTyre() {
        return tyre;
    }

    public Chair getChair() {
        return chair;
    }

    public Car() {
    }

    public Car(Engine engine, Tyre tyre, Chair chair) {
        this.engine = engine;
        this.tyre = tyre;
        this.chair = chair;
    }

    public void showCar() {
        System.out.println(this);
    }
    @Override
    public String toString() {
        return "Car{" +
                "engine=" + engine +
                ", tyre=" + tyre +
                ", chair=" + chair +
                '}';
    }

}
//发动机
public class Engine {
    //品牌
    private String brand;
    //型号
    private String model;
    //排量
    private double displacement;

    public Engine(String brand, String model, double displacement) {
        this.brand = brand;
        this.model = model;
        this.displacement = displacement;
    }

    @Override
    public String toString() {
        return "Engine{" +
                "brand='" + brand + ''' +
                ", model='" + model + ''' +
                ", displacement=" + displacement +
                '}';
    }
}
//轮胎
public class Tyre {
    //品牌
    private String brand;
    //型号
    private String model;
    //尺寸
    private int size;

    public Tyre(String brand, String model, int size) {
        this.brand = brand;
        this.model = model;
        this.size = size;
    }

    @Override
    public String toString() {
        return "Tyre{" +
                "brand='" + brand + ''' +
                ", model='" + model + ''' +
                ", size=" + size +
                '}';
    }
}
//座椅
public class Chair {
    //品牌
    private String brand;
    //型号
    private String model;
    //配置
    private String configure;

    public Chair(String brand, String model, String configure) {
        this.brand = brand;
        this.model = model;
        this.configure = configure;
    }

    @Override
    public String toString() {
        return "Chair{" +
                "brand='" + brand + ''' +
                ", model='" + model + ''' +
                ", configure='" + configure + ''' +
                '}';
    }
}
//客户端
public class Client {
    public static void main(String[] args) {

        Car car1=new Car(new Engine("Benz","E200",2.5),new Tyre("韩泰","T200",18),new Chair("奔驰","C200","高配"));
        car1.showCar();
        System.out.println("------------------------------------------------------------------------");
        Car car2=new Car(new Engine("宝马","325Li",3.5),new Tyre("米其林","T300",19),new Chair("宝马","325","低配"));
        car2.showCar();
    }
}

实现代码结构图

生成器模式之组装汽车初版代码UML.drawio

思考:上述代码会发现,汽车对象的创建和表示没有分离,建造一辆汽车太复杂了,有上百种配件,如果要这么制造客户端知道的细节太多了,代码的耦合性太强了,并且生产组装一辆汽车的步骤和配件基本上一样的,可以抽象出来,于是有了以下升级方案。

3.方案改进

实现代码结构图

生成器模式之组装汽车再版UML.drawio

汽车主管类:

public class CarDirector {
    private CarBuilder carBuilder;

    public CarDirector(CarBuilder carBuilder) {
        this.carBuilder = carBuilder;
    }

    public Car build() {
        carBuilder.buildChair();
        carBuilder.buildEngine();
        carBuilder.buildTyre();
        return carBuilder.getCar();
    }
}

汽车生成器抽象类:

public abstract class CarBuilder {
    protected Car car=new Car();
    public abstract void buildEngine();
    public abstract void buildTyre();
    public abstract void buildChair();
    public Car getCar(){
        return car;
    }
}

奥迪汽车生成器类:

public  class AudiConcreteCarBuilder extends CarBuilder {

    @Override
    public void buildEngine() {
        car.setEngine(new Engine("奥迪","A4L",2.0));

    }

    @Override
    public void buildTyre() {
        if(car.getEngine()== null){
            throw new RuntimeException("必须先安装发动机");
        }
        car.setTyre(new Tyre("朝阳","T300",17));
    }

    @Override
    public void buildChair() {
        if(car.getEngine()== null){
            throw new RuntimeException("必须先安装发动机");
        }
        if(car.getTyre()== null){
            throw new RuntimeException("必须先安装轮胎");
        }
        car.setChair(new Chair("奥迪","A4L","低配"));
    }
}

奔驰汽车生成器类:

public  class BenzConcreteCarBuilder extends CarBuilder {

    @Override
    public void buildEngine() {
        car.setEngine(new Engine("奔驰","E200",2.5));
    }

    @Override
    public void buildTyre() {
        if(car.getEngine()== null){
            throw new RuntimeException("必须先安装发动机");
        }
        car.setTyre(new Tyre("韩泰","T200",18));
    }

    @Override
    public void buildChair() {
        if(car.getEngine()== null){
            throw new RuntimeException("必须先安装发动机");
        }
        if(car.getTyre()== null){
            throw new RuntimeException("必须先安装轮胎");
        }
        car.setChair(new Chair("奔驰","C200","高配"));
    }
}

宝马汽车生成器类:

public  class BMWConcreteCarBuilder extends CarBuilder {

    @Override
    public void buildEngine() {
        car.setEngine(new Engine("宝马","325Li",2.0));
    }

    @Override
    public void buildTyre() {
        if(car.getEngine()== null){
            throw new RuntimeException("必须先安装发动机");
        }
        car.setTyre(new Tyre("powertec","T300",17));
    }

    @Override
    public void buildChair() {
        if(car.getEngine()== null){
            throw new RuntimeException("必须先安装发动机");
        }
        if(car.getTyre()== null){
            throw new RuntimeException("必须先安装轮胎");
        }
        car.setChair(new Chair("宝马","325","低配"));
    }
}

client类:

public class Client2 {
    public static void main(String[] args) {
        CarDirector carDirector1=new CarDirector(new BMWConcreteCarBuilder());
        Car car1=carDirector1.build();
        car1.showCar();
        System.out.println("------------------------------------------------------------------------");
        CarDirector carDirector2=new CarDirector(new BenzConcreteCarBuilder());
        Car car2=carDirector2.build();
        car2.showCar();
        System.out.println("------------------------------------------------------------------------");
        CarDirector carDirector3=new CarDirector(new AudiConcreteCarBuilder());
        Car car3=carDirector3.build();
        car3.showCar();
    }
}

思考:如果安装上述代码的实现,如果要组装一辆车,只需要告诉汽车主管组装什么类型的车(也就是指定具体的生成器)就行了,使用者不需要知道建造的全部细节,这种设计模式叫做——生成器模式,又叫建造者模式(Builder Pattern)

4.定义和组成结构

建造者模式(Builder Pattern)指将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示,这样的设计模式被称为建造者模式。它是将一个复杂的对象分解为多个简单的对象,然后一步一步构建而成。它将变与不变相分离,即产品的组成部分是不变的,但每一部分是可以灵活选择的。

生成器设计模式.drawio

主要角色:

  • 产品(Product):具体生成器要构造的复杂对象;
  • 抽象生成器(Builder):抽象生成器是一个接口,该接口除了为创建一个Product对象的各个组件定义了若干个方法外,还要定义返回Product对象的方法
  • 具体生成器(ConcreteBuilder):实现了Builder接口的类,具体生成器将实现Builder接口所定义的方法。;
  • 指挥者(Director):指挥者是一个类,该类需含有Builder接口声明的变量。指挥者的职责是负责向用户提供具体生成器,即指挥者将请求具体生成器来构造用户所需要的Product对象,如果所请求的具体对象生成器成功德构造出Product对象,指挥者就可以让该具体生成器返回所构造的Product对象。

5.优缺点以及应用场景

优点:

  • 产品使用者和创建者解耦,无须知道产品的内部的组成细节,对象的构建过程与表示分离(使用相同的构建过程来创建不同的表示)
  • 扩展性好,各个具体的创建者相互独立,满足单一原则开闭原则

缺点:

  • 产品对象的组成部分或创建步骤必须相同
  • 产品的内部发生变化,建造者也要同步修改,维护成本高
  • 引入了多个抽象和具体类,增加了系统的复杂度和理解难度

适用场景:

  • 对象创建复杂、多步骤创建
  • 根据不同需求创建内部细节不同对象

现实应用场景:

  • StringBuilder和StringBuffer:这俩个类都提供了动态生成字符串的构建功能,高效地创建和拼接字符串。
  • 数据库查询构造器:如 MyBatis 中的 SqlBuilder、Hibernate 的 CriteriaBuilder,都使用了建造者模式来构建复杂的查询语句。
    image-20241218153418864

6.和工厂模式对比

  1. 关注点不同:工厂模式关注的是对象的创建,建造者模式关注的是对象的构造过程。
  2. 复杂度不同:工厂模式通常用于创建单个对象,建造者模式用于创建具有复杂结构的对象。
  3. 使用场景不同:工厂模式适用于当创建逻辑简单且对象创建后直接可用的情况,建造者模式适用于需要一步步构建复杂对象的情况。

【个人链接

微信公众号:

CSDN博客:

个人博客网站:

你的收藏和点赞就是我最大的创作动力,关注我我会持续输出更新!

友情提示:请尊重作者劳动成果,如需转载本博客文章请注明出处!谢谢合作!

【作者:我爱吃菠菜

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇