(设计模式)建造者模式

第二篇:建造者模式

什么是建造者模式

建造者模式是一步一步创建一个复杂对象,允许用户不了解细节的情况下精细的控制对象的构造过程。使得复杂对象的构建与他的表示相分离,同样的构造过程可以创建不同的表示。

经典模式

在生活中我们经常买票,各种各样的票,我们这里要创建一个可以售卖多种票的程序。
首先是产品Product,他是一个抽象类,他有各种票都有的特征,以及票在购买当中会经历的状态,check,检测这张票的信息是否可靠(如生成时间,设备,渠道等),pay,对这张票进行支付,query,查询这张票的支付状态(如,金额是否一致等)

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
package top.huyuxin.builder;

public abstract class Ticket {
protected String ticketname;
protected boolean isCheck=false;
protected boolean isPayed=false;
protected boolean isQuery=false;

public Ticket() {
super();
}

public abstract void setTicketname();

public void setCheck(boolean isCheck) {
this.isCheck = isCheck;
}

public void setPayed(boolean isPayed) {
this.isPayed = isPayed;
}

public boolean isQuery() {
return isQuery;
}

public void setQuery(boolean isQuery) {
this.isQuery = isQuery;
}

@Override
public String toString() {
return "Ticket [ticketname=" + ticketname + ", isCheck=" + isCheck + ", isPayed=" + isPayed + ", isQuery="
+ isQuery + "]";
}

}

