建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
一个 Builder 类会一步一步构造最终的对象。该 Builder 类是独立于其他对象的。
Bean的建造者对象BeanBuilder是可以写成两个类的
BeanBuilder.xxa().xxb().xxc().build();就会返回一个Bean对象
假设build一个人
PersonBuilder.head(head)
.arm(arm).arm(arm)
.leg(leg).leg(leg)
.body(body).build();
发现什么问题没
如果我这样写呢
PersonBuilder.head(head).head(head).head(head)
.arm(arm).arm(arm).arm(arm).arm(arm).arm(arm).arm(arm)
.leg(leg).leg(leg)
.body(body).build();
这人不就三头六臂了吗,显然不是每一个人都是哪吒,建造者模式适合做整体和局部都可以单独存在组合。
专业术语叫做聚合
聚合 aggregation
UML类图中用 空心菱形箭头 标识
整体和部分可以脱离各自而存在
比如大雁和雁群,比如早餐自选餐。我可以选择豆浆、油条、煎包,也可以选择拌面、胡辣汤 这些聚合起来叫早餐
那么我真的要new一个人应该怎么做呢
其实这里应该用模板设计模式更合适
在模板模式(Template Pattern)中,一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。这种类型的设计模式属于行为型模式。
我设计好一套方法,子类继承以后直接填就行
public abstract class Person {
abstract void setHead();
abstract void setLeftArm();
abstract void setRightArm();
abstract void setLeftLeg();
abstract void setRightLeg();
abstract void setBody();
//模板
public final void create(){
abstract void setHead();
abstract void setLeftArm();
abstract void setRightArm();
abstract void setLeftLeg();
abstract void setRightLeg();
abstract void setBody();
}
}
想new一个人,只要继承这个类,然后挨个填就行,还兼容杨过,子类只要setLeftArm(null)就可以了
专业术语叫组合 composition
UML类图中用实心菱形箭头标识
实际使用中,这两者往往没有很明确的界限,要根据实际场景自己选用和适配修改。
比如洗澡
建造者模式就是我可以 桑拿 洗澡 泡温泉 搓澡 随意选几样体验结束就可以。
模板模式就要 先淋浴 泡澡 搓澡 按顺序一条龙
当然也可以混合使用,设计对象的行为,抽象成我们日常的操作方式,会设计的更优雅和更好理解
比如我上篇需要构建一个表格对象
建造者模式 我需要set表头,一行内容或者多行内容,可以选择其中几样,表头也可以不传,约束较低使用灵活但是别人用起来会有理解成本。
// 对象列表,支持泛型,单个对象和list都可以传
List<OrderDTO> list = Lists.newArrayList();
list.add(new OrderDTO("12345","创建中"));
OrderDTO orderDTO = new OrderDTO("12346", "销毁");
// 不传表格表头名为字段名,字段别名map可以将字段名替换成自定义的名称
HashMap<String,String> tableHeadDisplayMap = new HashMap();
tableHeadDisplayMap.put("orderCode","单号");
// 建造json对象
TableResultUtil<OrderDTO> tableResultUtil = new TableResultUtil<OrderDTO>();
TableResult<OrderDTO> tableResult=TableResult.builder().tableHead(tableHeadDisplayMap)
.item(orderDTO)
.items(list).build();
String jsonData = tableResultUtil.createTableResult(tableResult);
模板模式
模板模式 我必须set表头,然后一项一项set数据进去,这样有约束,但是代码即文档。
// 使用
TableResultTemplateExampleImpl<OrderDTO> tableTemplate = new TableResultTemplateExampleImpl();
tableTemplate.buildTableHead("单号", "结果");
tableTemplate.buildTableBody("xyz123","模板设计模式");
// 按理说模板这里只放属性,create()这个职责应该给其他类,为了简便就写这里了
String jsonData = tableTemplate.create();
使用
public static void template() throws IOException {
// 任意对象
OrderDTO orderDTO = new OrderDTO("54320001","已过期");
// 创建模板set表头
TableTemplateImpl tableTemplate = new TableTemplateImpl();
tableTemplate.setTableHead("单号","状态");
TableResult4Template<TableTemplateImpl> tableResult =
TableResult4Template.builder()
.template(tableTemplate)
// set对象的属性,对应表格的内容
.items(orderDTO.getOrderCode(),orderDTO.getStatus())
.build();
String toolResult = tableResult.toJson();
// 表格头及数据
StringBuffer sBuffer = new StringBuffer();
List<String> tableHead = dealTableHead2(toolResult);
dealTableData2(toolResult,sBuffer);
// 导出成excel
String filePath = "D:\\模板设计模式" + System.currentTimeMillis()+".xls";
export(tableHead,sBuffer,filePath);
// 导出成html table
String htmltable = convertTaskResultToHtmlTable(tableHead,sBuffer);
System.out.println(htmltable);
}
结果 控制台
单号 | 状态 |
---|---|
54320001 | 已过期 |
<table border='1' cellspacing='0' cellpadding='3' align='center'><tr><th>单号</th><th>状态</th></tr><tr><td>54320001</td><td>已过期</td></tr></table>
filepath excel表格
模板设计模式1656141582396.xls
image-20220625152224211