美文网首页
设计模式之建造者模式

设计模式之建造者模式

作者: 游戏人日常 | 来源:发表于2019-06-29 17:38 被阅读0次

序言

在看Retrofit源码时,可以看到里面用到了大量的设计模式,如果我们非常了解设计模式对理解是很有帮助的,在Rerofit里有用到建造者模式。

定义

将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以生成不同的表示。建造者模式也是对象创建行模式。

说明: 单看这个定义初学者也是很蒙, 大概意思是不需要关心复杂对象创建过程,只需要知道建造者类型即可,建造者才关心这个复杂对象是如何一步一步创建一个复杂对象的。 根据不同类型的建造者生成不同的复杂的对象。也是有具有良好的扩展性。

建造者模式类图

建造者模式类图

在建造者模式中包含如下几个角色:

  • Builder(抽象的建造者) : 它是创建Product对象各个部分的抽象接口。 在该接口一般有两类接口 ,一种是biuldPartX()方法,用于创建该复杂对象各个部分; 另一种方法是getResult, 它用于返回这个复杂对象。 Build可以是一个接口,也可以是抽象类。
  • ConcreteBuilder(具体的建造者): 它实现了Builder接口,具体实现该复杂对象的各个部分,然后返回具体的复杂对象。
  • Product(产品角色): 它是复杂对象,里面包含该对象有哪些部分组成。
  • Director(指挥者):它负责对象的建造次序。指挥者和抽象的建造者存在关联关系,可以在construct中完成复杂对象的创建过程。

上面有提到复杂对象,那什么是复杂对象呢,简单来说就是包含多个成员属性的对象。代码示例如下:

//产品
class Product{
    private String partA;//定义产品的属性,属性可以是其它类型, 值类型和引用类型都行。
    private String partB;
    private String partC;
    //Setter和Getter方法省略就不写了
}

在抽象建造者定义产品的创建方法和获取产品对象的方法。代码示例如下:

//抽象建造者
interface Builder{
    void buildPartA();//创建产品的属性
    void buildPartB();
    void buildPartC();
    Product getResult(); //返回产品对象

}

抽象建造者中申明了一系列的buildPartX()方法,但是具体的实现还是需要具体的建造者。 不同的建造者实现的buildPartX有所区别。代码示例如下:

//具体的建造者 A
public class AConcreteBuilder implements Builder {
Product productA=new Product();
@Override
public void buildPartA() {
    productA.setPartA("PartA from AConcreteBuilder");
}

@Override
public void buildPartB() {
    productA.setPartA("PartB from AConcreteBuilder");
}

@Override
public void buildPartC() {
    productA.setPartA("PartC from AConcreteBuilder");
}

@Override
public Product getResult() {
    return productA;
}
}

//具体的建造者 B
public class BConcreteBuilder implements Build {
Product productB=new Product();
@Override
public void buildPartA() {
    productB.setPartA("PartA from BConcreteBuilder");
}

@Override
public void buildPartB() {
    productB.setPartA("PartB from BConcreteBuilder");
}

@Override
public void buildPartC() {
    productB.setPartA("PartC from BConcreteBuilder");
}

@Override
public Product getResult() {
    return productB;
}
}

我们可以看到每个建造者实现的东西是不同的。但是返回的产品还是一类的,只是产品的属性不一样。

在建造者模式还有个Director角色(导演者或指挥者),该类主要有两个作用: 其一就是控制产品的创建过程,包括biuldPartX方法是否被调用以及调用的顺序; 其二 就是隔离了客户与创建的过程, Director只需要指挥抽象的建造者(Build),客户端需要具体的建造者然后调用指挥者的相关方法,返回一个完整的对象(Product)。 代码示例如下

//指挥者
public class Director {
private Builder mBuilder; //抽象的建造者

public Director(Builder build) {
    this.mBuilder = build;
}
public Product construct(){
    mBuilder.buildPartA();
    mBuilder.buildPartB();
    mBuilder.buildPartC();
    return  mBuilder.getResult();
}
}

//客户端   代码片段如下
Builder Abuilder=new AConcreteBuilder();//创建具体的建造者
Director director=new Director(Abuilder);//创建指挥者
Product productA=director.construct();//返回产品A

