前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >建造者模式浅析

建造者模式浅析

作者头像
孟君
发布2019-09-24 11:02:42
3150
发布2019-09-24 11:02:42
举报

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

一、建造者模式的基本介绍

建造者的基本结构如下:

  • Builder
    • 为创建一个Product对象的各个部件指定抽象接口。
  • ConcreteBuilder
    • 实现Builder的接口以构造和装载该产品的各个部件
    • 定义并明确它所创建的表示
  • Director
    • 构造一个使用Builder接口的对象
  • Product
    • 表示被构造的复杂对象。ConcreteBuilder创建该产品的内部表示并定义它的装配过程。
    • 包括定义组成部件的类,包括将这些部件装配成最终产品的接口。

Note:建造者模式是体现局部和整体关系的,产品是一步步构建,最终形成的一定是一个整体。

就比如顾客去餐厅购买一份儿童餐,跟收银员说要汉堡、饮料、甜甜圈有额外的玩具等,最终顾客得到是包含所有的儿童餐,是一个整体。

二、Builder模式示例

接下来,我们以上述点餐的例子编写一个建造者模式的示例代码。

  • 创建一个Meal类,作为Product。
    • 产品包含汉堡列表、饮料列表等参数进行区分
代码语言:javascript
复制
package com.wangmengjun.tutorial.designpattern.builder;

import java.util.ArrayList;
import java.util.List;

public class Meal {
  
  private List<String> hamburgerList = new ArrayList<>();
  
  private List<String> juicesList = new ArrayList<>();
  
  private List<String> chipsList= new ArrayList<>();
  
  private List<String> otherItemList= new ArrayList<>();

  /**
   * @return the hamburgerList
   */
  public List<String> getHamburgerList() {
    return hamburgerList;
  }

  /**
   * @param hamburgerList the hamburgerList to set
   */
  public void setHamburgerList(List<String> hamburgerList) {
    this.hamburgerList = hamburgerList;
  }

  /**
   * @return the juicesList
   */
  public List<String> getJuicesList() {
    return juicesList;
  }

  /**
   * @param juicesList the juicesList to set
   */
  public void setJuicesList(List<String> juicesList) {
    this.juicesList = juicesList;
  }

  /**
   * @return the chipsList
   */
  public List<String> getChipsList() {
    return chipsList;
  }

  /**
   * @param chipsList the chipsList to set
   */
  public void setChipsList(List<String> chipsList) {
    this.chipsList = chipsList;
  }

  /**
   * @return the otherItemList
   */
  public List<String> getOtherItemList() {
    return otherItemList;
  }

  /**
   * @param otherItemList the otherItemList to set
   */
  public void setOtherItemList(List<String> otherItemList) {
    this.otherItemList = otherItemList;
  }

  @Override
  public String toString() {
    return "Meal [hamburgerList=" + hamburgerList + ", juicesList=" + juicesList + ", chipsList=" + chipsList
        + ", otherItemList=" + otherItemList + "]";
  }
  
  
}
  • 创建一个Builder
    • 支持单个或者多个添加元素
代码语言:javascript
复制
package com.wangmengjun.tutorial.designpattern.builder;

import java.util.List;

public abstract class  Builder {

  public abstract void hamburger(String name);
  
  public abstract void juice(String name);
  
  public abstract void chips(String name);
  
  public abstract void other(String name);
  
  
  public abstract void hamburger(List<String> names);
  
  public abstract void juice(List<String> names);
  
  public abstract void chips(List<String> names);
  
  public abstract void other(List<String> names);
  
  public abstract Meal build();
  
}
  • 创建一个RestaurantCrew类(ConcreteBuilder)
代码语言:javascript
复制
package com.wangmengjun.tutorial.designpattern.builder;

import java.util.List;

public class RestaurantCrew extends Builder {

  private Meal meal;
  
  public RestaurantCrew() {
    this.meal = new Meal();
  }

  @Override
  public void hamburger(String name) {
    meal.getHamburgerList().add(name);
    
  }

  @Override
  public void juice(String name) {
    meal.getJuicesList().add(name);
    
  }

  @Override
  public void chips(String name) {
    meal.getChipsList().add(name);
    
  }

  @Override
  public void other(String name) {
    meal.getOtherItemList().add(name);
    
  }

  @Override
  public void hamburger(List<String> names) {
    meal.getHamburgerList().addAll(names);
    
  }

  @Override
  public void juice(List<String> names) {
    meal.getJuicesList().addAll(names);
    
  }

  @Override
  public void chips(List<String> names) {
    meal.getChipsList().addAll(names);
    
  }

  @Override
  public void other(List<String> names) {
    meal.getOtherItemList().addAll(names);
    
  }
  
  @Override
  public Meal build() {
    return meal;
  }

}
  • 创建一个Cashier类(Director)
代码语言:javascript
复制
package com.wangmengjun.tutorial.designpattern.builder;

import java.util.List;

public class Cashier {

  private Builder builder;
  
  public Cashier(Builder builder) {
    this.builder = builder;
  }

  public Cashier(Builder builder, List<String> juicesList, List<String> hamburgerList, List<String> otherList) {
    this.builder = builder;
  }
  
  public void construct( List<String> juicesList, List<String> hamburgerList, List<String> otherList) {
    this.builder.hamburger(hamburgerList);
    this.builder.juice(juicesList);
    this.builder.other(otherList);
  }

}
  • 创建一个Customer类(Client)
代码语言:javascript
复制
package com.wangmengjun.tutorial.designpattern.builder;

import java.util.Arrays;

public class Customer {

  public static void main(String[] args) {
    order();
  }
  
