设计模式-建造者模式

一、建造者模式简介

1.1、定义

建造者模式指将一个复杂的对象构造过程和对象的表示进行分离。使同样的建造过程可以创建不同的表示,将构建过程拆分成多个简单的对象,将不变和变进行分离。不变的是对象的组成部分,变化的是每个部分的具体内容

比如建造汽车的过程,不变的是都需要车身、底盘、车轮、发动机等组件,变化的是每个组件可以有不同的构造过程。

1.2、优缺点

a.封装性好,构建和表示进行分离

b.扩展性好,各个具体的建造者相互独立,各个组件之间互相解耦

c.对象调用者无需关系对象的具体建造过程,满足迪米特法则

1.3、建造者模式的角色

产品:需要建造的对象,通常包含是由多个简单的组件组合成的复杂对象

抽象建造者:包含创建产品各个子部件的抽象方法的接口,通过还包含一个返回复杂对象的方法用于返回建造后的对象

具体建造者:实现抽象建造者,完成复杂产品各个子部件的具体创建

指挥者:调用建造者对象中的部件构造方法与装配方法完成复杂对象的创建,指挥者不关心具体产品的信息

二、建造者模式案例

1、业务场景

构造一个汽车对象,汽车对象包含了车身、底盘、发动机、车轮等核心组件

2、代码实现

a.定义汽车对象及各个组件的实体类

/**
 * 汽车类
 */
public class Car {

    //车架
    private CarFrame frame;

    //发动机
    private Engine engine;

    //底盘
    private Chassis chassis;

    //车轮
    private Wheel wheel;

    public CarFrame getFrame() {
        return frame;
    }

    public void setFrame(CarFrame frame) {
        this.frame = frame;
    }

    public Engine getEngine() {
        return engine;
    }

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

    public Chassis getChassis() {
        return chassis;
    }

    public void setChassis(Chassis chassis) {
        this.chassis = chassis;
    }

    public Wheel getWheel() {
        return wheel;
    }

    public void setWheel(Wheel wheel) {
        this.wheel = wheel;
    }
}

b.定义抽象建造者,提供返回对象的方法并定义汽车对象构建各个子部件的抽象

/**
 * 抽象汽车建造者
 */
public abstract class CarBuilder {

    protected Car car = new Car();

    /** 返回构造的汽车对象*/
    public Car builder(){
        return car;
    }

    /** 构建车架*/
    public abstract CarBuilder frame();

    /** 构建发动机*/
    public abstract CarBuilder engine();

    /** 构建底盘*/
    public abstract CarBuilder chassis();

    /** 构建车轮*/
    public abstract CarBuilder wheel();
}

c.实现具体的建造者,如奔驰汽车建造者

/**
 * 奔驰汽车建造者实现类
 */
public class BenzCarBuilder extends CarBuilder{

    @Override
    public CarBuilder frame() {
        System.out.println("奔驰建造者构建车轮");
        car.setFrame(new CarFrame("奔驰车轮"));
        return this;
    }

    @Override
    public CarBuilder engine() {
        System.out.println("奔驰建造者构建发动机");
        car.setEngine(new Engine("奔驰发动机"));
        return this;
    }

    @Override
    public CarBuilder chassis() {
        System.out.println("奔驰建造者构建底盘");
        car.setChassis(new Chassis("奔驰底盘"));
        return this; this;
    }

    @Override
    public CarBuilder wheel() {
        System.out.println("奔驰建造者构建车轮");
        car.setWheel(new Wheel("奔驰车轮"));
        return this;
    }
}

测试代码如下:

 public static void main(String[] args){
         CarBuilder builder = new BenzCarBuilder();
         /** 通过奔驰建造者构建汽车对象 */
         Car car = builder.frame().engine().chassis().builder();
         System.out.println(JSON.toJSONString(car));
     }
1 奔驰建造者构建车轮
2 奔驰建造者构建发动机
3 奔驰建造者构建底盘
4 {"chassis":{"name":"奔驰底盘"},"engine":{"name":"奔驰发动机"},"frame":{"name":"奔驰车轮"}}

