设计模式-建造者模式

设计模式

设计模式的本质是面向对象设计原则的实际运用,是对类的==封装性==、==继承性==和==多态性==以及类的关联关系和组合关系的充分理解。

创建型模式-建造者模式

定义:指将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示,这样的设计模式被称为建造者模式。
它是将一个复杂的对象分解为多个简单的对象,然后一步一步构建而成。它将变与不变相分离,即产品的组成部分是不变的,但每一部分是可以灵活选择的。
eg: 汽车中的方向盘、发动机、车架、轮胎等部件组装,计算机由 CPU、主板、内存、硬盘、显卡、机箱、显示器、键盘、鼠标等部件组装。

特点:

  • 封装性好,构建和表示分离。
  • 扩展性好,各个具体的建造者相互独立,有利于系统的解耦。
  • 客户端不必知道产品内部组成的细节

缺点:

  • 产品的组成部分必须相同,适用产品范围被限制
  • 如果产品内部发生变化,则建造者也要同步修改,变化较为复杂,维护成本大

结构

建造者(==Builder==)模式由产品、抽象建造者、具体建造者、指挥者等 4 个要素构成

主要角色说明:

  • 产品角色(==Product==):它是包含多个组成部件的复杂对象,由具体建造者来创建其各个零部件。
  • 抽象建造者(==Builder==):它是一个包含创建产品各个子部件的抽象方法的接口,通常还包含一个返回复杂产品的方法 getResult()。
  • 具体建造者(==Concrete Builder==):实现 ==Builder== 接口,完成复杂产品的各个部件的具体创建方法。
  • 指挥者(==Director==):它调用建造者对象中的部件构造与装配方法完成复杂对象的创建,在指挥者中不涉及具体产品的信息。

UML 类图关系

image

建造者模式的实际体现

JDK

StringBuilder:

public final class StringBuilder extends AbstractStringBuilder implements java.io.Serializable, CharSequence{
    
    @Override
    public StringBuilder append(Object obj) {
        return append(String.valueOf(obj));
    }

    @Override
    public StringBuilder append(String str) {
        super.append(str);
        return this;
    }

    @Override
    public StringBuilder append(CharSequence s) {
        super.append(s);
        return this;
    }

    @Override
    public StringBuilder append(char[] str) {
        super.append(str);
        return this;
    }
    ...
}

AbstractStringBuilder:

abstract class AbstractStringBuilder implements Appendable, CharSequence {
    public AbstractStringBuilder append(String str) {
        if (str == null)
            return appendNull();
        int len = str.length();
        ensureCapacityInternal(count + len);
        str.getChars(0, len, value, count);
        count += len;
        return this;
    }
}

Appendable:

public interface Appendable {
    Appendable append(CharSequence csq) throws IOException;
    Appendable append(CharSequence csq, int start, int end) throws IOException;
    Appendable append(char c) throws IOException;
}
  • Appendable定义多个 append() 抽象方法,抽象建造者
  • AbstractStringBuilder 实现 Appendable 接口,已经作为了建造者,只是抽象类不能直接实例化,通过 StringBuilder 子类进行实例化。
  • StringBuilder 继承 AbstractStringBuilder ,即作为具体建造者,也作为指挥者。

Spring

BeanDefinitionBuilder:

public final class BeanDefinitionBuilder {
    
    public AbstractBeanDefinition getRawBeanDefinition() {
        return this.beanDefinition;
    }
    ...
    public BeanDefinitionBuilder setParentName(String parentName) {
        this.beanDefinition.setParentName(parentName);
        return this;
    }
    
    public BeanDefinitionBuilder setFactoryMethod(String factoryMethod) {
        this.beanDefinition.setFactoryMethodName(factoryMethod);
        return this;
    }

    public BeanDefinitionBuilder setScope(String scope) {
        this.beanDefinition.setScope(scope);
        return this;
    }

    ...
        
    public BeanDefinitionBuilder addPropertyValue(String name, Object value) {
        this.beanDefinition.getPropertyValues().add(name, value);
        return this;
    }
    ...
}

AbstractBeanDefinition:

public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor
        implements BeanDefinition, Cloneable {
    
    protected AbstractBeanDefinition(BeanDefinition original) {
        setParentName(original.getParentName());
        setBeanClassName(original.getBeanClassName());
        setScope(original.getScope());
        setAbstract(original.isAbstract());
        setFactoryBeanName(original.getFactoryBeanName());
        setFactoryMethodName(original.getFactoryMethodName());
        setRole(original.getRole());
        setSource(original.getSource());
        copyAttributesFrom(original);
        ...
    }
}

BeanDefinition:

public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
    void setParentName(String parentName);
    void setFactoryMethod(String factoryMethod);
    void setFactoryMethodOnBean(String factoryMethod, String factoryBean);
    void addConstructorArgValue(@Nullable Object value);
    void addConstructorArgReference(String beanName);
    void addPropertyValue(String name, @Nullable Object value);
}
  • BeanDefinition 扮演抽象 ==Builder== 的角色
  • BeanDefinitionBuilder 扮演具体 ==Builder== 角色
  • AbstractBeanDefinition 既扮演指挥者角色又为 ==Product==

简单使用示例

