创造模式-建造者模式

概述

建造者模式(Builder Pattern):将一个复杂对象的构建与表示分离,使构建过程能可以创建出不同的表示。

  • 对象创建的算法(步骤)固定,独立于对象的组成部分和装配方式。
  • 对象有多部分组成,每一部分可以有不同的表述

比如网上组装一台电脑,电脑需要有显示屏、鼠标、键盘、主机、内存、CPU、显卡等部件构成,每一种显示屏、鼠标、键盘、主机、内存、CPU、显卡都有不同的品种,我们可以根据不同的需求和预算来让商人组装不同的电脑。

问题

如何提供一种稳定的封装机制将一个复杂对象的各个部分的变化隔离,从而保证系统中稳定的构建算法不随需求的变化而变化?

解决方案

将一个复杂对象的构建与表示分离,使构建过程能可以创建出不同的表示。

结构

builderPattern.png
  • Builder(抽象构建者):它为创建一个产品Product对象的各个部件指定抽象接口。包含两类方法,第一类创建各个部件builderPartX();第二类是创建出具体的产品build();Builder可以是接口也可以是抽象类。
    电脑商人:1.知道电脑有哪些组件组成,并且买到这些组建 2.能根据这些买的组件组装一台具体的电脑
  • ConcreteBuilder(具体构建者):它实现了Builder接口(抽象类),提供了具体的组件创建和组装的方法,明确定义了它提供的复杂对象Product,也可以提供一个方法返回创建好的复杂产品对象。
    台式电脑商人:产品是台式电脑。
  • Product(产品):一个复杂对象它由各个组件组成,具体建造者创建该产品的内部表示并定义它的装配过程。
    台式电脑:由显示屏、鼠标、键盘、主机、内存、CPU、显卡等部件构成,有电脑商制造好卖给消费者。
  • Director(指导者):它负责安排复杂对象的建造次序,指挥者与抽象建造者之间存在关联关系,可以在其construct()建造方法中调用建造者对象的部件构造与装配方法,完成复杂对象的建造。
    消费者:要求电脑商人制造符合自己需求的电脑。

Java示例

场景:创造台式电脑

/**
 * 抽象的电脑建造者
 * @author jxiu
 *
 */
public interface ComputerBuilder {
    /**
     * 创建屏幕
     * @return
     */
    void buildScreen(String screen);
    /**
     * 创建CPU
     * @return
     */
    void buildCPU(String cpu);
    /**
     * 创建显卡
     * @return
     */
    void buildGPU(String gpu);
    /**
     * 创建内存
     * @return
     */
    void buildMemory(String memory);
    /**
     * 创建硬盘
     * @return
     */
    void buildDisk(String disk);
    /**
     * 创造鼠标
     * @param mouse
     */
    void buildMouse(String mouse);
    /**
     * 创建电脑
     * @return
     */
    Computer build();
}
/**
 * 具体的电脑建造者
 * @author jxiu
 *
 */
public class DeskopComputerBuilder implements ComputerBuilder{

    Computer deskopComputer = new Computer();
    
    
    @Override
    public void buildScreen(String screen) {
        deskopComputer.setScreen(screen);
        
    }

    @Override
    public void buildCPU(String cpu) {
        deskopComputer.setCPU(cpu);
    }

    @Override
    public void buildGPU(String gpu) {
        deskopComputer.setGPU(gpu);
    }

    @Override
    public void buildMemory(String memory) {
        deskopComputer.setMemory(memory);
    }

    @Override
    public void buildDisk(String disk) {
        deskopComputer.setDisk(disk);
    }
    
    @Override
    public void buildMouse(String mouse) {
        deskopComputer.setMouse(mouse);
    }

    @Override
    public Computer build() {
        return deskopComputer;
    }
}
/**
 * 电脑  产品对象
 * @author jxiu
 *
 */
public class Computer {

    /** 屏幕*/
    private String screen;
    /** CPU*/
    private String CPU;
    /** GPU*/
    private String GPU;
    /** 内存*/
    private String memory;
    /** 硬盘*/
    private String disk;
    /** 鼠标*/
    private String mouse;
    
    
    public String getScreen() {
        return screen;
    }
    public void setScreen(String screen) {
        this.screen = screen;
    }
    public String getCPU() {
        return CPU;
    }
    public void setCPU(String cPU) {
        CPU = cPU;
    }
    public String getGPU() {
        return GPU;
    }
    public void setGPU(String gPU) {
        GPU = gPU;
    }
    public String getMemory() {
        return memory;
    }
    public void setMemory(String memory) {
        this.memory = memory;
    }
    public String getDisk() {
        return disk;
    }
    public void setDisk(String disk) {
        this.disk = disk;
    }
    public String getMouse() {
        return mouse;
    }
    public void setMouse(String mouse) {
        this.mouse = mouse;
    }
    @Override
    public String toString() {
        return "Computer [screen=" + screen + ", CPU=" + CPU + ", GPU=" + GPU + ", memory=" + memory + ", disk=" + disk
                + ", mouse=" + mouse + "]";
    }
}
/***
 * 消费者  指导者对象--指导者负责制定配件的类型
 * @author jxiu
 *
 */
