专栏首页Frank909设计模式(四):通过做蛋糕理解构建模式及Android中的变种

设计模式(四):通过做蛋糕理解构建模式及Android中的变种

之前的文章介绍了抽象工厂模式,本文介绍另外一种创建型的设计模式,构建者模式(Builder Pattern)。

什么是构建者模式呢?

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

上面的描述有点抽象,所以大白话描述一下。

  1. 构建者模式的目的是为了构建一个复杂的对象
  2. 复杂的通俗理解就是,可以以不同的参数创建同一类型的不同对象。
  3. 和其他创建型模式不同的地方,构建者模式强调过程,是一步一步构建的,和现实当中建房子是一样的。

什么时候用构建者模式?

其实,就在于配置

以蛋糕店做蛋糕为例子说明。

无论一个蛋糕长什么样子,做蛋糕的大体流程都差不多。

但是顾客的要求,却不一样。

比如有人喜欢白色的奶油,有人喜欢粉色的奶油。

有人喜欢加巧克力,有人不喜欢加。

有人喜欢绘制图案,有人喜欢绘制文字。

有人喜欢猕猴桃,有人喜欢

抽象工厂模式强调的是不同工厂不同生产线产生不同的产品。

构建者模式更加强调同一家工厂同一生产线在创建过程动态配置最终生成不同的产品,这就是所谓的对象不同表示。

构建者的传统表示

  • Builder 是一个抽象类或者接口,定义了产品构建的通用过程
  • ConcreteBuiler 是 Builder 的实现类,提供了创建 Product 的接口。
  • Product 要创建的对象类型
  • Director 创建使用 Builder 的对象。

Builder 的 Java 代码示例

首先定义产品

Product.java

public class Product {

    public int level;
    public String color;
    public String text;
    public String fruit;

    public Product(){}

    @Override
    public String toString() {
        // TODO Auto-generated method stub
        return "A cake with " + level + " level,"+" a great "+color+" cream,"+" some "+fruit+" and the drawing  text is :"+text;
    }

}

在产品中定义了相关的属性,现在要定义 Builder。

先定义一个抽象类 CakeBuilder 代表蛋糕的创建器 CakeBuilder.java

public abstract class CakeBuilder {
    public abstract void buildCake(int level);
    public abstract void buildCream(String color);
    public abstract void buildText(String text);
    public abstract void buildFruit(String type);
    public abstract  Product getCake();
}

我们再定义 CakeBuilder 的实现类

ConcreteCakeBuilder.java

public class ConcreteCakeBuilder  extends CakeBuilder {

    private Product cake = new Product();

    public ConcreteCakeBuilder(){};

    public  void buildCake(int level){
        cake.level = level;
    }
    public void buildCream(String color){
        cake.color = color;
    }
    public void buildText(String text){
        cake.text = text;
    }
    public void buildFruit(String type){
        cake.fruit = type;
    }
    public Product getCake(){
        return cake;
    }
}

Builder 只是个执行角色,它需要指导,指导者是 Director,所以,我们还需要定义 Director。

Director.java

public class Director {

    public void makeCake(CakeBuilder builder) {

        builder.buildCake(3);
        builder.buildCream("pink");
        builder.buildText("Happy birthday,frank is better!");
        builder.buildFruit("mango");
    }

}

Director 定义了 Builder 工艺的细节。上面的代码表示要做 3 层粉色奶油的蛋糕,水果是芒果,上面有指定字迹。

现在,编写测试 Demo BuilderDemo.java

public class BuilderDemo {

    public static void main(String[] args) {
        Director director = new Director();
        ConcreteCakeBuilder builder = new ConcreteCakeBuilder();
        director.makeCake(builder);

        Product cake = builder.getCake();

        System.out.println(cake.toString());
    }
}

运行结果如下:

A cake with 3 level, a great pink cream, some mango and the drawing  text is :Happy birthday,frank is better!

完整代码

构建模式中的表示和构建

如果,我们想要不一样的蛋糕,我们需要定义另外一种 Director,在它的 makeCake 中定义不同的细节,这就是对象的表示。 如果,我们要改变做蛋糕的工艺,我们可以定义另外一种 Builder,它代表了对象的构建过程。

而如构建者模式定义,这个模式就是为了将对象的构建和表示分离,从而创建复杂的对象。

Android 中的构建者

Android 中用的最多的构建者模式是用于创建对话框,我们在 Android 9.0 源码中搜索相关代码,发现 Builder 用的非常广。

我挑选了 Person 对象分析。

Person.java

public final class Person implements Parcelable {

    @Nullable private CharSequence mName;
    @Nullable private Icon mIcon;
    @Nullable private String mUri;
    @Nullable private String mKey;
    private boolean mIsBot;
    private boolean mIsImportant;


    private Person(Builder builder) {
        mName = builder.mName;
        mIcon = builder.mIcon;
        mUri = builder.mUri;
        mKey = builder.mKey;
        mIsBot = builder.mIsBot;
        mIsImportant = builder.mIsImportant;
    }

    /** Creates and returns a new {@link Builder} initialized with this Person's data. */
    public Builder toBuilder() {
        return new Builder(this);
    }

 

