设计模式之构建者模式(Builder):初步理解
构建者(Builder)设计模式(又叫生成器设计模式):
当一个类的内部数据过于复杂的时候(通常是负责持有数据的类,比如Config、VO、PO、Entity...),要创建的话可能就需要了解这个类的内部结构,还有这些东西是怎么组织装配等一大坨乱七八糟的东西,这个时候就会增加学习成本而且会很混乱,这个时候就想啊想一种什么法子来管理一下这个类中的数据呢,怎么在创建的时候让它按部就班的来,并且代码可读性很好别让我看花了眼啊,我要的东西也能都很好设置进来,这就是Builder模式的应用场景,Builder模式可以将一个类的构建和表示进行分离。
看一个例子:
- public class Student {
- private int id;
- private String name;
- private String passwd;
- private String sex;
- private String address;
- // 构造器尽量缩小范围
- private Student() {
- }
- // 构造器尽量缩小范围
- private Student(Student origin) {
- // 拷贝一份
- this.id = origin.id;
- this.name = origin.name;
- this.passwd = origin.passwd;
- this.sex = origin.sex;
- this.address = origin.address;
- }
- public int getId() {
- return id;
- }
- public String getName() {
- return name;
- }
- public String getPasswd() {
- return passwd;
- }
- public String getSex() {
- return sex;
- }
- public String getAddress() {
- return address;
- }
- /**
- * Student的创建完全依靠Student.Builder,使用一种方法链的方式来创建
- *
- */
- public static class Builder {
- private Student target;
- public Builder() {
- target = new Student();
- }
- public Builder address(int id) {
- target.id = id;
- return this;
- }
- public Builder name(String name) {
- target.name = name;
- return this;
- }
- public Builder password(String passwd) {
- target.passwd = passwd;
- return this;
- }
- public Builder sex(String sex) {
- target.sex = sex;
- return this;
- }
- public Builder address(String address) {
- target.address = address;
- return this;
- }
- public Student build() {
- return new Student(target);
- }
- }
- }
Student并不是直接new出来的,对其构造器进行了处理使其可访问范围尽可能的小,只让它通过Student.Builder来构建自己,在Student.Builder中提供了一种类set的方法链的方式来设置值,然后在最后的build()方法的时候会返回一个Student对象,现在要创建一个Student对象,代码如下:
- Student s=new Student.Builder().name("CC").password("qwerty").sex("男").address("银河系第二旋臂").build();
再对比一下如果不使用构造者模式(一般情况下的用法):
- /**
- * 学生实体
- * @author CC11001100
- *
- */
- public class Student {
- private int id;
- private String name;
- private String passwd;
- private String sex;
- private String address;
- public Student() {
- }
- public Student(String name, String passwd, String sex, String address) {
- super();
- this.name = name;
- this.passwd = passwd;
- this.sex = sex;
- this.address = address;
- }
- public int getId() {
- return id;
- }
- public void setId(int id) {
- this.id = id;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public String getPasswd() {
- return passwd;
- }
- public void setPasswd(String passwd) {
- this.passwd = passwd;
- }
- public String getSex() {
- return sex;
- }
- public void setSex(String sex) {
- this.sex = sex;
- }
- public String getAddress() {
- return address;
- }
- public void setAddress(String address) {
- this.address = address;
- }
- }
创建对象:
- Student s=new Student("CC","qwerty","男","银河系第二旋臂");
对比一下进行一个优劣性分析:
一般的套路:优点是比较简单,开发效率高,缺点是如果参数真的很多的话鬼知道每个对应的是什么意思啊。
Builder模式:优点是可以将构造器的setter方法名取成类似注释的方式,这样我们可以很清晰的知道刚才究竟设置的什么值,可读性较高,缺点是比较冗长。
总结:初步的理解Builder模式解决了要设置的参数过多不好管理的问题(感觉每次构建不同对象是废话 - -)。
从Struts2框架中拿出来的两个Builder模式的例子(都是Config类):
ActionConfig :
- public class ActionConfig extends Located implements Serializable {
- public static final String WILDCARD = "*";
- protected List<InterceptorMapping> interceptors; // a list of interceptorMapping Objects eg. List<InterceptorMapping>
- protected Map<String,String> params;
- protected Map<String, ResultConfig> results;
- protected List<ExceptionMappingConfig> exceptionMappings;
- protected String className;
- protected String methodName;
- protected String packageName;
- protected String name;
- protected Set<String> allowedMethods;
- protected ActionConfig(String packageName, String name, String className) {
- this.packageName = packageName;
- this.name = name;
- this.className = className;
- params = new LinkedHashMap<String, String>();
- results = new LinkedHashMap<String, ResultConfig>();
- interceptors = new ArrayList<InterceptorMapping>();
- exceptionMappings = new ArrayList<ExceptionMappingConfig>();
- allowedMethods = new HashSet<String>();
- allowedMethods.add(WILDCARD);
- }
- /**
- * Clones an ActionConfig, copying data into new maps and lists
- * @param orig The ActionConfig to clone
- * @Since 2.1
- */
- protected ActionConfig(ActionConfig orig) {
- this.name = orig.name;
- this.className = orig.className;
- this.methodName = orig.methodName;
- this.packageName = orig.packageName;
- this.params = new LinkedHashMap<String,String>(orig.params);
- this.interceptors = new ArrayList<InterceptorMapping>(orig.interceptors);
- this.results = new LinkedHashMap<String,ResultConfig>(orig.results);
- this.exceptionMappings = new ArrayList<ExceptionMappingConfig>(orig.exceptionMappings);
- this.allowedMethods = new HashSet<String>(orig.allowedMethods);
- }
- public String getName() {
- return name;
- }
- public String getClassName() {
- return className;
- }
- public List<ExceptionMappingConfig> getExceptionMappings() {
- return exceptionMappings;
- }
- public List<InterceptorMapping> getInterceptors() {
- return interceptors;
- }
- public Set<String> getAllowedMethods() {
- return allowedMethods;
- }
- /**
- * Returns name of the action method
- *
- * @return name of the method to execute
- */
- public String getMethodName() {
- return methodName;
- }
- /**
- * @return Returns the packageName.
- */
- public String getPackageName() {
- return packageName;
- }
- public Map<String, String> getParams() {
- return params;
- }
- public Map<String, ResultConfig> getResults() {
- return results;
- }
- public boolean isAllowedMethod(String method) {
- if (allowedMethods.size() == 1 && WILDCARD.equals(allowedMethods.iterator().next())) {
- return true;
- } else {
- return allowedMethods.contains(method);
- }
- }
- @Override public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (!(o instanceof ActionConfig)) {
- return false;
- }
- final ActionConfig actionConfig = (ActionConfig) o;
- if ((className != null) ? (!className.equals(actionConfig.className)) : (actionConfig.className != null)) {
- return false;
- }
- if ((name != null) ? (!name.equals(actionConfig.name)) : (actionConfig.name != null)) {
- return false;
- }
- if ((interceptors != null) ? (!interceptors.equals(actionConfig.interceptors)) : (actionConfig.interceptors != null))
- {
- return false;
- }
- if ((methodName != null) ? (!methodName.equals(actionConfig.methodName)) : (actionConfig.methodName != null)) {
- return false;
- }
- if ((params != null) ? (!params.equals(actionConfig.params)) : (actionConfig.params != null)) {
- return false;
- }
- if ((results != null) ? (!results.equals(actionConfig.results)) : (actionConfig.results != null)) {
- return false;
- }
- if ((allowedMethods != null) ? (!allowedMethods.equals(actionConfig.allowedMethods)) : (actionConfig.allowedMethods != null)) {
- return false;
- }
- return true;
- }
- @Override public int hashCode() {
- int result;
- result = (interceptors != null ? interceptors.hashCode() : 0);
- result = 31 * result + (params != null ? params.hashCode() : 0);
- result = 31 * result + (results != null ? results.hashCode() : 0);
- result = 31 * result + (exceptionMappings != null ? exceptionMappings.hashCode() : 0);
- result = 31 * result + (className != null ? className.hashCode() : 0);
- result = 31 * result + (methodName != null ? methodName.hashCode() : 0);
- result = 31 * result + (packageName != null ? packageName.hashCode() : 0);
- result = 31 * result + (name != null ? name.hashCode() : 0);
- result = 31 * result + (allowedMethods != null ? allowedMethods.hashCode() : 0);
- return result;
- }
- @Override public String toString() {
- StringBuilder sb = new StringBuilder();
- sb.append("{ActionConfig ");
- sb.append(name).append(" (");
- sb.append(className);
- if (methodName != null) {
- sb.append(".").append(methodName).append("()");
- }
- sb.append(")");
- sb.append(" - ").append(location);
- sb.append("}");
- return sb.toString();
- }
- /**
- * The builder for this object. An instance of this object is the only way to construct a new instance. The
- * purpose is to enforce the immutability of the object. The methods are structured in a way to support chaining.
- * After setting any values you need, call the {@link #build()} method to create the object.
- */
- public static class Builder implements InterceptorListHolder{
- private ActionConfig target;
- public Builder(ActionConfig toClone) {
- target = new ActionConfig(toClone);
- }
- public Builder(String packageName, String name, String className) {
- target = new ActionConfig(packageName, name, className);
- }
- public Builder packageName(String name) {
- target.packageName = name;
- return this;
- }
- public Builder name(String name) {
- target.name = name;
- return this;
- }
- public Builder className(String name) {
- target.className = name;
- return this;
- }
- public Builder defaultClassName(String name) {
- if (StringUtils.isEmpty(target.className)) {
- target.className = name;
- }
- return this;
- }
- public Builder methodName(String method) {
- target.methodName = method;
- return this;
- }
- public Builder addExceptionMapping(ExceptionMappingConfig exceptionMapping) {
- target.exceptionMappings.add(exceptionMapping);
- return this;
- }
- public Builder addExceptionMappings(Collection<? extends ExceptionMappingConfig> mappings) {
- target.exceptionMappings.addAll(mappings);
- return this;
- }
- public Builder exceptionMappings(Collection<? extends ExceptionMappingConfig> mappings) {
- target.exceptionMappings.clear();
- target.exceptionMappings.addAll(mappings);
- return this;
- }
- public Builder addInterceptor(InterceptorMapping interceptor) {
- target.interceptors.add(interceptor);
- return this;
- }
- public Builder addInterceptors(List<InterceptorMapping> interceptors) {
- target.interceptors.addAll(interceptors);
- return this;
- }
- public Builder interceptors(List<InterceptorMapping> interceptors) {
- target.interceptors.clear();
- target.interceptors.addAll(interceptors);
- return this;
- }
- public Builder addParam(String name, String value) {
- target.params.put(name, value);
- return this;
- }
- public Builder addParams(Map<String,String> params) {
- target.params.putAll(params);
- return this;
- }
- public Builder addResultConfig(ResultConfig resultConfig) {
- target.results.put(resultConfig.getName(), resultConfig);
- return this;
- }
- public Builder addResultConfigs(Collection<ResultConfig> configs) {
- for (ResultConfig rc : configs) {
- target.results.put(rc.getName(), rc);
- }
- return this;
- }
- public Builder addResultConfigs(Map<String,ResultConfig> configs) {
- target.results.putAll(configs);
- return this;
- }
- public Builder addAllowedMethod(String methodName) {
- target.allowedMethods.add(methodName);
- return this;
- }
- public Builder addAllowedMethod(Collection<String> methods) {
- target.allowedMethods.addAll(methods);
- return this;
- }
- public Builder location(Location loc) {
- target.location = loc;
- return this;
- }
- public ActionConfig build() {
- target.params = Collections.unmodifiableMap(target.params);
- target.results = Collections.unmodifiableMap(target.results);
- target.interceptors = Collections.unmodifiableList(target.interceptors);
- target.exceptionMappings = Collections.unmodifiableList(target.exceptionMappings);
- target.allowedMethods = Collections.unmodifiableSet(target.allowedMethods);
- ActionConfig result = target;
- target = new ActionConfig(target);
- return result;
- }
- }
- }
ExceptionMappingConfig:
- public class ExceptionMappingConfig extends Located implements Serializable {
- private String name;
- private String exceptionClassName;
- private String result;
- private Map<String,String> params;
- protected ExceptionMappingConfig(String name, String exceptionClassName, String result) {
- this.name = name;
- this.exceptionClassName = exceptionClassName;
- this.result = result;
- this.params = new LinkedHashMap<String,String>();
- }
- protected ExceptionMappingConfig(ExceptionMappingConfig target) {
- this.name = target.name;
- this.exceptionClassName = target.exceptionClassName;
- this.result = target.result;
- this.params = new LinkedHashMap<String,String>(target.params);
- }
- public String getName() {
- return name;
- }
- public String getExceptionClassName() {
- return exceptionClassName;
- }
- public String getResult() {
- return result;
- }
- public Map<String,String> getParams() {
- return params;
- }
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (!(o instanceof ExceptionMappingConfig)) {
- return false;
- }
- final ExceptionMappingConfig exceptionMappingConfig = (ExceptionMappingConfig) o;
- if ((name != null) ? (!name.equals(exceptionMappingConfig.name)) : (exceptionMappingConfig.name != null)) {
- return false;
- }
- if ((exceptionClassName != null) ? (!exceptionClassName.equals(exceptionMappingConfig.exceptionClassName)) : (exceptionMappingConfig.exceptionClassName != null))
- {
- return false;
- }
- if ((result != null) ? (!result.equals(exceptionMappingConfig.result)) : (exceptionMappingConfig.result != null))
- {
- return false;
- }
- if ((params != null) ? (!params.equals(exceptionMappingConfig.params)) : (exceptionMappingConfig.params != null))
- {
- return false;
- }
- return true;
- }
- @Override
- public int hashCode() {
- int hashCode;
- hashCode = ((name != null) ? name.hashCode() : 0);
- hashCode = (29 * hashCode) + ((exceptionClassName != null) ? exceptionClassName.hashCode() : 0);
- hashCode = (29 * hashCode) + ((result != null) ? result.hashCode() : 0);
- hashCode = (29 * hashCode) + ((params != null) ? params.hashCode() : 0);
- return hashCode;
- }
- /**
- * The builder for this object. An instance of this object is the only way to construct a new instance. The
- * purpose is to enforce the immutability of the object. The methods are structured in a way to support chaining.
- * After setting any values you need, call the {@link #build()} method to create the object.
- */
- public static class Builder{
- private ExceptionMappingConfig target;
- public Builder(ExceptionMappingConfig toClone) {
- target = new ExceptionMappingConfig(toClone);
- }
- public Builder(String name, String exceptionClassName, String result) {
- target = new ExceptionMappingConfig(name, exceptionClassName, result);
- }
- public Builder name(String name) {
- target.name = name;
- return this;
- }
- public Builder exceptionClassName(String name) {
- target.exceptionClassName = name;
- return this;
- }
- public Builder result(String result) {
- target.result = result;
- return this;
- }
- public Builder addParam(String name, String value) {
- target.params.put(name, value);
- return this;
- }
- public Builder addParams(Map<String,String> params) {
- target.params.putAll(params);
- return this;
- }
- public Builder location(Location loc) {
- target.location = loc;
- return this;
- }
- public ExceptionMappingConfig build() {
- target.params = Collections.unmodifiableMap(target.params);
- ExceptionMappingConfig result = target;
- target = new ExceptionMappingConfig(target);
- return result;
- }
- }
- }
参考资料:
设计模式之构建者模式(Builder):初步理解的更多相关文章
- 构建者模式Builder创建对象
构建者(Builder)设计模式(又叫生成器设计模式): 当一个类的内部数据过于复杂的时候(通常是负责持有数据的类,比如Config.VO.PO.Entity...),要创建的话可能就需要了解这个类的 ...
- 深入探索Java设计模式之构建器模式(五)
抽丝剥茧 细说架构那些事——[优锐课] 简单的程序不需要大量的设计过程,因为它们只关注有限的解决方案,仅使用几个类.大型程序专注于广泛的设计,该设计比好的设计范例的任何其他属性都更能利用可重用性.宏伟 ...
- 设计模式系列之建造者模式(Builder Pattern)——复杂对象的组装与创建
说明:设计模式系列文章是读刘伟所著<设计模式的艺术之道(软件开发人员内功修炼之道)>一书的阅读笔记.个人感觉这本书讲的不错,有兴趣推荐读一读.详细内容也可以看看此书作者的博客https:/ ...
- Net设计模式实例之建造者模式(Builder Pattern)
一.建造者模式简介(Brief Introduction) 建造者模式(Builder Pattern),将一个复杂对象的构建与它的表示分离,使的同样的构建过程可以创建不同的表示. 建造者模式的优点是 ...
- 【原】iOS设计模式之:建造者模式Builder Pattern,用于改进初始化参数
本文主要讨论一下iOS中的Builder Pattern.与网上很多版本不同,本文不去长篇大论地解释建造者模式的概念,那些东西太虚了.设计模式这种东西是为了解决实际问题的,不能为了设计模式而设计模式, ...
- iOS设计模式之:建造者模式Builder Pattern,用于改进初始化参数
转自:http://www.cnblogs.com/wengzilin/p/4365855.html 本文主要讨论一下iOS中的Builder Pattern.与网上很多版本不同,本文不去长篇大论地解 ...
- 构建者模式(Builder pattern)
构建者模式应用场景: 主要用来构建一些复杂对象,这里的复杂对象比如说:在建造大楼时,需要先打牢地基,搭建框架,然后自下向上地一层一层盖起来.通常,在建造这种复杂结构的物体时,很难一气呵成.我们需要首先 ...
- IOS设计模式浅析之建造者模式(Builder)
定义 "将一个复杂对象的构建与它的表现分离,使得同样的构建过程可以创建不同的表现". 最初的定义出现于<设计模式>(Addison-Wesley,1994). 看这个概 ...
- 设计模式 笔记 生成器(建造者)模式 Builder
//---------------------------15/04/08---------------------------- //builder 生成器(建造者)模式---对象创建型模式 /* ...
随机推荐
- transition代替简单的animation注意事项
一. transition 和 animation 不支持 Internet Explorer 9,以及更早的版本. 二. 要变化的属性 transition-property:要变化的属性, ...
- ProgressDialog的使用
ProgressDialog 继承自AlertDialog,AlertDialog继承自Dialog,实现DialogInterface接口. ProgressDialog的创建方式有两种,一种是ne ...
- 基于php的snmp管理端开发
一.系统环境: 操作系统:CentOS 5.4 内核:Linux_2.6 编译环境:gcc 4.1.2 代码版本:php-5.2.8.tar ...
- SVN迁移到Git的过程(+ 一些技巧)
SVN迁移到Git的过程(+ 一些技巧) 李顺利 Key Words SVN,Git,Clone,Conversion,Tips,VCS,Pro Git 关于在VCS中SVN和Git之间的迁移(Clo ...
- 40 网络相关函数(八)——live555源码阅读(四)网络
40 网络相关函数(八)——live555源码阅读(四)网络 40 网络相关函数(八)——live555源码阅读(四)网络 简介 15)writeSocket向套接口写数据 TTL的概念 函数send ...
- 一致性哈希算法以及其PHP实现
在做服务器负载均衡时候可供选择的负载均衡的算法有很多,包括: 轮循算法(Round Robin).哈希算法(HASH).最少连接算法(Least Connection).响应速度算法(Respons ...
- IIS 处理请求 原理
有时候我们会发现当我们访问一个IIS网站时,使用网址可以正常访问,但是使用IP却不行,这是什么原因呢? 原来IIS可以使用一个IP地址和端口绑定多个网站,这些网站的IP地址与端口都一样,因此在客户端或 ...
- 【leetcode】Word Ladder
Word Ladder Total Accepted: 24823 Total Submissions: 135014My Submissions Given two words (start and ...
- Wince下sqlce数据库开发(二)
上次写到使用数据绑定的方法测试本地sqlce数据库,这次使用访问SQL Server的方法访问sqlce,你会发现他们是如此的相似... 参考资料:http://www.cnblogs.com/rai ...
- POJ 2559
http://poj.org/problem?id=2559 题意:就是找出可以完整连接的最大的矩形面积. 思路:找出单独的一块矩形,往两边延伸,记录两边的比他高的矩形是在哪个位置,然后最右的位置减去 ...