建造者模式是什么?

  • 建造者模式(Builder Pattern)又叫生成器模式,是一种对象构建模式。它可以将复杂对象的建造过程抽象出来(抽象类别),使这个抽象过程的不同实现方法可以构造出不同表现(属性)的对象。
  • 建造者模式是一步一步创建一个复杂的对象,它允许用户只通过指定复杂对象的类型和内容就可以构建它们,用户不需要知道内部的具体构建细节。

建造者模式所完成的内容就是通过将多个简单对象通过一步步的组装构建出一个复杂对象的过程。

那么,哪有这样的场景呢?
如你玩王者荣耀的时的初始化界面;有三条路、有树、有怪、有守卫塔等等,甚至依赖于你的网络情况会控制清晰度。当你换一个场景进行其他不同模式的选择时,同样会建设道路、树、怪等等,但是他们的摆放和大小都有不同。这里就可以用到建造者模式来初始化游戏元素。
而这样的根据相同的 物料 ,不同的组装所产生出的具体的内容,就是建造者模式的最终意图,也就是将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。

场景模拟

这里我们模拟装修公司对于设计出一些套餐装修服务的场景。

物料

1
2
3
4
5
6
7
8
9
10
11
12
public interface Matter {
// 场景;地板、地砖、涂料、吊顶
String scene();
// 品牌
String brand();
// 型号
String model();
// 价格
BigDecimal price();
// 描述
String desc();
}

吊顶

  1. 一级吊顶
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class LevelOneCeiling implements Matter {
public String scene() {
return "吊顶";
}
public String brand() {
return "装修公司自带";
}
public String model() {
return "一级顶";
}
public BigDecimal price() {
rerturn new BigDecimal(260);
}
public String desc() {
return "造型只做低一级,只有一个层次的吊顶,一般离顶120-150mm";
}
}
  1. 二级吊顶
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class LevelOneCeiling implements Matter {
public String scene() {
return "吊顶";
}
public String brand() {
return "装修公司自带";
}
public String model() {
return "二级顶";
}
public BigDecimal price() {
rerturn new BigDecimal(850);
}
public String desc() {
return "两个层次的吊顶,二级吊顶高度一般就往下吊20cm,要是层高很高,也可增加每级的厚度";
}
}

涂料

  • 多乐士
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class DuluxCOat implements Matter {
public String scene() {
return "涂料";
}
public String brand() {
return "多乐士(Dulux)";
}
public String model() {
return "第二代";
}
public BigDecimal price() {
rerturn new BigDecimal(719);
}
public String desc() {
return "多乐士是阿克苏诺尔旗下的著名建筑装饰油漆品牌,产品畅销于全球100个国 家,每年全球有5000万户家庭使⽤多乐士油漆.";
}
}
  • 立邦
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class LiBangCoat implements Matter {
public String scene() {
return "涂料";
}
public String brand() {
return "立邦";
}
public String model() {
return "默认级别";
}
public BigDecimal price() {
return new BigDecimal(650);
}
public String desc() {
return "立邦始终以开发绿色产品、注重高科技、高品质为目标,以技术力量不断推进科研和开发,满足消费者需求。";
}
}

地板

  • 德尔
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class DerFloor implements Matter {
public String scene() {
return "地板";
}
public String brand() {
return "德尔(Der)";
}
public String model() {
return "A+";
}
public BigDecimal price() {
return new BigDecimal(119);
}
public String desc() {
return "DER德尔集团是全球领先的专业木地板制造商,北京2008年奥运会家装和公装地板供应商";
}
}
  • 圣象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class ShengXiangFloor implements Matter {
public String scene() {
return "地板";
}
public String brand() {
return "圣象";
}
public String model() {
return "一级";
}
public BigDecimal price() {
return new BigDecimal(318);
}
public String desc() {
return "圣象地板是中国地板行业著名品牌。圣象地板拥有中国驰名商标、中国名牌、国家免检、中国环境标志认证等多项荣誉。";
}
}

地砖

  • 东鹏
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class DongPengTile implements Matter {
public String scene() {
return "地砖";
}

public String brand() {
return "东鹏瓷砖";
}

public String model() {
return "10001";
}

public BigDecimal price() {
return new BigDecimal(102);
}

public String desc() {
return "东鹏瓷砖以品质铸就品牌,科技推动品牌,口碑传播品牌为宗旨,2014年品牌价值132 .35 亿元,位列建陶业榜第一。";
}
}
  • 马可波罗
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class MarcoPoloTile implements Matter {
public String scene() {
return "地砖";
}
public String brand() {
return "马可波罗(MARCO POLO)";
}
public String model() {
return "缺省";
}
public BigDecimal price() {
return new BigDecimal(140);
}
public String desc() {
return "“马可波罗”品牌诞生于1996年,作为国内最早品牌化的建陶品牌,以“文化陶瓷”占领市场,享有“仿古砖至尊”的美誉。";
}
}