Builder Bbuilder=new BConcreteBuilder();//创建具体的建造者
Director director=new Director(Bbuilder);//创建指挥者
Product productA=director.construct();//返回产品B

例子

如某个公司要开发个APP(Product),就需要开发者(Builder), 如果有多端的话就需要不同的开发者(ConcreteBuilder),技术经理(Director)就充当指挥者来指示不同的开发者来开发。

APP (Product)

public class APP {
    String code;//代码
    String note;//注释及文档

    public String getCode() {
        return code;
    }
    public void setCode(String code) {
        this.code = code;
    }
    public String getNote() {
        return note;
    }
    public void setNote(String note) {
        this.note = note;
    }

    @Override
    public String toString() {
        return "APP = {" +
                "code='" + code + '\'' +
                ", note='" + note + '\'' +
                '}';
    }
}

开发者 (Builder)

public interface Developer {
    void writeCode();//写代码

    void writeNote();//写文档及注释

    APP getAPP();//返回APP
}

Andoird开发者(ConcreteBuilder)

public class AndroidDeveloper implements Developer {

    APP app = new APP();

    @Override
    public void writeCode() {
        app.setCode("Android code");
    }
    @Override
    public void writeNote() {
        app.setNote("Android note ");
    }
    @Override
    public APP getAPP() {
        return app;
    }
}

技术经理 (指挥者)

public class TechnicalManager {

    Developer mDeveloper;

    public void setDeveloper(Developer mDeveloper) {
        this.mDeveloper = mDeveloper;
    }

    public APP getAPP() {
        mDeveloper.writeCode();
        mDeveloper.writeNote();
        return mDeveloper.getAPP();
    }
}

测试:

    public static void main(String[] args) {
        TechnicalManager manager = new TechnicalManager();//创建技术经理对象(指挥者)
        AndroidDeveloper javaDeveloper = new AndroidDeveloper();//创建Android开发者(具体的建造者)
        manager.setDeveloper(javaDeveloper);//技术经理指挥Android程序员去干活
        APP app = manager.getAPP(); //完成 Android端 APP
        System.out.println(app);
    }

运行结果:

APP = {code='Android code', note='Android note'}

如果公司想在苹果商店也要上款APP,那就需要ios开发,这样我们就不用修改源代码,只需要另创建一个ios的建造者就OK。

ios 开发者(ConcreteBuilder)

public class IosDeveloper implements Developer {
    APP app = new APP();

    @Override
    public void writeCode() {
    app.setCode("ios code");
    }

    @Override
    public void writeNote() {
        app.setNote("ios note");
    }

    @Override
    public APP getAPP() {
        return app;
    }
}

测试:

  public static void main(String[] args) {
    TechnicalManager manager = new TechnicalManager();//创建技术经理对象(指挥者)
    IosDeveloper iosDeveloper = new IosDeveloper();//创建ios开发者(具体的建造者)
    manager.setDeveloper(iosDeveloper);//技术经理指挥ios程序员去干活
    APP app = manager.getAPP(); //完成 ios端 APP
    System.out.println(app);
}

运行结果:

APP {code='ios code', note='ios note'}

如果需要其他端的APP,只需另创建个建造者就可以完成APP。

但是我们看大多数的源码,里面的建造者模式是没有指挥者的(Director),这个又是怎样实现的呢。 在Android中的弹框(dialog)的实现就用了建造者模式,我们就大致实现下它是怎么创建的。 源码中还是很复杂的,这里只是简单实现。

在Android中创建一个dialog的代码

   AlertDialog.Builder builder = new AlertDialog.Builder(this)
    .setTitle("提示")
    .setMessage("消息")
    .setIcon(R.drawable.icon);
    AlertDialog alertDialog=builder.create(); 

这是Android创建dialog最简单的方式。 现在我们就实现这样的写法。

// Product
public class AlertDialog{
    String msg;//消息
    String tilte;//标题
    int icon; //图标

    @Override
    public String toString() {
        return "AlertDialog{" +
                "msg='" + msg + '\'' +
                ", tilte='" + tilte + '\'' +
                ", icon=" + icon +
                '}';
}
//建造者  (Builder)
    static class Builder{
        private AlertDialog mDialog=new AlertDialog();

