美文网首页Android知识技术干货
浅析设计模式-建造者模式

浅析设计模式-建造者模式

作者: RunAlgorithm | 来源:发表于2017-08-21 23:22 被阅读115次

定义

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

如果一个类的构造非常复杂,并且如果是由很多部件组合而成,而且整体的组装过程比较复杂的话,需要用到构建者。它的使用我认为有两种优势

  • 对复杂的对象进行动态配置,根据实际场景选择对象的部件
  • 把对象的复杂的封装组装对使用者透明(这个遇到得比较少)

构成类的部件,可以是多个一样,也可以不一样的,这个根据业务情况灵活选择

我们可以在现实生活中找到这样的模型

比如,要造一台计算机主机,需要CPU、内存卡、显卡、电源等。组装过程也相对复杂,比如一些接线的处理

比如,要造一辆汽车,需要底盘、方向盘、发动机、座椅、轮子等等

比如,要造航空母舰,需要甲板、起飞装置、机库、动力系统、武器库等

这些模型,都有一个共同点,就是主体由多个部分组成,并且主体的创建过程很复杂,有很多可选择的配置,丰富的组装细节

构建者模式的应用,就是把这个复杂的创建过程分离出来单独维护

现在拿组装电脑的案例来理解

构建者模式-现实模型.png

我们只关心需要使用哪些部件,而并不关心组装过程。我们的角色是使用者,组装电脑的人是指挥者,他们怎么组装,我们并不关心。使用者选好配置后,交给指挥者,然后输出一台符合我们预期的电脑产品

简单设计

构建者模式主要有两种形态

有抽象建造者

这个形态比较复杂,可以用来创建不同的复杂的产品,把产品的部件细节放在具体建造者中实现。然后由指挥者完成复杂的组装

这个实现和上面的区别在于,对 Builder 在进行了一次抽象,并增加了一个指挥者。抽象类声明各个部分的创建,不涉及具体的对象的部件的创建。具体的创建交给它的子类具体建造者来实现

  • 抽象建造者 Abstract Builder

    声明创建对象需要哪些部件

  • 具体建造者 Concrete Builder

    定义明确的部件

  • 产品 Product

    目标产品,由多个部件组成

  • 指挥者 Director

    指挥对象各部件的构建次序,通过指挥者可以使用和构建分离

可以得到这样的类图

构建者模式-复杂-类图.png

使用者调用 Director 的 construct 方法来完整对象的组装,这个方法内指挥者对象各部件的组装次序

public class Director {
    private AbstractBuilder builder;
    public Director(AbstractBuilder builder) {
        this.builder = builder;
    }

    public Product construct() {
        builder.buildA();
        builder.buildB();
        builder.buildC();
        return builder.getResult();
    }
}

使用者直接向指挥者拿最终的产品,整个有点像抽象工厂模式

构建者模式返回一个完整产品,抽象工厂返回一系列产品。构建者模式侧重一步步构造和组建复杂对象,把结果返回。工厂模式侧重生产不同类型的部件

每种具体的 Builder 都是独立的,到时候需要构建新产品,只需要扩展新的 Builder,实现开闭原则

适用:

  • 产品由多个部件组成
  • 部件中依赖关系复杂
  • 创建过程中需要用到系统的某些对象

无抽象建造者

这个模式的基本角色只有俩:

  • 建造者 Builder

    定义部件,并提供方法把所有部件组合成产品

  • 产品 Product

    我们的目标产品,由多个部件组成

这个形态,更侧重于对产品的部件进行按需配置。每个产品需要什么样的部件,交给外部使用者 Client 去选择。这个形态承担了大部分开源库工具类的使用配置,我们的实际应用中大量使用了这个方式,因为简单够用

最后的组装过程发生在 build 方法中,该方法内确定了各部件的组装次序

可以有这样的类图

构建者模式-简易-类图.png

适用:

  • 产品由多个部件组成
  • 部件中依赖关系简单
  • 创建过程不需要或者较少使用到系统的其他对象

应用实例

构建者模式用得比较多的有两种场景

  • 把复杂对象的构建和实现分离,相同的构建过程生产出不同的产品。我们不需要关系构建的过程,只需要知道我们要什么部分。比如对话框的创建
  • 方法多态的改良,可选参数多的场景,比如一个对象的创建有多个可选参数,而且参数还会继续扩展。或者某个执行方法有多个可选参数。应用构建者模式可以让代码简洁,易与扩展与编写。我们举个方法多态的改良例子

对话框的创建

一个对话框由多个部件组成,比如标题栏、内容、确定按钮、取消按钮等等。有的页面需要标题栏,有的页面不需要,有的页面需要确定按钮,有的不需要,这些都通过 Builder 来构建这个复杂的对话框

CommonAlertDialogFragment builder = new CommonAlertDialogFragment.Builder(getActivity())
    .setMessage(xxxx)
    .setCancelable(true)
    .setNegativeButtonText(xxx, null)
    .setPositiveButtonText(xxx, null)
    .setOnDismissListener(new OnDismissListener() {
        @Override
        public void onDismiss() {
            ...
        }
    });
