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

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

什么是构建者模式呢?

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

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

  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 用的非常广。2

我挑选了 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 ↩︎

frank909 CSDN认证博客专家 CV(computer vision)
爱阅读的程序员,专注于技术思考和分享。关注架构设计、Android 开发、AI、数学、自动驾驶领域,个人公号:Frankcall
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页
实付 19.90元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值