设计模式(4):构造者模式 Builder

如果一个对象由多个元素组成,而且这些元素可组成不同的对象,用构造者模式去分离出这个对象的构造过程。

构造者模式 Builder

问题

An application needs to create the elements of a complex aggregate. The specification for the aggregate exists on secondary storage and one of many representations needs to be built in primary storage.

意图:

代码

例:比如一个网店卖包子=10块,饺子=20快,馒头=50块,很多用户一次买两样或三样都要点几次,于是使用构造者模式可以构造一个“套餐”,包子和饺子一走卖省5元,三个一起买省10元,除了方便用户,还带来了促销效果。

代码1:元数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.xdnote.DesignPattern.creational.bulider;
public enum Product {

PRODUCT1("包子",10),
PRODUCT2("馒头",50),
PRODUCT3("饺子",20);

private String name;
private int price;
private Product(String name1,int price1){
this.name=name1;
this.price=price1;
}
public String getName(){
return this.name;
}
public int getPirce(){
return this.price;
}
}

代码2:套餐类,用户买一个套餐就可知道套餐里面有什么内容

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
package com.xdnote.DesignPattern.creational.bulider;

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

public class Combo {
//套餐包含的产品
private List<Product> product ;

//套餐折扣
private int discount;
public Combo(){
this.product=new ArrayList<Product>();
this.discount=0;
}

public void setDiscount(int discount){
this.discount = discount;
}

public void addProduct(Product p){
this.product.add(p);
}

public String toString(){
int length=product.size();
StringBuffer sb=new StringBuffer("买了");
int total = 0;
for(int i=0;i<length;i++){
Product p = product.get(i);
total+=p.getPirce();
sb.append(p.getName()).append(" ");
}
sb.append(length).append("件物品");
sb.append("共").append(total).append("元");
sb.append("套餐优惠").append(this.discount).append("元");
sb.append("共").append(total-this.discount).append("元");
return sb.toString();

}
}

代码3:套餐构造类,及详细套餐的Bulider

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
package com.xdnote.DesignPattern.creational.bulider;

public abstract class ComboBulider {
//每个套餐制造者们都有自己的套餐属性,按照套餐属性订做套餐
private Combo combo;
//给套餐加入套餐需要的内容
public abstract void builder();
//给套餐对应的套餐优惠
public abstract void disCount();
//开始制作套餐
public void bulidCombo(){
this.combo = new Combo();
this.builder();
}
//取套餐
public Combo getCombo(){
return this.combo;
}

//套餐公用的方便代码
public void addProduct(Product p){
this.combo.addProduct(p);
}
public void setDiscount(int discount){
this.combo.setDiscount(discount);
}
}
public class Combo1Bulider extends ComboBulider{
@Override
public void builder() {
this.addProduct(Product.PRODUCT1);
this.addProduct(Product.PRODUCT3);
}
@Override
public void disCount() {
this.setDiscount(5);
}
}
public class Combo2Bulider extends ComboBulider{
@Override
public void builder() {
this.addProduct(Product.PRODUCT1);
this.addProduct(Product.PRODUCT2);
this.addProduct(Product.PRODUCT3);
}
@Override
public void disCount() {
this.setDiscount(10);
}

代码4:接口类,与客户端打交道的,这里为Server

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
package com.xdnote.DesignPattern.creational.bulider;

/**
* Server在Buider充当角色: 服务员
* 和工厂一样:接收命令,再返回最终需要的实体对象
* 和工厂不一样:工厂收到命令就直接做菜了,而构造收到命令后 要再给工厂去做,
* 工厂就好比杂货商,买一个馒头我就给你一个馒头,买一个包子我就给你一个包子,客户直接和你的生产地打交道
* 而构造则是买一个馒头,则告诉做馒头的伙计去做一个馒头,做完了,再取走,再给客户,客户只和你的服务员打交道
* */

/**
* 作为服务员:应该有
* 接收客户的命令(被点餐)
* 去厂房拿货(去通知作餐)
* 把货给客户(取餐,取餐给用户之前要打折)
* */

/**
* 适用性,
* */
public class Server {
//呼叫服务员
private ComboBulider bulider ;
public Server(){}

//服务员要知道客户需要什么,然后实例化需要的套餐制作人员
public void setBuider(ComboBulider bulider){
this.bulider = bulider;
}

public Combo getCombo(){
//通知套餐制作人员制作套餐
this.bulider.bulidCombo();
//服务员要完成打打折,当然他不知道具体的折扣
this.bulider.disCount();
//打完折后取餐
return this.bulider.getCombo();
}

}

代码5:客户端调用

1
2
3
4
5
6
7
8
9
10
11
public static void main(String[] args) {
Server server = new Server();
server.setBuider(new Combo1Bulider());
Combo combo = server.getCombo();
System.out.println(combo);

Server server2 = new Server();
server2.setBuider(new Combo2Bulider());
Combo combo2 = server2.getCombo();
System.out.println(combo2);
}

小结

构造者模式 Builder

个人在Java中好像非常少的使用,相反在Javascript里面还使用过一些,虽然是函数式的语言,但也可以用面向对象的思维去写嘛。比如prototype什么的。