• 建造者模式


    建造者模式

    建造者模式Builder Pattern又可以称为生成器模式,是将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示,建造者模式属于对象创建型模式。

    描述

    建造者模式是一步一步创建一个复杂的对象,它允许用户只通过指定复杂对象的类型和内容就可以构建它们,用户不需要知道内部的具体构建细节。

    模式结构

    • Builder: 抽象建造者,引入抽象建造者的目的,是将建造的具体过程交与它的子类来实现。这样更容易扩展。一般至少会有两个抽象方法,一个用来建造产品,一个是用来返回产品。
    • ConcreteBuilder: 具体建造者,实现抽象类的所有未实现的方法,具体来说一般是两项任务:组建产品、返回组建好的产品。
    • Director: 指挥者,负责调用适当的建造者来组建产品,指挥者一般不与产品类发生依赖关系,与指挥者直接交互的是建造者类,一般来说指挥者被用来封装程序中易变的部分。
    • Product: 产品角色,一般是一个较为复杂的对象,产品类可以是由一个抽象类与它的不同实现组成,也可以是由多个抽象类与他们的实现组成。

    比较

    • 与抽象工厂模式相比,建造者模式返回一个组装好的完整产品,而抽象工厂模式返回一系列相关的产品,这些产品位于不同的产品等级结构,构成了一个产品族。
    • 在抽象工厂模式中,客户端实例化工厂类,然后调用工厂方法获取所需产品对象,而在建造者模式中,客户端可以不直接调用建造者的相关方法,而是通过指挥者类来指导如何生成对象,包括对象的组装过程和建造步骤,它侧重于一步步构造一个复杂对象,返回一个完整的对象。
    • 如果将抽象工厂模式看成汽车配件生产工厂,生产一个产品族的产品,那么建造者模式就是一个汽车组装工厂 ,通过对部件的组装可以返回一辆完整的汽车。

    优点

    • 在建造者模式中, 客户端不必知道产品内部组成的细节,将产品本身与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象。
    • 每一个具体建造者都相对独立,而与其他的具体建造者无关,因此可以很方便地替换具体建造者或增加新的具体建造者, 用户使用不同的具体建造者即可得到不同的产品对象 。
    • 可以更加精细地控制产品的创建过程,将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰,也更方便使用程序来控制创建过程。
    • 增加新的具体建造者无须修改原有类库的代码,指挥者类针对抽象建造者类编程,系统扩展方便,符合开闭原则。

    缺点

    • 建造者模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围受到一定的限制。
    • 如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大。

    实现

    class Product{ // 具体产品
        constructor(){
            this.name = null;
            this.type = null;
        }
        setName(name){
            this.name = name;
        }
        setType(type){
            this.type = type;
        }
        showProduct(){
            console.log("name:", this.name);
            console.log("type:", this.type);
        }
    }
    
    class Builder{ // 抽象建造者
        setPart(name, type){
            throw new Error("Abstract method cannot be called");
        }
        getProduct(){
            throw new Error("Abstract method cannot be called");
        }
    }
    
    class ConcreteBuilder extends Builder{ // 实体建造者
        constructor(){
            super();
            this.product = new Product();
        }
        build(name, type){
            this.product.setName(name);
            this.product.setType(type);
        }
        getProduct(){
            return this.product;
        }
    }
    
    class Director{ // 指挥者
        constructor(){
            this.builder = new ConcreteBuilder();
        }
        getProductA(){
            this.builder.build("A", "TypeA");
            return this.builder.getProduct();
        }
    
        getProductB(){
            this.builder.build("B", "TypeB");
            return this.builder.getProduct();
        }
    }
    
    (function() {
        var director = new Director();
        var productA = director.getProductA();
        productA.showProduct(); // name: A type: TypeA
        var director = new Director();
        var productB = director.getProductB();
        productB.showProduct(); // name: B type: TypeB
    })()
    

    每日一题

    https://github.com/WindrunnerMax/EveryDay
    

    参考

    https://www.runoob.com/design-pattern/builder-pattern.html
    https://wiki.jikexueyuan.com/project/java-design-pattern/builder-pattern.html
    https://design-patterns.readthedocs.io/zh_CN/latest/creational_patterns/builder.html
    
  • 相关阅读:
    volatile 和 mutable 关键字
    字符串第一个只出现一次的字符
    学一下HDFS,很不错(大数据技术原理及应用)
    把数组排成最小的数
    求第K大的数字
    数组中超过一半的数字
    打印字符的任意排列
    实时推荐系统架构
    带有任意指向指针的链表进行复制
    surfaceflinger中各个layer的排序
  • 原文地址:https://www.cnblogs.com/WindrunnerMax/p/13668419.html
Copyright © 2020-2023  润新知