现在这个程序出售两种票,一种火车票,一种汽车票

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package top.huyuxin.builder;
/**
*火车票
**/
public class TrainTicket extends Ticket {


public TrainTicket() {
super();
}

@Override
public void setTicketname() {
ticketname=TrainTicket.class.getSimpleName();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package top.huyuxin.builder;
/**
*汽车票
**/
public class BusTicket extends Ticket {


public BusTicket() {
super();
}

@Override
public void setTicketname() {
ticketname=BusTicket.class.getSimpleName();
}

}

处理两种票的逻辑应该是一致的。

1
2
3
4
5
6
7
8
9
10
11
package top.huyuxin.builder;

public abstract class TicketSeller {

public abstract void createTicket(); //创建票
public abstract void checkTicket(); //检查票的生成信息
public abstract void payTicket(); //支付
public abstract void queryTicket(); //查询
public abstract void drawTicket(); //出票

}

但是细节肯定是不一致的,所以我们创建两个不同的Builder

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
package top.huyuxin.builder;

public class TrainTicketSeller extends TicketSeller {

private TrainTicket ticket;

@Override
public void createTicket() {
ticket=new TrainTicket();
ticket.setTicketname();
}

@Override
public void checkTicket() {
ticket.isCheck=true;

}

@Override
public void payTicket() {
ticket.isPayed=true;
}

@Override
public void queryTicket() {
ticket.isQuery=true;
}

@Override
public void drawTicket() {
System.out.println(ticket.toString());
}
}
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
package top.huyuxin.builder;

public class BusTicketSeller extends TicketSeller {

private BusTicket busticket;

@Override
public void createTicket() {
busticket=new BusTicket();
busticket.setTicketname();
}

@Override
public void checkTicket() {
busticket.isCheck=true;
}

@Override
public void payTicket() {
busticket.isPayed=true;
}

@Override
public void queryTicket() {
busticket.isQuery=true;
}
@Override
public void drawTicket() {
System.out.println(busticket.toString());
}

}

当在完成票的生成到出票的过程,顺序应该是一定的,不能还没生成票就去支付,还没支付就去查询。所以需要一个指挥者(Director)来控制他们的进程

1
2
3
4
5
6
7
8
9
10
11
12
package top.huyuxin.builder;

public class TicketProgram {

public static void sellTicket(TicketSeller ticketSeller){
ticketSeller.createTicket();
ticketSeller.checkTicket();
ticketSeller.payTicket();
ticketSeller.queryTicket();
ticketSeller.drawTicket();
}
}

这样我们就可以安心售票了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package top.huyuxin.builder;

public class Main {

public static void main(String[] args) {
TrainTicketSeller ticketSeller =new TrainTicketSeller();
BusTicketSeller busTicketSeller=new BusTicketSeller();

TicketProgram.sellTicket(ticketSeller);
TicketProgram.sellTicket(busTicketSeller);
TicketProgram.sellTicket(ticketSeller);

}

}

结果:

1
2
3
Ticket [ticketname=TrainTicket, isCheck=true, isPayed=true, isQuery=true]
Ticket [ticketname=TrainTicket, isCheck=true, isPayed=true, isQuery=true]
Ticket [ticketname=BusTicket, isCheck=true, isPayed=true, isQuery=true]

当我们的程序需要买别的票的时候,只需要再次继承抽象类Ticket,并创建处理对应票的Builder就可以了,在TicketProgram 里我们通过依赖注入的方式,使得即使有新的票出售只要逻辑一致,也能正常控制票的出售。
在经典的建造者模式当中Director的控制流程应该是可变的,创建多个不同的sellTicket()方法,通过调动builder的执行顺序产生不同的结果。这就是建造者模式。

填充模式

填充模式,你可能没听过,因为这是我自己起的名字。很多时候对象的构建伴随着很多很多参数的初始化,并且这些参数又不得不先初始化好,大量的setter和getter需要一个管理者来管理一波。比如刚刚的买票,买票可以但是现在的票都是实名制的,在购票前应先获取购票人信息。
于是就有了下面的代码:

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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
package top.huyuxin.builder;

public abstract class Ticket {
protected String ticketname;
protected boolean isCheck=false;
protected boolean isPayed=false;
protected boolean isQuery=false;

protected String holdername;
protected String sex;
protected int age;
protected String birthday;
protected String address;

public Ticket() {
super();
}

public abstract void setTicketname();

public void setCheck(boolean isCheck) {
this.isCheck = isCheck;
}

public void setPayed(boolean isPayed) {
this.isPayed = isPayed;
}

public boolean isQuery() {
return isQuery;
}

public void setQuery(boolean isQuery) {
this.isQuery = isQuery;
}

public String getTicketname() {
return ticketname;
}

public void setTicketname(String ticketname) {
this.ticketname = ticketname;
}

public String getHoldername() {
return holdername;
}

public void setHoldername(String holdername) {
this.holdername = holdername;
}

public String getSex() {
return sex;
}

public void setSex(String sex) {
this.sex = sex;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

public String getBirthday() {
return birthday;
}

public void setBirthday(String birthday) {
this.birthday = birthday;
}

public String getAddress() {
return address;
}

public void setAddress(String address) {
this.address = address;
}

public boolean isCheck() {
return isCheck;
}

public boolean isPayed() {
return isPayed;
}

@Override
public String toString() {
return "Ticket [ticketname=" + ticketname + ", isCheck=" + isCheck + ", isPayed=" + isPayed + ", isQuery="
+ isQuery + "]";
}

}

这使得原来逻辑清晰的Ticket类变得杂乱不堪,由于setter和getter过多可能在初始化的时候你可能漏了用户的sex或则age没有填上。
这里写图片描述
(翻不完的setter和getter)
于是我们创建一个对象信息的建造者,用来构建对象,在setter的时候我们return this这样使得可以链式调用,

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
50
51
52
53
54
55
56
57
58
package top.huyuxin.builder;

public class PersonInfo {
private String holdername;
private String sex;
private int age;
private String birthday;
private String address;

public static class Builder{

private String holdername;
private String sex;
private int age;
private String birthday;
private String address;

public Builder setHoldername(String holdername) {
this.holdername = holdername;
return this;
}
public Builder setSex(String sex) {
this.sex = sex;
return this;
}
public Builder setAge(int age) {
this.age = age;
return this;
}
public Builder setBirthday(String birthday) {
this.birthday = birthday;
return this;
}
public Builder setAddress(String address) {
this.address = address;
return this;
}

public PersonInfo create(){
PersonInfo personInfo=new PersonInfo();
personInfo.holdername=this.holdername;
personInfo.sex=this.sex;
personInfo.age=this.age;
personInfo.birthday=this.birthday;
personInfo.address=this.address;
return personInfo;

}


}

@Override
public String toString() {
return "PersonInfo [holdername=" + holdername + ", sex=" + sex + ", age=" + age + ", birthday=" + birthday
+ ", address=" + address + "]";
}
}

在Ticket类初始化的时候便写入的购票人信息

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
package top.huyuxin.builder;

public abstract class Ticket {
protected String ticketname;
protected boolean isCheck=false;
protected boolean isPayed=false;
protected boolean isQuery=false;

protected PersonInfo personInfo;


public Ticket(PersonInfo personInfo) {
super();
this.personInfo=personInfo;
}


public abstract void setTicketname();

public void setCheck(boolean isCheck) {
this.isCheck = isCheck;
}

public void setPayed(boolean isPayed) {
this.isPayed = isPayed;
}

public boolean isQuery() {
return isQuery;
}

public void setQuery(boolean isQuery) {
this.isQuery = isQuery;
}


@Override
public String toString() {
return "Ticket [ticketname=" + ticketname + ", personInfo=" + personInfo.toString() +", isCheck=" + isCheck + ", isPayed=" + isPayed + ", isQuery="
+ isQuery + "]";
}
}

在调用的时候也十分的清晰

1
2
3
4
5
6
7
8
9
		PersonInfo xiaoshuangInfo=new PersonInfo.Builder()
.setHoldername("小双")
.setSex("women")
.setAge(18)
.setBirthday("2000-01-01")
.setAddress("旮旯")
.create();
TicketProgram.sellTicket(ticketSeller,xiaoshuangInfo);
TicketProgram.sellTicket(busTicketSeller,xiaoshuangInfo);

结果:

1
2
Ticket [ticketname=BusTicket, personInfo=PersonInfo [holdername=小双, sex=women, age=18, birthday=2000-01-01, address=旮旯], isCheck=true, isPayed=true, isQuery=true]
Ticket [ticketname=TrainTicket, personInfo=PersonInfo [holdername=小双, sex=women, age=18, birthday=2000-01-01, address=旮旯], isCheck=true, isPayed=true, isQuery=true]

通过使用这个填充参数的填充模式使得Ticket对象的构建与表示分离。在填充模式中没有指挥官(Director)但是用于对象的构建还是搓搓有余。

您的一份奖励,就是我的一份激励