設計模式之----建造者模式
建造者模式
抽象建造者(Builder)角色:給 出一個抽象介面,以規範產品物件的各個組成成分的建造。一般而言,此介面獨立於應用程式的商業邏輯。模式中直接建立產品物件的是具體建造者 (ConcreteBuilder)角色。具體建造者類必須實現這個介面所要求的兩種方法:一種是建造方法(buildPart1和 buildPart2),另一種是返還結構方法(retrieveResult)。一般來說,產品所包含的零件數目與建造方法的數目相符。換言之,有多少 零件,就有多少相應的建造方法。
導演者(Director)角色:擔任這個角色的類呼叫具體建造者角色以建立產品物件。應當指出的是,導演者角色並沒有產品類的具體知識,真正擁有產品類的具體知識的是具體建造者角色。
產品(Product)角色:產品便是建造中的複雜物件。一般來說,一個系統中會有多於一個的產品類,而且這些產品類並不一定有共同的介面,而完全可以是不相關聯的。
一般來說,每有一個產品類,就有一個相應的具體建造者類。這些產品應當有一樣數目的零件,而每有一個零件就相應地在所有的建造者角色裡有一個建造方法
要建立一個保險合同的物件,裡面很多屬性的值都有約束,要求創建出來的物件是滿足這些約束規則的。
約束規則如下:
a.保險合同通常情況下可以和個人簽訂,也可以和某個公司簽訂,但是一份保險合同不能同時與個人和公司簽訂。
b.保險失效日期,一定會大於保險開始生效日期
c.一份保險合同必須有生效的日期
d.一份保險合同必須有失效的日期
e.一份保險合同必須有保險物件
f.一份保險合同必須有保險編號
採用建造模式來構建複雜的物件,通常會對建造模式進行一定的簡化,因為目標明確,就是建立某個複雜物件,因此做適當簡化會使程式更簡潔。大致簡化如下:
● 由於是用Builder模式來建立某個物件,因此就沒有必要再定義一個Builder介面,直接提供一個具體的建造者類就可以了。
● 對於建立一個複雜的物件,可能會有很多種不同的選擇和步驟,乾脆去掉“導演者”,把導演者的功能和Client的功能合併起來,也就是說,Client這個時候就相當於導演者,它來指導構建器類去構建需要的複雜物件。
在本例中將具體建造者合併到了產品物件中,並將產品物件的建構函式私有化,防止客戶端不使用構建器來構建產品物件,而是直接去使用new來構建產品物件所導致的問題。另外,這個構建器的功能就是為了建立被構建的物件,完全可以不用單獨一個類。
圖片引用自部落格
package insuranceContract;
import java.text.SimpleDateFormat;
import java.util.Date;
import builder.InsuranceBuilder;
/**
* 保險合同類
*/
public class InsuranceContract {
//以下二者不能同時參與保險
private String personName;//被保險人姓名
private String companyName;//被保險公司名稱
private String id;//保險合同編號
private Date startDate;//生效日期
private Date endDate;//失效時間
public InsuranceContract(InsuranceBuilder builder){
this.id = builder.getId();
this.personName = builder.getPersonName();
this.companyName = builder.getCompanyName();
this.startDate = builder.getStartDate();
this.endDate = builder.getEndDate();
}
public void createInsurance(){
System.out.println("當前保險合同編號為:"+this.id);
if(personName != null){
System.out.println("被保險人姓名:"+personName);
}else if(companyName != null){
System.out.println("被保險公司名稱:"+companyName);
}
SimpleDateFormat sdf= new SimpleDateFormat("yyyy-MM-dd");
System.out.println("當前保險合同生效日期:"+sdf.format(startDate));
System.out.println("當前保險合同失效日期:"+sdf.format(endDate));
}
}
package builder;
import insuranceContract.InsuranceContract;
import java.util.Date;
/**
* 具體建造類
*/
public class InsuranceBuilder {
private String personName;// 被保險人姓名
private String companyName;// 被保險公司名稱
private String id;// 保險合同編號
private Date startDate;// 生效日期
private Date endDate;// 失效時間
public InsuranceBuilder(String id, Date startDate, Date endDate) {
this.id = id;
this.startDate = startDate;
this.endDate = endDate;
}
public InsuranceBuilder setPersonName(String personName) {
this.personName = personName;
return this;
}
public InsuranceBuilder setCompanyName(String companyName) {
this.companyName = companyName;
return this;
}
public InsuranceContract create() {
if (id.equals("") || id.trim().length() == 0) {
throw new IllegalArgumentException("保險合同編號不能為空!");
}
if (personName == null && companyName == null) {
throw new IllegalArgumentException("一份保險的簽訂物件不能為空!");
}
if(personName != null && companyName != null){
throw new IllegalArgumentException("一份保險不能同時與個人和公司簽訂!");
}
if (startDate == null) {
throw new IllegalArgumentException("一份保險必須有生效日期!");
}
if (endDate == null) {
throw new IllegalArgumentException("一份保險必須有失效日期!");
}
if (endDate.compareTo(startDate) <= 0) {
throw new IllegalArgumentException("一份保險失效日期必須大於生效日期!");
}
return new InsuranceContract(this);
}
public String getId() {
return id;
}
public Date getStartDate() {
return startDate;
}
public Date getEndDate() {
return endDate;
}
public String getPersonName() {
return personName;
}
public String getCompanyName() {
return companyName;
}
}
package client;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import builder.InsuranceBuilder;
import insuranceContract.InsuranceContract;
/**
* 客戶端類
*/
public class Client {
public static void main(String[] args){
SimpleDateFormat format= new SimpleDateFormat("yyyy-MM-dd");
Date startDate = null,endDate = null;
try {
startDate = format.parse("2018-10-24");
endDate = format.parse("2020-10-24");
} catch (ParseException e) {
e.printStackTrace();
}
InsuranceBuilder builder = new InsuranceBuilder("1001", startDate, endDate);
builder.setPersonName("張三");
//builder.setCompanyName("蘋果公司");
InsuranceContract contract = builder.create();
contract.createInsurance();
}
}