设计模式-建造者模式

设计模式-建造者模式

概念

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

用户只需指定需要建造的类型就可以得到他们,建造过程及细节不需要知道

类型:创建型

使用场景

  • 如果一个对象有非常复杂的内部结构(很多属性)
  • 把对象创建和使用分离

优点

  • 封装性好,创建和使用分离

  • 扩展性好,建造类之间独立,一定程度上解耦

  • 便于控制细节风险

    建造者是独立的,因此可以对建造过程逐步细化,不影响其他模块

缺点

  • 产生多余的Builder对象
  • 产品内部发生变化,建造者需要修改

UML

建造者模式UML.png
  • Product 产品类

    public class Product {
        public void doSomething() {
            //...
        }
    }
    
  • Builder抽象建造者

    public abstract class Builder {
        //设置产品的不同部分,以获得不同的产品
        public abstract void setPart();
        //构建产品
        pubilc abstract Product buildProduct();
    }
    
  • ConcreteBuilder具体建造者

    public class ConcreteProduct extends Builder {
        private Product product = new Product();
        //设置产品零件
        pubilc void setPart() {
            //设置Product相关属性等
        }
        //组件一个产品
        public Product buildProduct() {
            return product;
        }
    }
    
  • Director导演类

    导演类起到了封装作用,避免了高层模块深入到建造者内部的实现。如果建造者模式比较庞大,导演类可以有多个

    public class Director {
        private Builder builder = new ConcreteProduct();
        //构建不同的产品
        public Product getAProduct() {
            //设置不同的零件,可以产生不同的产品
            builder.setPart();
            return builder.buildProduct();
        }
    }
    

实例

我们以组装电脑为例:组装电脑需要主板、CPU、内存、硬盘等等

UML

实例UML.png

产品类

public class Computer {

    //各个组件 与 电脑 是整体与部分关系;该场景主要是建造者模式;组件就不在抽象,均以Object为类型
    private Object cpu;
    private Object mainBoard;
    private Object memory;
    private Object disk;
    private Object power;

    public Object getCpu() {
        return cpu;
    }
    public void setCpu(Object cpu) {
        this.cpu = cpu;
    }

    public Object getMainBoard() {
        return mainBoard;
    }
    public void setMainBoard(Object mainBoard) {
        this.mainBoard = mainBoard;
    }

    public Object getMemory() {
        return memory;
    }
    public void setMemory(Object memory) {
        this.memory = memory;
    }

    public Object getDisk() {
        return disk;
    }
    public void setDisk(Object disk) {
        this.disk = disk;
    }

    public Object getPower() {
        return power;
    }
    public void setPower(Object power) {
        this.power = power;
    }

    @Override
    public String toString() {
        return "{" +
                "cpu:" + cpu + ",  " +
                "mainBoard:" + mainBoard + ",  " +
                "memory:" + memory + ",  " +
                "disk:" + disk + ",  " +
                "power:" + power +
                "}";
    }
}

抽象建造者

public interface IComputerBuilder {

    void buildCpu(Object cpu);

    void buildMainBoard(Object mainBoard);

    void buildMemory(Object memory);

    void buildDisk(Object disk);

    void buildPower(Object power);

    Computer getComputer();
}

具体构建者

public class ComputerBuilderImpl implements IComputerBuilder {

    private Computer computer = new Computer();

    @Override
    public void buildCpu(Object cpu) {
        computer.setCpu(cpu);
    }

    @Override
    public void buildMainBoard(Object mainBoard) {
        computer.setMainBoard(mainBoard);
    }

    @Override
    public void buildMemory(Object memory) {
        computer.setMemory(memory);
    }

    @Override
    public void buildDisk(Object disk) {
        computer.setDisk(disk);
    }

    @Override
    public void buildPower(Object power) {
        computer.setPower(power);
    }

    @Override
    public Computer getComputer() {
        return computer;
    }
}

导演类

public class Director {

    public void construct(IComputerBuilder builder) {
        builder.buildCpu("i5");
        builder.buildDisk("500G");
        builder.buildMainBoard("hp-MainBoard");
        builder.buildMemory("16G");
        builder.buildPower("hp-Power");
    }
}

使用场景

