设计模式-建造者模式

建造者模式详解
摘要:建造者模式是创建型模式大类中的一种,在面向对象的语言中无时无刻不在进行者对象的创建,下面来学习一下建造者模式来创建对象。
 
在这篇文章中我们来学习一下下面几个问题
1、什么是建造者模式
2、使用建造者模式创建产品
3、为何要用建造者模式,在怎样的场景下使用建造者模式
4、演变后的建造者模式
5、演变后的建造者模式相比构造函数和setter的优缺点
 
一、建造者模式
    1、建造者模式定义
    (1)、建造者模式是设计模式的一种,将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
    (2)、建造模式是一步一步创建一个复杂的对象,它允许用户可以只通过指定复杂对象的类型和内容就可以构建它们,用户不知道内部的具体构建细节,构建过程对用户是隐藏的。
 
建造者模式UML图:
 
2、建造者模式各个角色
(1)、Product: 要建造的产品
(2)、抽象的Builder: 建造过程具体建造步骤的抽象
(3)、ConcreteBuilder建造者实现抽象类Builder: 实现Builder 就具体建造抽象步骤
(4)、Director: 指导者,指导构建过程;实现用户和构建的分离。
 
二 、对象创建
我们这里使用建造者创建不同配置的手机如pro 、标配。
按照上面的UML图其中有四个角色,产品、抽象构建过程、具体构建过程、指导者show me code……
 
1、需要的产品定义、建造者创建产品
package com.sb.design;

/***
* product
*/

public class Phone {

    /**
     * 处理器
     */
    private String cpu;

    /**
     * 内存
     */
    private String ram;

    /**
     * 像素
     */
    private Integer pixel;

    /**
     * 电池容量
     */
    private Integer battery;


    public void setCpu(String cpu) {
        this.cpu = cpu;
    }

    public void setRam(String ram) {
        this.ram = ram;
    }

    public void setPixel(Integer pixel) {
        this.pixel = pixel;
    }

    public void setBattery(Integer battery) {
        this.battery = battery;
    }

    public String getCpu() {
        return cpu;
    }

    public String getRam() {
        return ram;
    }

    public Integer getPixel() {
        return pixel;
    }

    public Integer getBattery() {
        return battery;
    }

    @Override
    public String toString() {
        return new StringBuffer().append("处理器:").append(cpu).append(" 内存:").append(ram).append(" 像素:").append
                (pixel).append(" 电池容量:").append(battery).toString();
    }
}

2、建造流程、步骤是固定的,所有建造者都是按照这个流程来建造具体产品,所以抽象这个创建流程。

package com.sb.design;

/***
* 建造过程抽象
*/

public interface PhoneBuilder {
    /**
     * 处理器
     */
    void setCpu();

    /**
     * 内存
     */
    void setRam();

    /**
     * 像素
     */
    void setPixel();

    /**
     * 电池
     */
    void setBattery();

    /**
     * 组装
     *
     * @return
     */
    Phone build();

}

3、按照用户需求,实现不同创建者、但是产品创建的流程确定,所以实现创建流程接口;具体产品创建操作。

(1)、高配手机创建
package com.sb.design;

/***
* 高配手机建造者
*/

public class ProPhoneBuilder implements PhoneBuilder {

    Phone phone;

    {
        phone = new Phone();
    }

    public ProPhoneBuilder() {
    }


    @Override
    public void setCpu() {
        phone.setCpu("加强版");
    }

    @Override
    public void setRam() {
        phone.setRam("256G");
    }

    @Override
    public void setPixel() {
        phone.setPixel(10000);
    }

    @Override
    public void setBattery() {
        phone.setBattery(20000);
    }

    @Override
    public Phone build() {
        return phone;
    }
}

(2)、标配手机创建

package com.sb.design;

/***
* 标配手机创建
*/

public class StandardPhoneBuilder implements PhoneBuilder {

    private Phone phone;

    {
        phone = new Phone();
    }


    @Override
    public void setCpu() {
        phone.setCpu("标准版");
    }

    @Override
    public void setRam() {
        phone.setRam("128G");
    }

    @Override
    public void setPixel() {
        phone.setPixel(10000);
    }

    @Override
    public void setBattery() {
        phone.setBattery(15000);
    }

    @Override
    public Phone build() {
        return phone;
    }
}

4、指导者按照客户要求,指定具体的建造者、并按照建造者建造流程建造具体产品,这里只是指定了流程,而具体的建造操作是在具体建造者中完成。

package com.sb.design;

/**
* 表示、建造过程的隔离
*/
public class Directory {

    private PhoneBuilder builder;

    /**
     * 具体建造者
     *
     * @param builder
     */
    public Directory(PhoneBuilder builder) throws Exception {
        this.builder = builder;
    }