CommonAlertDialogFragment dialog = builder.create()

方法多态的改良

实际应用中,也可以使用构建者来解决一个多参数构造类的问题,对一些参数设置默认值,按需配置,可以帮助类减少方法重载导致方法数量膨胀的问题。假设我们要用客户端下载一个文件,需要配置一些下载参数

  • 必选项

    下载的 url 地址

    下载后的文件的保存地址

  • 可选项

    是否支持多线程,默认不支持

    是否支持文件覆盖,默认可以

    下载失败重试次数,默认10次

如果直接用方法多态的方式,如果想要尽可能地覆盖这些条件的组合所有的情况,需要很多的重载方法

void downloadFile(String url, String savePath);
void downloadFile(String url, String savePath, boolean multiThread);
void downlaodFile(String url, String savePath, boolean multiThread, boolean overwrite);
void downloadFile(String url, String savePath, boolean multiThread, boolean overwrite, int retryNum);
void downloadFile(String url, String savePath, int retryNum);
...

如果未来又增加一个新的条件,方法数量又会有膨胀出好几个;而删除一个条件,则会干扰到多个方法

所以,我们用构建者模式来改善它

public static class Builder {
    private String url;
    private String savePath;
    private int retryNum = 0;
    private boolean multiThread = false;
    private boolean overwrite = true;

    public Builder(String url, String savePath) {
        this.url = url;
        this.savePath = savePath;
    }

    public Builder addRetryNum(int retryNum) {
        this.retryNum = retryNum;
        return this;
    }

    public Builder addMultiThread(boolean multiThread) {
        this.multiThread = multiThread;
        return this;
    }

    public Builder addOverwrite(boolean overwrite) {
        this.overwrite = overwrite;
        return this;
    }

    public DownloadParams build() {
        return new DownloadParams(url, savePath, retryNum, callBack, multiThread, overwrite, sync);
    }
}

然后方法缩减为只有一个

void download(DownloadParams params);

这样用到下载的地方,进行按需配置,不用担心方法数过度膨胀难以更新和维护的问题

开源库使用举例

这些开源库,大都使用构建者模式来满足丰富的配置选项

OKHttp 的创建

OKHttp 的创建,OkHttp 作为 HTTP 请求的客户端,需要配置超时时间、是否允许重定向处理、是否允许连接失败重试等

OkHttpClient.Builder builder = new OkHttpClient.Builder()
    .connectTimeout(20, TimeUnit.MILLISECONDS)
    .readTimeout(60, TimeUnit.MILLISECONDS)
    .writeTimeout(60, TimeUnit.MILLISECONDS)
    .followRedirects(true);
    .followSslRedirects(true);
    .retryOnConnectionFailure(true);
OkHttpClient okHttpClient = builder.build();

通过 Builder 来存储 OkHttpClient 的配置,最后使用这些可选配置完成 OkHttp 的创建

ImageLoader 的创建

ImageLoader 的创建,需要配置线程池核心线程大小、磁盘缓存策略、内存缓存的大小

ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(MeiPaiApplication.getApplication())
    .memoryCacheSizePercentage(13)
    .threadPoolSize(Runtime.getRuntime().availableProcessors())
    .denyCacheImageMultipleSizesInMemory()
    .diskCache(new UnlimitedDiscCache(mImageCacheDir, null, new Md5FileNameGenerator()))
    .tasksProcessingOrder(QueueProcessingType.LIFO)
    .build();
ImageLoader imageLoader = ImageLoader.getInstance();    
imageLoader.init(config);

GsonBuilder 的创建

作为部件,不一定非得每个部件都不一样,有的时候,需要过个相同类型的部件构成。比如我们使用 Gson 库来解析 Json 字符串的时候,需要一个 GsonBuilder,它就可以传入多个对象解析器来处理对象的解析

GsonBuilder buider = new GsonBuilder().
    .registerTypeAdapter(MediaBean.class, new MediaBeanDeserializer())
    .registerTypeAdapter(UserBean.class, new UserBeanDeserializer())
    .registerTypeAdapter(LiveBean.class, new LiveBeanDeserializer());
Gson gson = builder.create();

相关文章

  • 浅析Java设计模式【1】——观察者

    前情内容 浅析Java设计模式【1】——观察者 浅析Java设计模式【2】——适配器 浅析Java设计模式【3】—...

  • 浅析Java设计模式【2】——适配器

    前情内容 浅析Java设计模式【1】——观察者 浅析Java设计模式【2】——适配器 浅析Java设计模式【3】—...

  • 浅析Java设计模式【3】——代理

    1. 前情内容 浅析Java设计模式【1】——观察者 浅析Java设计模式【2】——适配器 浅析Java设计模式【...

  • 浅析设计模式-建造者模式

    定义 建造者模式(Builder Pattern):将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建...

  • Retrofit

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

  • Android中涉及的模式

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

  • 设计模式之建造者模式

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

  • 设计模式 - 目录

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

  • 设计模式之建造者模式

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

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

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

网友评论

    本文标题:浅析设计模式-建造者模式

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