建造者模式 build pattern 也叫做生成器模式。将一个复杂对象分解,可以构建不同内置部分的对象
UML图:
建造者模式的核心是 builder,builder根据需求进行结构顺序的重新组成或者构造,然后一个builder返回一个对应符合需求的产品,这个与工厂模式的区别在于,工厂模式是整体进行制造,而builder主要是通过改变其内部组成。
director导演类用来封装builder,使其细节不暴露,这样的话,可以将builder的方法进行私有化。达到保护细节的作用。
这个模式感觉可以再进行演变,和其他模式结合在一起使用,以下是实例
1.使用静态内部类构造宠物
本类的亮点在于通过静态内部类的方式来对实体类进行建造。
隐藏了私有方法,可以根据需要来设置需要的参数。比如可以将必填项删除掉,有选择的进行参数的构造。
/**
* 建造者模式
*/
public class Pet implements Serializable {
private static final long serialVersionUID = -2582687321051957354L;
/**
* 静态内部类
*/
public static class Builder implements Serializable {
private static final long serialVersionUID = 3670075346133332769L;
private Animal animal;
private String petName;
private String ownerName;
private String address;
private String telephone;
private Date dateOfbirth;
private String emailAddress;
public Builder withEmailAddress(String emailAddress) {
this.emailAddress = emailAddress;
return this;
}
public Builder withAnimal(Animal animal) {
this.animal = animal;
return this;
}
public Builder withPetName(String petName) {
this.petName = petName;
return this;
}
public Builder withOwnerName(String ownerName) {
this.ownerName = ownerName;
return this;
}
public Builder withAddress(String address) {
this.address = address;
return this;
}
public Builder withTelephone(String telephone) {
this.telephone = telephone;
return this;
}
public Builder withDateOfbirth(Date dateOfbirth) {
this.dateOfbirth = dateOfbirth;
return this;
}
public Pet build() {
if (null == address ||
null == petName ||
null == ownerName ||
null == dateOfbirth ||
null == emailAddress ||
null == telephone) {
throw new IllegalStateException("Cannot create Pet");
}
return new Pet(animal, petName, ownerName, address, telephone, dateOfbirth, emailAddress);
}
}
private Animal animal;
private String petName;
private String ownerName;
private String address;
private String telephone;
private Date dateOfBirth;
private String emailAdrress;
private Pet(Animal animal, String petName, String ownerName, String address, String telephone, Date dateOfBirth, String emailAdrress) {
this.animal = animal;
this.petName = petName;
this.ownerName = ownerName;
this.address = address;
this.telephone = telephone;
this.dateOfBirth = dateOfBirth;
this.emailAdrress = emailAdrress;
}
/**
* 测试方法
* @param args
*/
public static void main(String[] args) {
// 声明构造器
Pet.Builder build = new Pet.Builder();
// 构造对象
Pet pet = build.withAnimal(Animal.DOG)
.withPetName("lily")
.withOwnerName("smith")
.withTelephone("132345555")
.withAddress("123 high street")
.withDateOfbirth(new Date())
.withEmailAddress("1234@qq.com")
.build();
System.out.println(pet);
}
}
2. 不同宝马车和奔驰车的建造,
以下示例对车类的行为进行抽象,共同的部分和不同的本分分别实现
建造者实际上也可以使用一个实现类,但是如果需要更多的细节,可以封装在建造者当中,以下示例中将车的次序封装在到导演类中实际上不太好,应该将这部分封装在不同的builder当中,然后导演类直接调用更为妥当,导演类中展示了太多细节部分。
宝马的共性:启动、停止、鸣笛、引擎响,跑
以上的顺序四辆跑车各不相同,顺序由客户来决定,决定的 顺序使用List<String> 集合来组装,然后遍历出来执行
A宝马:只有启动、停止,没有鸣笛和引擎响
B宝马:先引擎响,然后启动、停止,没鸣笛
A奔驰:先鸣笛、再的启动,然后停车
B奔驰:先启动,然后一路跑,不需要停止、鸣笛、引擎、一直跑
抽象类车:
public abstract class AbstractCarModel {
private List<String> seq;
protected abstract void start();
protected abstract void stop();
protected abstract void alarm();
protected abstract void engineBoom();
/**
* 遍历执行顺序
*/
protected void run(){
for (String step : seq) {
if ("start".equals(step.toLowerCase())) {
this.start();
}
if ("stop".equals(step.toLowerCase())) {
this.stop();
}
if ("alarm".equals(step.toLowerCase())) {
this.alarm();
}
if ("engineBoom".equals(step.toLowerCase())) {
this.engineBoom();
}
}
}
/**
* 设置执行顺序
* @param seq
*/
protected void setSeq(List<String> seq){
this.seq = seq;
}
}
宝马车及奔驰车实现类
public class BMWModel extends AbstractCarModel {
public void start() {
System.out.println("宝马启动");
}
public void stop() {
System.out.println("宝马停车");
}
public void alarm() {
System.out.println("宝马鸣笛");
}
public void engineBoom() {
System.out.println("宝马引擎响");
}
}
public class BENZModel extends AbstractCarModel {
public void start() {
System.out.println("奔驰启动");
}
public void stop() {
System.out.println("奔驰停车");
}
public void alarm() {
System.out.println("奔驰鸣笛");
}
public void engineBoom() {
System.out.println("奔驰引擎响");
}
}
抽象类建造类:
public abstract class AbstractCarBuilder {
protected abstract AbstractCarModel getCarModel();
protected abstract void setSeq(List<String> seq);
}
宝马车及奔驰车建造实现类
public class BMWBuilder extends AbstractCarBuilder {
private AbstractCarModel bmw = new BMWModel();
@Override
public AbstractCarModel getCarModel() {
return bmw;
}
@Override
public void setSeq(List<String> seq) {
bmw.setSeq(seq);
}
}
public class BENZBuilder extends AbstractCarBuilder {
private AbstractCarModel benz = new BENZModel();
@Override
protected AbstractCarModel getCarModel() {
return benz;
}
@Override
protected void setSeq(List<String> seq) {
benz.setSeq(seq);
}
}
3. 建造者模式可以用作不同的数据处理handler,比如同步表中记录了需要不同handler进行处理的数据记录,此时的handler也类似于建造者中的一个个builder分别处理针对数据进行不同的处理,这样开发者编写不同的handler进行数据处理,而查询出来的数据根据handler的不一样进行处理,以下尝试做一个模式演示:
job的调用采用web方式进行(controller)调用
以下主要模拟相应的handler进行实现。使用一个map容器来装载相应的TransHandler实例,这个有点像容器模式了。
(1) 定义接口
public interface TransHandler {
void execute(JobEntity param);
}
(2) 一个抽象类继承它,并且编写实例注册方法
public abstract class AbstractTransHandler implements TransHandler {
@PostConstruct
public void registerHandler(){
String handlerName = this.getClass().getSimpleName();
// 截取开头及到transhandler部分作为key进行存储
handlerName = handlerName.substring(0, handlerName.lastIndexOf("TransHandler"));
TransHandlerManager.register(handlerName.toLowerCase(),this);
}
}
(3) 编写处理实例,并且让实例随着spring容器启动实例化
/**
* 随spring容器启动的时候,执行PostStruct标记的方法即完成了相应的TransHandler注册
*/
@Service
public class SpiderTransHandler extends AbstractTransHandler{
@Override
public void execute(JobEntity param) {
System.out.println("dosomething with param");
}
}
(4) 上述引用的容器类工具
public class TransHandlerManager {
private static Map<String, Object> handlers = new ConcurrentHashMap<>(100);
private TransHandlerManager() {
}
public static void register(String key, TransHandler handler){
if (null!= handler && null== handlers.get(key)&& null != key){
handlers.put(key, handler);
}
}
public static TransHandler getHandler(String key){
return (TransHandler) handlers.get(key);
}
}