        public Builder setIcon(int icon){
            mDialog.icon=icon;
            return this;
        }

        public  Builder setTitle(String title){
        mDialog.tilte=title;
            return this;
        }

        public  Builder setMsg(String msg){
            mDialog.msg=msg;
            return this;
        }

        public AlertDialog create(){
            return  mDialog;
        }
    }
}

测试 :

public static void main(String args[]) {
    //因为Builder是AlertDialog的成员内部类,所以这样调用AlertDialog.Builder  
    AlertDialog.Builder builder = new AlertDialog.Builder();
    builder.setIcon(1)
            .setMsg("消息")
            .setTitle("提示");
    AlertDialog dialog = builder.create();
    System.out.println(dialog);
}

运行结果:

AlertDialog{msg='消息', tilte='提示', icon=1}

可以看到我们也按照Android源码这样的调用方法创建了自己的dialog。 Android中的dialog实现比我这复杂,dialog属性更多,逻辑更复杂。

我们可以再看看Retrofit中使用的建造者模式

   Retrofit retrofit = new Retrofit.Builder()
    .baseUrl(API_URL)
    .addConverterFactory(GsonConverterFactory.create())
    .build();

这是创建Retrofit对象。可以看到也是用了建造者模式。 这里就不说了,下次分析源码时再说。

总结:建造者模式只要明白四个角色Product、Builder、ConcreteBuilder、Director的作用,就差不多明白建造者模式是怎么回事了。

优点:

  • 将产品的本身与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象。
  • 每一个具体建造者都是相对独立的,不依赖其他的具体建造者,可以方便地替换和增加新的具体建造者,用户使用不同的具体建造者就能得到不同的产品对象。 由于指挥者(Director)是针对抽象的建造者(Builder)编程,增加新的建造者无需修改原来的建造者,符合‘开闭原则’。

缺点:

  • 所创建的产品具有较多的共同点,其组成部分相似。 如果产品之间的差异性很大的话,就不适用建造者模式。
  • 产品的内部变化复杂的话,可能会导致定义很多的具体建造者来应对这样的变化,这样会导致系统的复杂性。
一个游戏技术人,分享Java、Python、H5、Android 等知识。同时会分享游戏行业日常。

相关文章

  • Android中涉及的模式

    我的Java设计模式-建造者模式 我的Java设计模式-观察者模式 重学设计模式之单例模式

  • 设计模式之建造者模式

    设计模式之建造者模式 Intro 简介 建造者模式: 建造者模式隐藏了复杂对象的创建过程,它把复杂对象的创建过程加...

  • 设计模式之建造者模式

    设计模式之建造者模式 1. 模式定义 建造者模式又可以成为生成器模式,它属于对象创建型模式。建造者模式将一个复杂对...

  • Javaの设计模式之建造者模式

    推荐阅读:《设计模式之禅》 今早早起,刚刚出炉,哈哈 BuilderPattern 设计模式之建造者模式 Demo...

  • 设计模式之建造者模式

    设计模式之建造者模式 建造者模式 属于 创建型模式,提供一种创建对象的最佳方式。 创建型模式 指不是直接使用ne...

  • Retrofit

    Retrofit设计模式 动态代理,装饰模式,建造者模式,抽象工厂模式,适配器模式 建造者模式创建Retrofit...

  • 设计模式 - 目录

    设计模式01 - 单例模式 设计模式02 - 工厂模式 设计模式03 - 建造者模式 设计模式04 - 适配器模式...

  • java设计模式--建造者模式

    java设计模式--建造者模式 建造者模式定义 建造者模式:是将复杂对象的构建与表示进行分离,使同样的构建过程会有...

  • 【Java设计模式】--建造者模式

    建造者模式(Bulider模式) 一、什么是建造者模式 建造者模式是设计模式的一种,将一个复杂对象的构建与它的表示...

  • 建造者设计模式-Builder design pattern

    建造者设计模式是创建型设计模式的一种。创建型设计模式处理对象创建的问题。 建造者设计模式,用来构建需要经过若干个建...

网友评论

      本文标题:设计模式之建造者模式

      本文链接:https://www.haomeiwen.com/subject/gmkgmqtx.html