public class Client {
    // 一个消费者向电脑门店购买电脑;电脑商家组件电脑后,卖给消费者
    public static void main(String[] args) {
        IComputerBuilder builder = new ComputerBuilderImpl();
        Director director = new Director();
        director.construct(builder);

        Computer computer = builder.getComputer();

        System.out.println(computer);
    }
}

源码案例

  1. StringBuilder (源码做了提取)

    abstract class AbstractStringBuilder implements Appendable, CharSequence {
        char[] value;
        int count;
        
        public AbstractStringBuilder append(String str) {
            if (str == null)
                return appendNull();
            int len = str.length();
            ensureCapacityInternal(count + len);
            //将 value 插入到 str 对应的char数组中;从0开始插入
            str.getChars(0, len, value, count);
            
            count += len;
            //返回自己
            return this;
        }
    }
    
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 String toString() {
        // Create a copy, don't share the array
        return new String(value, 0, count);
    }

}
  1. ES-BulkProcessor (静态内部类方式)

    public class BulkProcessor implements Closeable {
        //...无关代码
        //构造器,该构造器 不是 public,由静态内部类构建
        BulkProcessor(Client client, 
                      BackoffPolicy backoffPolicy, 
                      Listener listener, 
                      @Nullable String name, 
                      int concurrentRequests, 
                      int bulkActions, ByteSizeValue bulkSize, 
                      @Nullable TimeValue flushInterval) {
            //属性设置
            this.... = ...
        }
        
        //静态内部类构建 对象
        public static class Builder {
            private final Client client;
            private final Listener listener;
    
            private String name;
            private int concurrentRequests = 1;
            private int bulkActions = 1000;
            private ByteSizeValue bulkSize = new ByteSizeValue(5, ByteSizeUnit.MB);
            private TimeValue flushInterval = null;
            private BackoffPolicy backoffPolicy = BackoffPolicy.exponentialBackoff();
    
            public Builder(Client client, Listener listener) {
                this.client = client;
                this.listener = listener;
            }
            
            public Builder setName(String name) {
                this.name = name;
                return this;
            }
            
            public Builder setConcurrentRequests(int concurrentRequests) {
                this.concurrentRequests = concurrentRequests;
                return this;
            }
            
            public Builder setBulkActions(int bulkActions) {
                this.bulkActions = bulkActions;
                return this;
            }
    
            public Builder setBulkSize(ByteSizeValue bulkSize) {
                this.bulkSize = bulkSize;
                return this;
            }
    
            public Builder setFlushInterval(TimeValue flushInterval) {
                this.flushInterval = flushInterval;
                return this;
            }
    
            public Builder setBackoffPolicy(BackoffPolicy backoffPolicy) {
                this.backoffPolicy = backoffPolicy;
                return this;
            }
    
            public BulkProcessor build() {
                return new BulkProcessor(client, backoffPolicy, listener, name, concurrentRequests, bulkActions, bulkSize, flushInterval);
            }
        }
    }
    
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 229,237评论 6 537
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 98,957评论 3 423
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 177,248评论 0 382
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 63,356评论 1 316
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 72,081评论 6 410
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 55,485评论 1 324
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 43,534评论 3 444
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 42,720评论 0 289
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 49,263评论 1 335
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 41,025评论 3 356
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 43,204评论 1 371
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 38,787评论 5 362
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 44,461评论 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 34,874评论 0 28
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 36,105评论 1 289
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 51,945评论 3 395
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 48,205评论 2 375

推荐阅读更多精彩内容

  • 定义 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。 介绍 建造者模式属于创建型模式。...
    敏捷Studio阅读 421评论 0 0
  • 总体说来,建造者模式适合于一个具有较多的零件(属性)的产品(对象)的创建过程。根据产品创建过程中零件的构造是否具有...
    时待吾阅读 278评论 0 0
  • 适用性 建造者设计模式定义了处理其他对象的复杂构建的对象设计 UML 代码示例 具体项目包含一个创建复杂产品对象的...
    木有sky阅读 524评论 0 0
  • 面向对象的六大原则 单一职责原则 所谓职责是指类变化的原因。如果一个类有多于一个的动机被改变,那么这个类就具有多于...
    JxMY阅读 957评论 1 3
  • 建造者模式:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。这种类型的设计模式属于创建型...
    夜航星osmo阅读 181评论 0 0