public class Consumer {

    private static ComputerBuilder builder = null;
    /**
     * 指导方法
     * @return
     */
    public static Computer buy () {
        builder = new DeskopComputerBuilder();
        builder.buildCPU("i7");
        builder.buildGPU("1080TI");
        builder.buildDisk("1T");
        builder.buildMemory("DDR4");
//      builder.buildMouse("普通鼠标");
        builder.buildScreen("普通屏幕");
        Computer computer = builder.build();
        return computer;
    }
    
    public static void main(String[] args) {
        System.out.println("用户购买电脑:" + buy());
    }
}
effective java示例

effective java中提供了另外一种简化的建造者模式。
主要应用场景:类有多个可选参数
解决方案:

  • 提供多个重叠构造器(缺点:比较麻烦,容易出错)
  • javaBeans模式(setter方法设置参数)(缺点:非线程安全,不能把类做成不可变模式)
  • Builder模式
    代码示例:
/**
 * 抽象的建造者
 * @author jxiu
 *
 * @param <T>
 */
public interface Builder<T> {

    /**
     * 建造方法
     * @return
     */
    public T build();
}
使用泛型可以创造出任何需要的对象。
/**
 * 产品对象
 * @author jxiu
 *
 */
public class Computer {

    /** 屏幕*/
    private String screen;
    /** CPU*/
    private String CPU;
    /** GPU*/
    private String GPU;
    /** 内存*/
    private String memory;
    /** 硬盘*/
    private String disk;
    /** 鼠标*/
    private String mouse;
    /**
     * 私有的构造方法,使用具体builder对象建造
     * @param builder
     */
    private Computer(ComputerBilder builder) {
        screen = builder.screen;
        CPU = builder.CPU;
        GPU = builder.GPU;
        memory = builder.memory;
        disk = builder.disk;
        mouse = builder.mouse;
    }
    /**
     * 具体的建造者
     * @author jxiu
     *
     */
    public static class ComputerBilder implements Builder<Computer>{

        /** 屏幕*/
        private String screen;
        /** CPU*/
        private String CPU;
        /** GPU*/
        private String GPU;
        /** 内存*/
        private String memory;
        /** 硬盘*/
        private String disk;
        /** 鼠标*/
        private String mouse;
        
        public ComputerBilder() {
            
        }
        public ComputerBilder screen(String screen) {
            this.screen = screen;
            return this;
        }
        public ComputerBilder CPU(String CPU) {
            this.CPU = CPU;
            return this;
        }
        public ComputerBilder GPU(String GPU) {
            this.GPU = GPU;
            return this;
        }
        public ComputerBilder memory(String memory) {
            this.memory = memory;
            return this;
        }
        public ComputerBilder disk(String disk) {
            this.disk = disk;
            return this;
        }
        public ComputerBilder mouse(String mouse) {
            this.mouse = mouse;
            return this;
        }
        @Override
        public Computer build() {
            return new Computer(this);
        }
        
    }
    
    @Override
    public String toString() {
        return "Computer [screen=" + screen + ", CPU=" + CPU + ", GPU=" + GPU + ", memory=" + memory + ", disk=" + disk
                + ", mouse=" + mouse + "]";
    }
}
/***
 * 消费者  指导者对象--指导者负责制定配件的类型
 * @author jxiu
 *
 */
public class Consumer {
    
    public static void main(String[] args) {
        Computer computer = new ComputerBilder().screen("普通屏幕").CPU("i7").GPU("1080TI").disk("disk").memory("无线鼠标").build();
        System.out.println("用户购买电脑:" + computer);
    }
}

建造者模式和抽象工厂模式区别

  • 建造者模式主要强调指导者(客户端使用者)可以根据需求指导产品的创建
  • 抽象工厂模式是由工厂提供一系列的产品(工厂确定产品的类型和建造过程)。

缺点

  • 如果产品之间的差异性很大,例如很多组成部分都不相同,不适合使用建造者模式,因此其使用范围受到一定的限制
  • 如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大,增加系统的理解难度和运行成本。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,390评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,821评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,632评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,170评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,033评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,098评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,511评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,204评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,479评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,572评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,341评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,893评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,171评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,486评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,676评论 2 335

推荐阅读更多精彩内容