  private static void order() {
    //Builder
    Builder builder = new RestaurantCrew();
    //Director
    Cashier defaultCashier = new Cashier(builder);
    defaultCashier.construct(Arrays.asList("大杯冰可乐","大杯九珍果汁"), Arrays.asList("香辣鸡腿堡","香辣鸡腿堡"), Arrays.asList("热牛奶","香辣鸡翅"));
    
    //Meal [hamburgerList=[香辣鸡腿堡, 香辣鸡腿堡], juicesList=[大杯冰可乐, 大杯九珍果汁], chipsList=[], otherItemList=[热牛奶, 香辣鸡翅]]
    Meal defaultMeal = builder.build();
    System.out.println(defaultMeal);
  }
}

运行Customer类之后,就会获取一份点餐后的结果,包含了2个香辣鸡腿堡,大杯冰可乐,大杯九珍果汁,热牛奶以及一个香辣鸡翅。

代码语言:javascript
复制
Meal [hamburgerList=[香辣鸡腿堡, 香辣鸡腿堡], juicesList=[大杯冰可乐, 大杯九珍果汁], chipsList=[], otherItemList=[热牛奶, 香辣鸡翅]]

这样,一个Builder模式的示例就完成了。

三、简化后的构建者模式

一般在使用的情况下,Builder只有一个,且不需要Diractor的。如下面一个结果返回的示例:

  • Result
代码语言:javascript
复制
package com.wangmengjun.tutorial.designpattern.builder;

public class Result {

  private ResultType type;
  
  private String code;
  
  private String message;
  
  private Object data;

  /**
   * @return the type
   */
  public ResultType getType() {
    return type;
  }

  /**
   * @param type the type to set
   */
  public void setType(ResultType type) {
    this.type = type;
  }

  /**
   * @return the code
   */
  public String getCode() {
    return code;
  }

  /**
   * @param code the code to set
   */
  public void setCode(String code) {
    this.code = code;
  }

  /**
   * @return the message
   */
  public String getMessage() {
    return message;
  }

  /**
   * @param message the message to set
   */
  public void setMessage(String message) {
    this.message = message;
  }

  /**
   * @return the data
   */
  public Object getData() {
    return data;
  }

  /**
   * @param data the data to set
   */
  public void setData(Object data) {
    this.data = data;
  }

  @Override
  public String toString() {
    return "Result [type=" + type + ", code=" + code + ", message=" + message + ", data=" + data + "]";
  }
  
  
}
  • 结果类型
代码语言:javascript
复制
package com.wangmengjun.tutorial.designpattern.builder;

public enum ResultType {
  SUCCESS, FAILURE, TIMED_OUT, UNKNOWN;
}
  • ResultBuilder类
代码语言:javascript
复制
package com.wangmengjun.tutorial.designpattern.builder;

public class ResultBuilder {

  private ResultType type;
  private String code;
  private String message;
  private Object data;
  
  public static ResultBuilder newInstance() {
    return new ResultBuilder();
  }
  
  public ResultBuilder type(ResultType type) {
    this.type = type;
    return this;
  }
  
  
  public ResultBuilder code(String code) {
    this.code = code;
    return this;
  }
  
  
  public ResultBuilder message(String message) {
    this.message = message;
    return this;
  }
  
  public ResultBuilder data(Object data) {
    this.data = data;
    return this;
  }
  
  public Result build() {
    Result result = new Result();
    result.setCode(code);
    result.setData(data);
    result.setMessage(message);
    result.setType(type);
    return result;
  }
}
  • 测试一下,使用Builder来构建结果。
代码语言:javascript
复制
package com.wangmengjun.tutorial.designpattern.builder;

public class BuilderMain {

  public static void main(String[] args) {
    Result result1 = ResultBuilder.newInstance().type(ResultType.SUCCESS)
                  .message("success message")
                  .code("code123456")
                  .build();
    //Result [type=SUCCESS, code=code123456, message=success message, data=null]
    System.out.println(result1);
    
    
    Result result2 = ResultBuilder.newInstance().type(ResultType.TIMED_OUT)
        .message("timed-out message")
        .code("timedout123456")
        .data("abcdef")
        .build();
    //Result [type=TIMED_OUT, code=timedout123456, message=timed-out message, data=abcdef]
    System.out.println(result2);
  }
}

这种方式是否似曾相识,比如Guava的CacheBuilder,如:

代码语言:javascript
复制
    CacheBuilder.newBuilder()
          .maximumSize(10000)
          .expireAfterAccess(2, TimeUnit.MINUTES)
          .expireAfterWrite(10, TimeUnit.MINUTES)
          .initialCapacity(100)
          .build();

又如Curator中的:

代码语言:javascript
复制
        CuratorFramework curatorFramework = CuratorFrameworkFactory.
                builder().
                connectString(server.getConnectString()).
                sessionTimeoutMs(1000).
                retryPolicy(new RetryNTimes(3, 1000)).
                build();

这种流式风格的赋值方式更加直观和灵活。

四、小结

4.1 与抽象工厂的关系

抽象工厂和建造者模式相似,因为它也可以创建复杂的对象。主要的区别是建造是者模式着重于一步一步构建一个复杂对象。而抽象工厂着重于多个系列的产品对象(简单的或者复杂的)。建造者模式在最后的一步返回产品,而对于抽象工厂来说,产品是立即返回的。

4.2 小结

建造者模式的意图是将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。建造者模式是体现局部和整体关系的,产品是一步步构建,最终形成的一定是一个整体。

针对有诸多参数的复杂对象的创建,可能包含多个构造函数。在这种场景下,使用建造者模式的来进行创建对象,更加直观和灵活。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-09-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 孟君的编程札记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档