文章目录
- 介绍
- 开始
- 架构图
- 样例一
- 定义生成器
- 定义具体生成器(HTML格式、markdown格式)
- 实体类
- HTML格式生成器
- MarkDown格式生成器
- 测试样例
- 总结
- 优点
- 缺点
介绍
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
如:大都市中林立着许多高楼大厦,这些高楼大厦都是具有建筑结构的大型建筑。通常,建造和构建这种具有建筑结构的大型物体在英文中称为Build
。
在建造大楼时,需要先打牢地基,搭建框架,然后自下而上地一层一层盖起来。通常,在建造这种具有复杂结构的物体时,很难一气呵成。我们需要首先建造组成这个物体的各个部分,然后分阶段将它们组装起来。
开始
架构图
样例一
定义生成器
public interface IBuilder {
/**
* 打开
*/
void open();
/**
* 建造一个 标题
*
* @param str
*/
void buildTitle(String str);
/**
* 生成托盘的父类
*
* @param str
*/
void buildString(String str);
/**
* 建造一个托盘
*
* @param myDomainList
*/
void buildTray(List<MyDomain> myDomainList);
/**
* 释放,结束
*/
void close();
}
定义具体生成器(HTML格式、markdown格式)
实体类
@Data
public class MyDomain implements Serializable {
/**
* 链接
*/
private String url;
/**
* 内容
*/
private String content;
}
HTML格式生成器
@Service
@Slf4j
public class HtmlBuilder implements IBuilder {
@Override
public void open() {
System.out.println("<html><head><title>HTML生成器</title></head><body>");
}
@Override
public void buildTitle(String str) {
System.out.println("<h1>" + str + "</h1>");
}
@Override
public void buildString(String str) {
System.out.println(str + "<ul>");
}
@Override
public void buildTray(List<MyDomain> myDomainList) {
for (MyDomain myDomain : myDomainList) {
System.out.println("<li><a href=\"" + myDomain.getUrl() + "\">" + myDomain.getContent() + "</a></li>");
}
System.out.println("</ul>");
}
@Override
public void close() {
System.out.println("</body></html>");
}
}
MarkDown格式生成器
@Service
@Slf4j
public class MarkDownBuilder implements IBuilder {
@Override
public void open() {
}
@Override
public void buildTitle(String str) {
System.out.println("# " + str);
System.out.println();
}
@Override
public void buildString(String str) {
System.out.println(str);
}
@Override
public void buildTray(List<MyDomain> myDomainList) {
for (MyDomain myDomain : myDomainList) {
System.out.println(" - [" + myDomain.getContent() + "](" + myDomain.getUrl() + ")");
}
System.out.println();
}
@Override
public void close() {
}
}
测试样例
@Slf4j
@SpringBootTest(classes = BuilderApplication.class)
public class TestBuilder {
@Resource
private Map<String, IBuilder> builderMap;
@Resource
private Director director;
@Test
public void testBuilder() {
for (Map.Entry<String, IBuilder> map : builderMap.entrySet()) {
log.info("----------------------------------------");
log.info("这是 : {} \n 准备开始建造", map.getKey());
director.printContent(map.getValue());
log.info("建造完毕");
log.info("----------------------------------------");
}
}
}
总结
优点
在 Builder类中,需要声明编辑文档(实现功能)所必需的所有方法。Director 类中使用的方法都是 Builder 类提供的。因此,在 Builder 类中应当定义哪些方法是非常重要的。而且,Builder类还必须能够应对将来子类可能增加的需求。
在示例程序中,我们只编写了支持MarkDown文档
的子类和支持 HTML 代码
的子类。但是将来可能还会希望能够编写其他形式(例如xxXx形式
)的文档。那时候,到底能不能编写出支持xxXx形式
的 xxXxBuilder类
呢?应该不需要新的方法吧?
虽然类的设计者并不是神仙,他们无法准确地预测到将来可能发生的变化。但是,我们还是有必要让设计出的类能够尽可能灵活地应对近期可能发生的变化。
缺点
他的优点便也是他的缺点。之后如果要支持新的xxXx形式
的文档,然而最初提供的方法并不满足他的要求,这个时候就要在生成器上添加方法,届时所有的实现类都要加上这个方法。
除此以外,还要关心加上了之后,会不会影响到我整体设计上。