建造者模式
抽象建造者(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();
}
}