建造者模式浅析
- 2019 年 10 月 6 日
- 笔记
建造者模式是一种创建型的模式,其意图是将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
一、建造者模式的基本介绍
建造者的基本结构如下:

- Builder
- 为创建一个Product对象的各个部件指定抽象接口。
- ConcreteBuilder
- 实现Builder的接口以构造和装载该产品的各个部件
- 定义并明确它所创建的表示
- Director
- 构造一个使用Builder接口的对象
- Product
- 表示被构造的复杂对象。ConcreteBuilder创建该产品的内部表示并定义它的装配过程。
- 包括定义组成部件的类,包括将这些部件装配成最终产品的接口。
Note:建造者模式是体现局部和整体关系的,产品是一步步构建,最终形成的一定是一个整体。
就比如顾客去餐厅购买一份儿童餐,跟收银员说要汉堡、饮料、甜甜圈有额外的玩具等,最终顾客得到是包含所有的儿童餐,是一个整体。

二、Builder模式示例
接下来,我们以上述点餐的例子编写一个建造者模式的示例代码。
- 创建一个Meal类,作为Product。
- 产品包含汉堡列表、饮料列表等参数进行区分
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
- 支持单个或者多个添加元素
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)
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)
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)
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个香辣鸡腿堡,大杯冰可乐,大杯九珍果汁,热牛奶以及一个香辣鸡翅。
Meal [hamburgerList=[香辣鸡腿堡, 香辣鸡腿堡], juicesList=[大杯冰可乐, 大杯九珍果汁], chipsList=[], otherItemList=[热牛奶, 香辣鸡翅]]
这样,一个Builder模式的示例就完成了。
三、简化后的构建者模式
一般在使用的情况下,Builder只有一个,且不需要Diractor的。如下面一个结果返回的示例:
- Result

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 + "]"; } }
- 结果类型
package com.wangmengjun.tutorial.designpattern.builder; public enum ResultType { SUCCESS, FAILURE, TIMED_OUT, UNKNOWN; }
- ResultBuilder类

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来构建结果。
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,如:
CacheBuilder.newBuilder() .maximumSize(10000) .expireAfterAccess(2, TimeUnit.MINUTES) .expireAfterWrite(10, TimeUnit.MINUTES) .initialCapacity(100) .build();
又如Curator中的:
CuratorFramework curatorFramework = CuratorFrameworkFactory. builder(). connectString(server.getConnectString()). sessionTimeoutMs(1000). retryPolicy(new RetryNTimes(3, 1000)). build();
这种流式风格的赋值方式更加直观和灵活。
四、小结
4.1 与抽象工厂的关系
抽象工厂和建造者模式相似,因为它也可以创建复杂的对象。主要的区别是建造是者模式着重于一步一步构建一个复杂对象。而抽象工厂着重于多个系列的产品对象(简单的或者复杂的)。建造者模式在最后的一步返回产品,而对于抽象工厂来说,产品是立即返回的。
4.2 小结
建造者模式的意图是将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。建造者模式是体现局部和整体关系的,产品是一步步构建,最终形成的一定是一个整体。
针对有诸多参数的复杂对象的创建,可能包含多个构造函数。在这种场景下,使用建造者模式的来进行创建对象,更加直观和灵活。