    /** Builder for the immutable {@link Person} class. */
    public static class Builder {
        @Nullable private CharSequence mName;
        @Nullable private Icon mIcon;
        @Nullable private String mUri;
        @Nullable private String mKey;
        private boolean mIsBot;
        private boolean mIsImportant;

        /** Creates a new, empty {@link Builder}. */
        public Builder() {
        }

        private Builder(Person person) {
            mName = person.mName;
            mIcon = person.mIcon;
            mUri = person.mUri;
            mKey = person.mKey;
            mIsBot = person.mIsBot;
            mIsImportant = person.mIsImportant;
        }


        @NonNull
        public Person.Builder setName(@Nullable CharSequence name) {
            this.mName = name;
            return this;
        }


        @NonNull
        public Person.Builder setIcon(@Nullable Icon icon) {
            this.mIcon = icon;
            return this;
        }


        public Person.Builder setKey(@Nullable String key) {
            mKey = key;
            return this;
        }

 
        public Person.Builder setImportant(boolean isImportant) {
            mIsImportant = isImportant;
            return this;
        }

     
        public Person.Builder setBot(boolean isBot) {
            mIsBot = isBot;
            return this;
        }

        /** Creates and returns the {@link Person} this builder represents. */
        @NonNull
        public Person build() {
            return new Person(this);
        }
    }


}

和文章前面讲到 Builder 不同的是,Android 中 Builder 更能体现过程。

Builder 是 Product 中的静态类,然后 Android 中的 Builder 不需要 Director。

它将 Director 的行为通过链式调用替代了。

我们仔细看

 public Person.Builder setImportant(boolean isImportant) {
            mIsImportant = isImportant;
            return this;
        }

     
public Person.Builder setBot(boolean isBot) {
    mIsBot = isBot;
    return this;
}

这一类 setXXX() 方法返回的都是 Builder 本身,也就是同一个 Builder,所以很容易去掉 Director 。比如,创建 Person 我们可以通过如下代码:

Person p = new Person.Builder()
                                    .setImportant(true)
                                    .setBot(false)
                                    .setName("frank")
                                    .build();

大家看看,更喜欢 Android 这种改良式呢?还是传统的构建者模式?

参考

  1. 百度百科.建造者模式.https://baike.baidu.com/item/%E5%BB%BA%E9%80%A0%E8%80%85%E6%A8%A1%E5%BC%8F/3229729?fr=aladdin
  2. http://androidxref.com/9.0.0_r3/s?n=25&start=25&sort=relevancy&defs=Builder&project=frameworks

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • RxAndroid从零开始学之四(常见操作符)

    翻译过来就是操作符的意思。什么用途呢? 先看场景分析。 一般在学校的学生花名册找一个学生的话,是通过学生的学号。然后通过学号检索出学生的详细情况。现在我...

    Frank909
  • 设计模式(二):Android 源码中的工厂模式

    之前的文章介绍了单例模式,单例模式非常简单,也很容易懂。本文介绍另外一种简单的创建型设计模式:工厂模式(Factory Pattern)。

    Frank909
  • 【深度学习】多通道图像卷积过程及计算方式

    之前,有写了一篇博文,【深度学习入门】——亲手实现图像卷积操作介绍卷积的相应知识,但那篇文章更多的是以滤波器的角度去讲解卷积。但实际上是神经网络中该博文内容并不...

    Frank909
  • 从头编写 asp.net core 2.0 web api 基础框架 (5) EF CRUD

    Github源码地址:https://github.com/solenovex/Building-asp.net-core-2-web-api-starter-...

    solenovex
  • salesforce 零基础开发入门学习(二)变量基础知识,集合,表达式,流程控制语句

    salesforce如果简单的说可以大概分成两个部分:Apex,VisualForce Page. 其中Apex语言和java很多的语法类似,今天总结的是一些简...

    用户1169343
  • 从头编写 asp.net core 2.0 web api 基础框架 (2)

    Github源码地址是: https://github.com/solenovex/Building-asp.net-core-2-web-api-starte...

    solenovex
  • .net Core 1.0.1 下的Web框架的的搭建过程step by step

    环境:ubuntu+VScode 数据库:mysql ,ORM框架:chloe 官网

    FreeTimeWorker
  • Java基础-day07-代码题-自定义数据类型;ArrayList集合

    Java基础-day07-代码题-自定义数据类型&ArrayList集合 1.饭店结账程序. 定义菜品类,属性为名称,价格,数量. 集合中添加若干菜品对象. 遍...

    Java帮帮
  • ASP.NET Core应用针对静态文件请求的处理[3]: StaticFileMiddleware中间件如何处理针对文件请求

    我们通过《以Web的形式发布静态文件》和《条件请求与区间请求》中的实例演示,以及上面针对条件请求和区间请求的介绍,从提供的功能和特性的角度对这个名为Static...

    蒋金楠
  • cssjshtml css 盒模型

    CSS 框模型 (Box Model) 规定了元素框处理元素内容、内边距、边框 和 外边距 的方式。

    葫芦

扫码关注云+社区

领取腾讯云代金券