创建角色

  • Director

    public class Director {
    
        private Builder builder;
    
        public Director(Builder builder) {
            this.builder = builder;
        }
    
        public Computer construct(String cpu, String motherboard, String graphic) {
            builder.cpu(cpu);
            builder.motherboard(motherboard);
            builder.graphic(graphic);
            builder.os();
            return builder.build();
        }
    }
    
  • Builder

    public abstract class Builder {
    
        /**
         * setupCPU
         * @param cpu
         */
        public abstract void cpu(String cpu);
    
        /**
         * setupMotherboard
         * @param motherboard
         */
        public abstract void motherboard(String motherboard);
    
        /**
         * setupGraphic
         * @param graphic
         */
        public abstract void graphic(String graphic);
    
        /**
         * setOS
         */
        public abstract void os();
    
        /**
         * build
         * @return
         */
        public abstract Computer build();
    }
    
  • LenovoLaptopBuilder

    public class LenovoLaptopBuilder extends Builder {
    
        private Computer computer = new Computer();
    
        @Override
        public void cpu(String cpu) {
            computer.setCpu(cpu);
        }
    
        @Override
        public void motherboard(String motherboard) {
            computer.setMotherboard(motherboard);
        }
    
        @Override
        public void graphic(String graphic) {
            computer.setGraphic(graphic);
        }
    
        @Override
        public void os() {
            computer.setOs("Windows 10");
        }
    
        @Override
        public Computer build() {
            return computer;
        }
    }
    
  • MacLaptopBuilder

    public class MacLaptopBuilder extends Builder{
    
        private Computer computer = new Computer(); 
        
        @Override
        public void cpu(String cpu) {
            computer.setCpu(cpu);
        }
    
        @Override
        public void motherboard(String motherboard) {
            computer.setMotherboard(motherboard);
        }
    
        @Override
        public void graphic(String graphic) {
            computer.setGraphic(graphic);
        }
    
        @Override
        public void os() {
            computer.setOs("MacOS");
        }
    
        @Override
        public Computer build() {
            return computer;
        }
    }
    
  • Computer

    public class Computer {
        
        private String cpu;
        private String motherboard;
        private String graphic;
        private String os;
    
        public void setCpu(String cpu) {
            this.cpu = cpu;
        }
    
        public void setMotherboard(String motherboard) {
            this.motherboard = motherboard;
        }
    
        public void setGraphic(String graphic) {
            this.graphic = graphic;
        }
    
        public void setOs(String os) {
            this.os = os;
        }
    }
    

简化模式

将角色==Director==与==Client==共用,以达到一种链式调用的编程

  • Laptop

    public class Laptop {
        private String cpu;
        private String motherboard;
        private String graphic;
        private String os;
    
        public String getCpu() {
            return cpu;
        }
    
        public void setCpu(String cpu) {
            this.cpu = cpu;
        }
    
        public String getMotherboard() {
            return motherboard;
        }
    
        public void setMotherboard(String motherboard) {
            this.motherboard = motherboard;
        }
    
        public String getGraphic() {
            return graphic;
        }
    
        public void setGraphic(String graphic) {
            this.graphic = graphic;
        }
    
        public String getOs() {
            return os;
        }
    
        public void setOs(String os) {
            this.os = os;
        }
    
        public Laptop(String cpu, String motherboard, String graphic, String os) {
            this.cpu = cpu;
            this.motherboard = motherboard;
            this.graphic = graphic;
            this.os = os;
        }
    
            /**
         * 静态工厂方法构建 Builder
         * @return
         */
        public static Laptop.Builder builder() {
            return new Laptop.Builder();
        }
    
            /**
         * 静态内部类
         */
        public static class Builder {
            private String cpu;
            private String motherboard;
            private String graphic;
            private String os;
    
            public Laptop.Builder cpu(String cpu) {
                this.cpu = cpu;
                return this;
            }
    
            public Laptop.Builder motherboard(String motherboard) {
                this.motherboard = motherboard;
                return this;
            }
    
            public Laptop.Builder graphic(String graphic) {
                this.graphic = graphic;
                return this;
            }
    
            public Laptop.Builder os(String os) {
                this.os = os;
                return this;
            }
    
            public Laptop build() {
                return new Laptop(cpu, motherboard, graphic, os);
            }
        }
    
        public static void main(String[] args) {
        Laptop laptop = Laptop.builder()
                      .cpu("intel")
                      .motherboard("apple")
                      .graphic("amd")
                      .os("macOS")  
                      .build();
            System.out.println(laptop);
        }
    }
    
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,123评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,031评论 2 384
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,723评论 0 345
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,357评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,412评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,760评论 1 289
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,904评论 3 405
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,672评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,118评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,456评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,599评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,264评论 4 328
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,857评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,731评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,956评论 1 264
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,286评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,465评论 2 348

推荐阅读更多精彩内容

  • 建造者模式:将一个复杂对象的构建与它的表示分离,是的同样的构建过程可以创建不同的表示 使用建造者模式,客户端只需要...
    超级大鸡腿阅读 199评论 0 0
  • 设计模式-建造者模式 概念 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示 用户只需指定...
    蜗牛写java阅读 237评论 0 0
  • 1.简介 将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。 2.使用场景 主要解决在软件系统...
    夜沐下的星雨阅读 125评论 0 0
  • 英文:Builder 对于建造者模式而已,它主要是将一个复杂对象的构建与表示分离,使得同样的构建过程可以创建不同的...
    代码之尖阅读 541评论 0 51
  • 我的博客地址 建造者模式 主要参考了 /冰鉴/ 的一篇博客,觉得写的很详细,然后自己敲了一遍。学习了 设计模式之建...
    下位子阅读 463评论 2 6