调用方main函数中无需关心汽车是如何构建的,只需要关心需要将哪些组件组合到汽车对象上。如果汽车需要增加或者删除一些组件,只需要在抽象建造者中增加或删除对应的方法即可,比如需要添加仪表盘组件,则只需要定义仪表盘对象,并且在抽象建造者中添加对应的方法即可,代码如下:

/**
 * 抽象汽车建造者
 */
public abstract class CarBuilder {

    protected Car car = new Car();

    /** 返回构造的汽车对象*/
    public Car builder(){
        return car;
    }

    /** 构建车架*/
    public abstract CarBuilder frame();

    /** 构建发动机*/
    public abstract CarBuilder engine();

    /** 构建底盘*/
    public abstract CarBuilder chassis();

    /** 构建车轮*/
    public abstract CarBuilder wheel();

    /** 构建仪表盘*/
    public abstract CarBuilder bashBoard();
}

此时构造汽车时就可以加上仪表盘的构造

 public static void main(String[] args){
         CarBuilder builder = new BenzCarBuilder();
         /** 通过奔驰建造者构建汽车对象 */
         Car car = builder.frame().engine().chassis().bashBoard().builder();
         System.out.println(JSON.toJSONString(car));
     }

另外本例子中的具体建造者是直接实现了构建细节,还可以改造成将构建细节分离,将构建的组件进行抽象化,比如将上例中的需求改动,汽车不再由奔驰建造者来建造,而是由一个第三方建造者来构建,第三方建造者造汽车时可能会用保时捷的发动机、奔驰的车身、宝马的底盘和奥迪的仪表盘,此时将构建细节交给具体建造者的化就不好扩展,所以具体建造者应该将构建组件的部分抽象分离出去。代码如下:

/**
 * 车架组件
 */
public interface CarFrame {
    public String name();
}
/**
 * 底盘组件
 */
public interface Chassis {
    public String name();
}
/**
 * 发动机组件
 */
public interface Engine {
    public String name();
}
/**
 * 车轮组件
 */
public interface Wheel {
    public String name();
}
/**
 * 仪表盘抽象
 */
public interface BashBoard {
    public String name();
}

修改抽象建造者类,此时由于组件是直接由外部构建,那么可以直接去除建造者类的抽象定义,直接由建造者类构建即可,代码如下:

/**
 * 抽象汽车建造者
 */
public class CarBuilder {

    protected Car car = new Car();

    /** 返回构造的汽车对象*/
    public Car builder(){
        return car;
    }

    /** 构建车架*/
    public  CarBuilder frame(CarFrame carFrame){
        car.setFrame(carFrame);
        return this;
    }

    /** 构建发动机*/
    public  CarBuilder engine(Engine engine){
        car.setEngine(engine);
        return this;
    }

    /** 构建底盘*/
    public  CarBuilder chassis(Chassis chassis){
        car.setChassis(chassis);
        return this;
    }

    /** 构建车轮*/
    public  CarBuilder wheel(Wheel wheel){
        car.setWheel(wheel);
        return this;
    }

    /** 构建仪表盘*/
    public  CarBuilder bashBoard(BashBoard bashBorad){
        car.setBashBoard(bashBorad);
        return this;
    }
}

测试代码:

public static void main(String[] args){
        CarBuilder builder = new CarBuilder();
        /** 通过建造者类构建汽车对象 */
        Car car = builder
                .frame(new BenzFrame())//奔驰车架
                .engine(new PorscheEngine())//保时捷发动机
                .chassis(new BmwChassis())//宝马底盘
                .bashBoard(new AudiBashBoard())//奥迪仪表盘
                .wheel(new MichelinWheel())//米其林车轮
                .builder();
        System.out.println(car.toString());
    }
{"engine":"保时捷发动机","wheel":"米其林车轮","chassis":"宝马底盘","bashBoard":"奥迪仪表盘","frame":"奔驰车架"}

三、建造者模式和工厂模式的对比

1、建造者不关注组件的生产过程,只关心复杂对象的构建过程;而工厂模式需要关心各个组件的生产过程;

2、建造者倾向于建造结构相同内容不同的对象;工厂模式倾向于批量生产结构相同且内容也相同的对象

3、建造者模式中客户端可以控制如何构造对象的组件;工厂模式中客户端无法控制构建对象的细节;

可以表示中建造者模式更加注重的是创建对象的过程;工厂模式更加注重的是创建对象的结果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值