建筑者模式
引言
设计模式也许就是把原来直的思路折弯。
或者是大的拆分成小的。
定义
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
最近用的例子
最近要开发一个一键周报的功能,功能就是将某个员工本周的工作日志整理成PPT的形式。
PPT包括整体信息(员工工号,姓名,汇报时间段,汇报类型)
概要(已完成任务,各任务占比)
具体内容(一个list包含多个子页ppt)
总结(summary)
这些子部分是可变且变化性比较大的,所以给这些子类都定义了单独类,最后创建一个构造这模式去讲这些部分组合成一个完整的PPT对象。
转弯
如果是常规思路,应该是新建一个PPTService,然后将所有业务逻辑都写在里面,这样的话
- 代码量大
- 每次修改的时候需要看的地方很多,如果你曾经写过大量代码的话一定会理解这样的痛苦
- 代码里最终一定会穿插越来越多的if-else
- 如果组合过程产生变化,就需要穿插大量的新的代码
- 如果提升到组件,这个无法做到,因为内嵌太多业务代码。
如果用了建造者模式的话,思路就转弯了不是直来直去的,他把原来一个类拆分成多个可组合的部分,这样某个部分产生变化只需要快速定位到那个部分的代码然后进行修改。
如果是组合产生变化,只要新增一个组合的部分,在构造器中调用组合的接口插入进去。
大拆小
如同三层架构一样,本来控制器——服务——DAO是放在一个类里的,后来被拆分到了三个类里,在后面无论是分布式还是企业应用开发都带来了极大的便利。这种行为在我看来是一种大拆小。
原来三个类的代码集中在一个类中的话,会像上述构造者模式使用之前的情况一样,代码爆炸,不易于修改,改动时需要看的代码量很大。
拆分后的好处也一样,只需要关注容易改变的地方。
这样看来构造者模式和三层架构也一样,也是将原本一个大串代码拆分成多个。
俗话大拆小,实际可能是用了设计原则:单一职责(将PPT类的多个部分[概要,内容,总结]拆分开,将某个类的三层架构拆分开,拆分的一方面是基于他们负责的不同,另一方面是他们经常会独立变化。)
多个抽象
构造者模式定义了多重构造类,实现同一接口,面向接口编程,可以随时切换实现类以切换组合方式。我没这么写。因为我这个是为我这个业务服务的,如果真的这么写的话,似乎就上升到架构层面了。
不止为任务写PPT,还为其他功能写PPT。
各个版本
第一版本,万能类
public class PPTService{
public PPT getPPT(String userNo,String startDate,String endDate){
PPT ppt = new PPT();
// 省略一千行获取公共信息的代码
// 省略一千行获取概要的代码
// 省略一千行获取详情的代码
// 省略一千行获取总结的代码
return ppt;
}
}
第二版本,职责拆分
好处:独立变化的部分被拆分开,方便修改和阅读。
缺点:没有抽象,假设这里新增了一个需要获取部门PPT(现在这个是个人的),需要重写一个接口,或者重写一个类。
public class PPTInfoService{
// 公共信息类
}
public class PPTOutlineService{
// 概要
}
public class PPTContentService{
// 详情
}
public class PPTSummaryService{
// 总结
}
public class Builder{
public PPT getppt(String userNo){
PPT ppt = new PPT();
ppt.setInfo(infoService.getinfo(userNo));
ppt.setOutLine(outlineService.getOutline(userNo));
// 省略其他获取
return ppt;
}
}
第三版本,构造者
不太标准的版本,因为我的构造器里只有一个getppt方法。这个例子中的Director有点多余,可以看一下下一个省略Director的模式。
public class Director{
public PPT getPPT(Builder builder,String userNo){
return builder.getppt(uerNo);
}
}
public class PersonalBuilder implements{
public PPT getppt(String userNo){
PPT ppt = new PPT();
// 省略其他获取
return ppt;
}
}
public class DeptBuilder implements Builder{
public PPT getppt(String userNo){
PPT ppt = new PPT();
// 省略其他获取
return ppt;
}
}
public static void main(String[] args){
Builder builder = new PersonalBuilder();
Direcotr director = new Director();
director.getppt(builder,"123");
}
public static void main(String[] args){
Builder builder = new DeptBuilder();
Direcotr director = new Director();
director.getppt(builder,"123");
}
第四版本 删掉director
是不是清爽很多,如果要切换builder直接切换即可,但是这个比较特殊,因为我吧构造过程都写在builder里了,下一个版本是将构造步骤写在director里,也是比较标准的版本,但是我觉得还的还是当前版本号
public class PersonalBuilder implements Builder{
public PPT getppt(String userNo){
PPT ppt = new PPT();
// 省略其他获取
return ppt;
}
}
public class DeptBuilder implements Builder{
public PPT getppt(String userNo){
PPT ppt = new PPT();
// 省略其他获取
return ppt;
}
}
public static void main(String[] args){
Builder builder = new PersonalBuilder();
// Builder builder = new DeptBuilder();
builder.getppt("123");
}
第五版本 标准版本
上面版本最不标准的地方在于,构造者有了搭建的能力。
真正的构造者模式有三个角色
客户端:Client调用代码的地方。
构造者:Builder构造的地方。
指导者:Director搭建的地方。
比如一个房子,构造者负责的是如何砌一面墙,如何建一个门,如何造一扇窗。
但是他不负责将这些组合成一个房子,组合成房子是指导者的事情。
同理,上述的PPT中,构造者不应该拥有直接组合PPT的能力,他只负责搭建ppt的各个部分,如何组合在一起是指导者的事情。且最终要提供一个返回一个完整ppt的接口。
public class PersonalBuilder implements Builder{
private PPT ppt;
public void builderInfo(String userNo){
ppt.setInfo(infoService.getInfo(userNo));
}
public void builderOutline(String userNo){
//代码省略
}
public void builderContent(String userNo){
//代码省略
}
public void builderSummary(String userNo){
//代码省略
}
public void getPPT(){
return ppt;
}
}
public class Director{
public PPT getPPT(Builder builder,String userNo){
builder.builderInfo();
builder.builderOutline();
builder.builderContent();
builder.builderSummary();
return builder.getPPT();
}
}
public static void main(String[] args){
Builder builder = new PersonalBuilder();
// Builder builder = new DeptBuilder();
Director director = new Director();
director.getPPT(builder,"123");
}
标准版本的交互图
共同学习,写下你的评论
评论加载中...
作者其他优质文章