    /**
     * 建造流程、具体建造操作是在具体的建造者中完成
     * 使用组装过程来比喻更贴切,具体的cpu、ram、等都是现成的,这里只是一个组装的过程
     */
    public void create() {
        //建造者设置,配置具体产品属性
        builder.setCpu();
        builder.setRam();
        builder.setPixel();
        builder.setBattery();
    }

    /**
     * 获取产品、建造过程隐藏
     *
     * @return
     */
    public Phone getProduct() {
        return builder.build();
    }
}

5、获取产品

//高配手机建造者
PhoneBuilder proBuilder = new ProPhoneBuilder();
//指导者(组装这)
Directory proDirectory = new Directory(proBuilder);
//按照用户需求组装
proDirectory.create();
//获取用户所需产品
Phone proPhone = proDirectory.getProduct();
System.out.println(proPhone.toString());

//标配
PhoneBuilder stdBuilder = new StandardPhoneBuilder();
Directory stdDirectory = new Directory(stdBuilder);
stdDirectory.create();
Phone stdPhone = stdDirectory.getProduct();
System.out.println(stdPhone.toString());

6、执行结果

处理器:加强版 内存:256G 像素:10000 电池容量:20000
处理器:标准版 内存:128G 像素:10000 电池容量:15000
 
三、为何使用建造者模式、在什么场景下使用
1、相比使用构造函数直接给对象变量赋值,使用setter、builder 这两种方式不用去看参数类型、顺序,使用起来方便。
2、具体的建造者相互独立,因此可以对建造的过程逐步细化,而不会对其他模块产生任何影响。
3、对象比较复杂的时候使用构造函数或setter来设置属性,容易丢失一些属性,而建造者模式能复用,可以有效避免这个问题。
 
四、演变后的建造者模式
演变后的建造者模式在平时项目中使用的很多,下来看看他的实现
1、产品定义、具体建造者定义、建造流程设置、具体建造操作实现
package com.sb.design;
/***
* 电脑产品
* 如果创建的对象属性不能修改,可以不设置setter方法
*/

public class Computer {


    private String cpu;

    private String memory;

    private String disk;

    /**
     * 使用建造者创建,所以私有构造函数、不进行直接创建
     */
    private Computer() {

    }

    /**
     * 使用建造者创建,所以私有构造函数、不进行直接创建
     *
     * @param builder
     */
    private Computer(Builder builder) {
        this.cpu = builder.cpu;
        this.memory = builder.memory;
        this.disk = builder.disk;
    }

    @Override
    public String toString() {
        return new StringBuffer().append("cpu:").append(cpu).append(" memory:").append(memory).append(" disk:")
                .append(disk).toString();
    }

    /**
     * 建造者
     * 建造者属性和产品属性一致
     */
    public static class Builder {


        private String cpu;

        private String memory;

        private String disk;

        /**
         * 具体建造操作
         *
         * @param cpu
         * @return
         */
        public Builder cpu(String cpu) {
            this.cpu = cpu;
            return this;
        }

        /**
         * 具体建造操作
         *
         * @param memory
         * @return
         */
        public Builder memory(String memory) {
            this.memory = memory;
            return this;
        }

        /**
         * 具体建造操作
         *
         * @param disk
         * @return
         */
        public Builder disk(String disk) {
            this.disk = disk;
            return this;
        }

        /**
         * 建造流程(组装操作)、并返回产品
         *
         * @return
         */
        public Computer build() {
            Computer computer = new Computer(this);
            return computer;
        }
    }

}

2、产品定义、创建产品

Computer computerHigh = new Computer.Builder().cpu("i7").memory("32G").disk("1T固态盘").build();
Computer computerStd = new Computer.Builder().cpu("i7").memory("16G").disk("500固态盘").build();
System.out.println(computerHigh.toString());
System.out.println(computerStd.toString());

3、运行结果

cpu:i7 memory:32G disk:1T固态盘
cpu:i7 memory:16G disk:500固态盘
 
Process finished with exit code 0
 
五、演变后的建造者模式优缺点
 
优点
1、其实相比标准的(经典)建造者模式,这种演变后的建造者设计模式使用的更多,他同样隐藏了产品的建造过程、你只需要输入你需要的属性和值。
2、创建产品的时候还可以设置构造函数的私有化、只能按照构建者构建、还可以省略setter方法创建一个不能改变的对象;当然如果有必填属性还是定义为final来保证参数必填;使用灵活!
3、使用方便、可读性强、有逼格!
 
缺点
1、但是这种方式相比直接使用构造函数或setter来给对象赋值多了一个对象的创建,相对来说更耗资源。
 
 
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值