材料构建完成,使用建造者模式

工程中有三个核心类和一个测试类,核心类是建造者模式的具体实现。具体功能如下;
Builder ,建造者类具体的各种组装由此类实现。
DecorationPackageMenu ,是 IMenu 接口的实现类,主要是承载建造过程中的填充器。相当于
这是一套承载物料和创建者中间衔接的内容。

好,那么接下来会分别讲解每个类的具体实现。

定义装修包接口

1
2
3
4
5
6
7
8
9
10
11
12
public interface IMenu {

IMenu appendCeiling(Matter matter); // 吊顶

IMenu appendCoat(Matter matter); // 涂料

IMenu appendFloor(Matter matter); // 地板

IMenu appendTile(Matter matter); // 地砖

String getDetail(); // 明细
}

装修包实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
public class DecorationPackageMenu implements IMenu {
private List<Matter> list = new ArrayList<Matter>(); // 装修清单
private BigDecimal price = BigDecimal.ZERO;
private BigDecimal area; // ⾯积
private String grade; // 装修等级;豪华欧式、轻奢⽥园、现代简约
private DecorationPackageMenu() {
}
public DecorationPackageMenu(Double area, String grade) {
this.area = new BigDecimal(area);
this.grade = grade;
}
public IMenu appendCeiling(Matter matter) {
list.add(matter);
price = price.add(area.multiply(new
BigDecimal("0.2")).multiply(matter.price()));
return this;
}
public IMenu appendCoat(Matter matter) {
list.add(matter);
price = price.add(area.multiply(new
BigDecimal("1.4")).multiply(matter.price()));
return this;
}
public IMenu appendFloor(Matter matter) {
list.add(matter);
price = price.add(area.multiply(matter.price()));
return this;
}
public IMenu appendTile(Matter matter) {
list.add(matter);
price = price.add(area.multiply(matter.price()));
return this;
}
public String getDetail() {
StringBuilder detail = new StringBuilder("\r\n--------------------
-----------------------------------\r\n" +
"装修清单" + "\r\n" +
"套餐等级:" + grade + "\r\n" +
"套餐价格:" + price.setScale(2, BigDecimal.ROUND_HALF_UP) +
" 元\r\n" +
"房屋面积:" + area.doubleValue() + " 平米\r\n" +
"材料清单:\r\n");
for (Matter matter: list) {
detail.append(matter.scene()).append(":").append(matter.brand()).append( "、").append(matter.model())
.append("、平米价格:").append(matter.price()).append(" 元。\n");
}
return detail.toString();
}
}

建造者方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class Builder {
public IMenu levelOne(Double area) {
return new DecorationPackageMenu(area, "豪华欧式")
.appendCeiling(new LevelTwoCeiling()) // 吊顶,二级顶
.appendCoat(new DuluxCoat()) // 涂料,多乐士
.appendFloor(new ShengXiangFloor()); // 地板,圣象
}
public IMenu levelTwo(Double area){
return new DecorationPackageMenu(area, "轻奢田园")
.appendCeiling(new LevelTwoCeiling()) // 吊顶,二级顶
.appendCoat(new LiBangCoat()) // 涂料,立邦
.appendTile(new MarcoPoloTile()); // 地砖,马可波罗
}
public IMenu levelThree(Double area){
return new DecorationPackageMenu(area, "现代简约")
.appendCeiling(new LevelOneCeiling()) // 吊顶,二级顶
.appendCoat(new LiBangCoat()) // 涂料,立邦
.appendTile(new DongPengTile()); // 地砖,东鹏
}
}

测试验证

1
2
3
4
5
6
7
8
9
10
@Test
public void test_Builder(){
Builder builder = new Builder();
// 豪华欧式
System.out.println(builder.levelOne(132.52D).getDetail());
// 轻奢⽥园
System.out.println(builder.levelTwo(98.25D).getDetail());
// 现代简约
System.out.println(builder.levelThree(85.43D).getDetail());
}

以上就是建造者模式的一个例子

建造者模式的注意细节

客户端(使用程序)不必知道产品内部组成的细节,将产品本身与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象
每一个具体建造者都相对独立,而与其他的具体建造者无关,因此可以很方便地替换具体建造者或增加新的具体建造者,用户使用不同的具体建造者即可得到不同
的产品对象
可以更加精细地控制产品的创建过程。将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰,也更方便使用程序来控制创建过程
增加新的具体建造者无须修改原有类库的代码,指挥者类针对抽象建造者类编程,系统扩展方便,符合开闭原则