8、Builder 建造者模式 组装复杂的实例 创造型模式
1、什么是Builder模式
定义:
将一个复杂对象的构建与表示相分离,使得同样的构建过程可以创建不同的表示。大白话就是,你不需要知道这个类的内部是什么样的,只用把想使用的参数传进去就可以了,达到了解耦的目的。
使用场景:
(1) 相同的方法,不同的执行顺序,产生不同的事件结果时。
(2) 多个部件或零件,都可以装配到一个对象中。但是产生的运行结果又不相同时。
(3) 产品类非常复杂,或者产品类中的调用顺序不同产生了不同的作用,这个时候使用建造者模式非常合适。
(4) 当初始化一个对象特别复杂,如参数多,且很多参数都具有默认值时。
2、示例
类的一览表:
示例类图:
定义Builder接口
package cn.design.create.builder; /**
* @author lin
* @version 1.0
* @date 2020-07-20 14:15
* @Description TODO
*/
public interface Builder { void makeTitle(String title); void makeString(String str); void makeItems(String[] item); void close();
}
定义HtmlBuilder类
package cn.design.create.builder; import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter; /**
* @author lin
* @version 1.0
* @date 2020-07-20 15:58
* @Description TODO
*/
public class HtmlBuilder implements Builder {
//文件名
private String filename;
//用于编写文件的PrintWriter
private PrintWriter writer; @Override
public void makeTitle(String title) {
// HTML文件的标题
//将标题作为文件名
filename = title + ".html";
try {
// 生成PrintWriter
writer = new PrintWriter(new FileWriter(filename));
} catch (IOException e) {
e.printStackTrace();
}
writer.println("<html><head><title>" + title + "</title></head><body>");
//输出标题
writer.println("<h1>" + title + "</h1>");
} @Override
public void makeString(String str) {
// HTML文件中的字符串
//用<p>标签输出
writer.println("<h4>" + str + "</h4>");
} @Override
public void makeItems(String[] items) {
// HTML文件中的条目
writer.println("<ul>");
//用<ul>和<li>输出
for (int i = 0; i < items.length; i++) {
writer.println("<li>" + items[i] + "</1i>");
}
writer.println("</ul>");
} @Override
public void close() {
//完成文档
writer.println("</body></html>");
//关闭标签
writer.close();
//关闭文件
} public String getResult() {
//编写完成的文档
//返回文件名
return filename;
}
}
定义TextBuilder类
package cn.design.create.builder; /**
* @author lin
* @version 1.0
* @date 2020-07-20 15:53
* @Description TODO
*/
public class TextBuilder implements Builder {
private StringBuffer buffer = new StringBuffer(); //又档内容保存在该子段中
@Override
public void makeTitle(String title) {
//纯文本的标题
buffer.append("=========================\n"); //装饰线
//为标题添加「」
buffer.append("「" + title + "」\n");
} @Override
public void makeString(String str) {
//纯文本的字符串.
//为字符串添加■
buffer.append(" ■" + str + "\n");
} @Override
public void makeItems(String[] items) {
//纯文本的条目
for (int i = 0; i < items.length; i++) {
//为条目添加.
buffer.append("\t● " + items[i] + "\n");
}
} @Override
public void close() {
//完成文档
// 装饰线
buffer.append("========================\n");
} public String getResult() {
//完成的文档
//将StringBuffer变换为String
return buffer.toString();
}
}
定义Director类
package cn.design.create.builder; /**
* @author lin
* @version 1.0
* @date 2020-07-20 14:18
* @Description TODO
*/
public class Director {
private Builder builder; public Director(Builder builder) {
//因为接收的参数是Builder类的子类
//所以可以将其保存在builder字段中
this.builder = builder;
} public void construct() {
//编写文档
//标题
builder.makeTitle("Greeting");
//字符串
builder.makeString("从早上至下午");
//条目
builder.makeItems(new String[]{
"早上好。",
"下午好。",
});
//其他字符串
builder.makeString("晚上");
//其他条目
builder.makeItems(new String[]{
"晚上好。",
"晚安。",
"再见。",
});
//完成文档
builder.close();
}
}
定义测试BuilderMain类
package cn.design.create.builder; /**
* @author lin
* @version 1.0
* @date 2020-07-20 13:53
* @Description TODO
*/
public class BuilderMain {
public static void main(String[] args) {
if (args.length != 1) {
usage();
System.exit(0);
}
if (args[0].equals("plain")) {
TextBuilder textbuilder = new TextBuilder();
Director director = new Director(textbuilder);
director.construct();
String result = textbuilder.getResult();
System.out.println(result);
} else if (args[0].equals("html")) {
HtmlBuilder htmlbuilder = new HtmlBuilder();
Director director = new Director(htmlbuilder);
director.construct();
String filename = htmlbuilder.getResult();
System.out.println(filename + "文件编写完成。");
} else {
usage();
System.exit(0);
}
} public static void usage() {
System.out.println("Usage: java Main plain 编写纯文本文档");
System.out.println("Usage: java Main html 编写HTML文档");
} }
运行结果:
plain:
=========================
「Greeting」
■从早上至下午
● 早上好。
● 下午好。
■晚上
● 晚上好。
● 晚安。
● 再见。
========================
html:
3、Builder模式中的角色
类图:
角色说明:
◆ Builder (建造者)
Builder角色负责定义用于生成实例的接口( API )。Builder 角色中准备了用于生成实例的方法。在示例程序中,由Builder类扮演此角色。
◆ ConcreteBuilder (具体的建造者)
ConcreteBuilder角色是负责实现Builder角色的接口的类(API)。这里定义了在生成实例时实际被调用的方法。此外,在ConcreteBuilder角色中还定义了获取最终生成结果的方法。在示例程序中,由TextBuilder类和HTMLBui lder类扮演此角色。
◆ Director (监工)
Director角色负责使用Builder角色的接口( API)来生成实例。它并不依赖于ConcreteBuilder角色。为了确保不论ConcreteBuilder角色是如何被定义的,Director 角色都能正常工作,它只调用在Builder角色中被定义的方法。在示例程序中,由Director类扮演此角色。
◆Client(使用者)
该角色使用了Builder 模式中,Builder 模式并不包含Client角色。在示例程序中,由Main类扮演此角色。
4、相关的设计模式对比
◆Template Method模式
在Builder模式中,Director 角色控制Builder角色。在Template Method模式中,父类控制子类。
◆Composite模式
有些情况下Builder模式生成的实例构成了Composite模式。
◆Abstract Factory模式
Builder模式和Abstract Factory模式都用于生成复杂的实例。
◆Facade模式
在Builder模式中,Director 角色通过组合Builder角色中的复杂方法向外部提供可以简单生成实例的接口( API)(相当于示例程序中的construct方法)。Facade模式中的Facade角色则是通过组合内部模块向外部提供可以简单调用的接口( API)。
5、小结
为了灵活构造复杂对象,该对象会有多个成员变量,在外部调用的时候,不需要或者不方便一次性创建出所有的成员变量,在这种情况下,使用多个构造方法去构建对象,很难维护,这时候Builder设计模式解决这个问题,进行buid()方法中创建对象,并且将builder传入,该builder中,维护了传入对象的成员变量。
优点:
我可以不必知道你的内部构造是怎样的,我可以直接使用Builder建造自己需要的客户端;代码清晰,易维护,易扩展;将构造和表示分离,降低耦合
缺点:
代码也可能不清晰,不易维护(怎么说:比如你的客户端实现了很多接口,当你每当修改接口的时候,每次都要对应修改你的客户端);使用不恰当消耗内存
6、Main方法如何为args传参
参数举例: 123 456 abc def 1. 编译器idea的使用方式:
在 main 的 启动配置中 ,在程序参数中 填入自己需要的值
2. 黑窗口的使用方式:
不使用包路径, 大家都会. javac XXX.java 执行 java XXX abc def 123
使用包路径,则要注意, javac -d . XXX.java 执行 java cn.**.XXX 123 456
第一种参考如下:
第二种参考如下:
javac -d . cn.fagejiang.Test.java
java cn.fagejiang.Test plain
发哥讲
如果你觉得文章还不错,就请点击右上角选择发送给朋友或者转发到朋友圈~
● 扫码关注公众号, 转载请备注来源,和链接
8、Builder 建造者模式 组装复杂的实例 创造型模式的更多相关文章
- 7、Prototype 原型模式 通过复制创造实例 创造型模式
2020-07-19 发哥讲 发哥讲 其实上一节的末尾讲到如何去生成对象,其中有一个关于clone的,这其实就是Prototype原型模式. 通过克隆(拷贝)的方式生成对象 1.了解Prototype ...
- [WCF编程]7.实例上下文模式
一.实例上下文模式概述 实例上下文(IntanceContext Mode)表示服务端的服务实例与客户端的服务代理的绑定方式. 在实例化服务器对象时,WCF采用了3种不同的模式:单调(Per-Call ...
- 一天一个设计模式——Builder建造者模式
一.模式说明 在现实世界中,当我们要构造一个大型工程时(建一个大楼),通常的做法是先建造工程的每个独立部分,然后再逐步构造完成(先打地基,再搭框架,最后逐层累造).在程序设计领域,构造一个复杂的类时( ...
- Android设计模式——Builder(建造者)模式
1.建造者模式是一步一步创建一个复杂对象的创建模式.该模式是为了将构建复杂对象的过程和他的部件解耦,使得构建过程和部件表示隔离开. 2.Bulider模式的定义是:将一个复杂对象的构建与它的表示分离, ...
- WCF实例上下文模式与并发模式对性能的影响
实例上下文模式 InstanceContextMode 控制在响应客户端调用时,如何分配服务实例.InstanceContextMode 可以设置为以下值: •Single – 为所有客户端调用分配一 ...
- MVC实例应用模式
MVC实例应用模式 1.可用性: 比如异常处理 2.可修改性: 比如用接口实现 3.性能战术: 4.易用性战术: 分层实现 5.可测试性战术: 实现对其接口进行测试,并不需要对其实现方法进行 6.安全 ...
- MVC(Model -View-Controller)实例应用模式
MVC(Model -View-Controller)实例应用模式 以登录为例: Model:User package com.keith.bean; public class TUser imple ...
- WCF - 服务实例管理模式
WCF 提供了三种实例上下文模式:PreCall.PreSession 以及 Single.开发人员通过 ServiceBehavior.InstanceContextMode 就可以很容易地控制服务 ...
- 抽象工厂模式(Abstract Factory)C#实例
抽象工厂模式(Abstract Factory)C#实例 本文出处http://www.dofactory.com/net/abstract-factory-design-pattern 一.场景描述 ...
随机推荐
- web 部署专题(九):Nginx 前后端分离中csrf_token 认证的实现
1. 思路 参考:https://stackoverflow.com/questions/20826201/simple-csrf-protection-using-nginx-alone?r=Sea ...
- 数据载入、存储及文件格式知识图谱-《利用Python进行数据分析》
所有内容整理自<利用Python进行数据分析>,使用MindMaster Pro 7.3制作,emmx格式,源文件已经上传Github,需要的同学转左上角自行下载或者右击保存图片.
- Quartz.Net系列(十六):通过Plugins模式使用Xml方式配置Job和Trigger和自定义LogPrivider
1.简单介绍 Quarz.Net中采用插件式来实现配置文件配置,通过XMLSchedulingDataProcessor类进行Xml数据处理 默认配置文件命名:quart_jobs.xml publi ...
- bzoj4459[Jsoi2013]丢番图
bzoj4459[Jsoi2013]丢番图 题意: 丢番图方程:1/x+1/y=1/n(x,y,n∈N+) ,给定n,求出关于n的丢番图方程有多少组解.n≤10^14. 题解: 通分得yn+xn=xy ...
- ffmpeg源码编译环境搭建
ffmpeg是视频开发最常用到的开源软件,FFmpeg功能强大,用途广泛,提供几乎所有你能够想到的与视频开发相关的操作,许多商业软件都以ffmpeg为基础进行开发定制. FFmpeg: FFmpeg ...
- 足球动图gif(二)
- fastjson将json字符串转化为java对象
目录 一.导入一个fastjson的jar包 二.Json字符串格式 三.根据json的格式创建Java类 四.给java类的所有属性添加setter方法 五.转换为java对象 一.导入一个fast ...
- Java继承之面向对象
面向对象与面向过程: 面向对象(OOP)与面向过程 二者都是一种思想,面向对象是相对于面向过程而言的. 面向过程,强调的是功能行为.面向对象,将功能封装进对象,强调具备了功能的对象. 面向对象更加强调 ...
- 谁能告诉我如何通过Jenkins完成分布式环境搭建并执行自动化脚本
今天我们接着昨天的内容,看一看如何完成Jenkins分布式环境的搭建和使用,因为我之前也是自己一个人摸索的,如果有不对的地方,请各位看官私信指出. 新增分布式部署节点 在系统管理/节点管理中点击新建 ...
- 前端学习(十):CSS选择器
进击のpython ***** 前端学习--CSS选择器 每一条CSS样式声明由两部分组成: 选择器{ 样式: } 在CSS中{}之前的部分就是"选择器","选择器&qu ...