构建者(Builder)设计模式(又叫生成器设计模式):

当一个类的内部数据过于复杂的时候(通常是负责持有数据的类,比如Config、VO、PO、Entity...),要创建的话可能就需要了解这个类的内部结构,还有这些东西是怎么组织装配等一大坨乱七八糟的东西,这个时候就会增加学习成本而且会很混乱,这个时候就想啊想一种什么法子来管理一下这个类中的数据呢,怎么在创建的时候让它按部就班的来,并且代码可读性很好别让我看花了眼啊,我要的东西也能都很好设置进来,这就是Builder模式的应用场景,Builder模式可以将一个类的构建和表示进行分离。

看一个例子:

  1. public class Student {
  2.  
  3. private int id;
  4. private String name;
  5. private String passwd;
  6. private String sex;
  7. private String address;
  8.  
  9. // 构造器尽量缩小范围
  10. private Student() {
  11. }
  12.  
  13. // 构造器尽量缩小范围
  14. private Student(Student origin) {
  15. // 拷贝一份
  16. this.id = origin.id;
  17. this.name = origin.name;
  18. this.passwd = origin.passwd;
  19. this.sex = origin.sex;
  20. this.address = origin.address;
  21. }
  22.  
  23. public int getId() {
  24. return id;
  25. }
  26.  
  27. public String getName() {
  28. return name;
  29. }
  30.  
  31. public String getPasswd() {
  32. return passwd;
  33. }
  34.  
  35. public String getSex() {
  36. return sex;
  37. }
  38.  
  39. public String getAddress() {
  40. return address;
  41. }
  42.  
  43. /**
  44. * Student的创建完全依靠Student.Builder,使用一种方法链的方式来创建
  45. *
  46. */
  47. public static class Builder {
  48.  
  49. private Student target;
  50.  
  51. public Builder() {
  52. target = new Student();
  53. }
  54.  
  55. public Builder address(int id) {
  56. target.id = id;
  57. return this;
  58. }
  59.  
  60. public Builder name(String name) {
  61. target.name = name;
  62. return this;
  63. }
  64.  
  65. public Builder password(String passwd) {
  66. target.passwd = passwd;
  67. return this;
  68. }
  69.  
  70. public Builder sex(String sex) {
  71. target.sex = sex;
  72. return this;
  73. }
  74.  
  75. public Builder address(String address) {
  76. target.address = address;
  77. return this;
  78. }
  79.  
  80. public Student build() {
  81. return new Student(target);
  82. }
  83.  
  84. }
  85.  
  86. }

Student并不是直接new出来的,对其构造器进行了处理使其可访问范围尽可能的小,只让它通过Student.Builder来构建自己,在Student.Builder中提供了一种类set的方法链的方式来设置值,然后在最后的build()方法的时候会返回一个Student对象,现在要创建一个Student对象,代码如下:

  1. Student s=new Student.Builder().name("CC").password("qwerty").sex("男").address("银河系第二旋臂").build();

再对比一下如果不使用构造者模式(一般情况下的用法):

  1. /**
  2. * 学生实体
  3. * @author CC11001100
  4. *
  5. */
  6. public class Student {
  7.  
  8. private int id;
  9. private String name;
  10. private String passwd;
  11. private String sex;
  12. private String address;
  13.  
  14. public Student() {
  15. }
  16.  
  17. public Student(String name, String passwd, String sex, String address) {
  18. super();
  19. this.name = name;
  20. this.passwd = passwd;
  21. this.sex = sex;
  22. this.address = address;
  23. }
  24.  
  25. public int getId() {
  26. return id;
  27. }
  28.  
  29. public void setId(int id) {
  30. this.id = id;
  31. }
  32.  
  33. public String getName() {
  34. return name;
  35. }
  36.  
  37. public void setName(String name) {
  38. this.name = name;
  39. }
  40.  
  41. public String getPasswd() {
  42. return passwd;
  43. }
  44.  
  45. public void setPasswd(String passwd) {
  46. this.passwd = passwd;
  47. }
  48.  
  49. public String getSex() {
  50. return sex;
  51. }
  52.  
  53. public void setSex(String sex) {
  54. this.sex = sex;
  55. }
  56.  
  57. public String getAddress() {
  58. return address;
  59. }
  60.  
  61. public void setAddress(String address) {
  62. this.address = address;
  63. }
  64.  
  65. }

创建对象:

  1. Student s=new Student("CC","qwerty","男","银河系第二旋臂");

对比一下进行一个优劣性分析:

一般的套路:优点是比较简单,开发效率高,缺点是如果参数真的很多的话鬼知道每个对应的是什么意思啊。

Builder模式:优点是可以将构造器的setter方法名取成类似注释的方式,这样我们可以很清晰的知道刚才究竟设置的什么值,可读性较高,缺点是比较冗长。

总结:初步的理解Builder模式解决了要设置的参数过多不好管理的问题(感觉每次构建不同对象是废话 - -)。

从Struts2框架中拿出来的两个Builder模式的例子(都是Config类):

ActionConfig :

  1. public class ActionConfig extends Located implements Serializable {
  2.  
  3. public static final String WILDCARD = "*";
  4.  
  5. protected List<InterceptorMapping> interceptors; // a list of interceptorMapping Objects eg. List<InterceptorMapping>
  6. protected Map<String,String> params;
  7. protected Map<String, ResultConfig> results;
  8. protected List<ExceptionMappingConfig> exceptionMappings;
  9. protected String className;
  10. protected String methodName;
  11. protected String packageName;
  12. protected String name;
  13. protected Set<String> allowedMethods;
  14.  
  15. protected ActionConfig(String packageName, String name, String className) {
  16. this.packageName = packageName;
  17. this.name = name;
  18. this.className = className;
  19. params = new LinkedHashMap<String, String>();
  20. results = new LinkedHashMap<String, ResultConfig>();
  21. interceptors = new ArrayList<InterceptorMapping>();
  22. exceptionMappings = new ArrayList<ExceptionMappingConfig>();
  23. allowedMethods = new HashSet<String>();
  24. allowedMethods.add(WILDCARD);
  25. }
  26.  
  27. /**
  28. * Clones an ActionConfig, copying data into new maps and lists
  29. * @param orig The ActionConfig to clone
  30. * @Since 2.1
  31. */
  32. protected ActionConfig(ActionConfig orig) {
  33. this.name = orig.name;
  34. this.className = orig.className;
  35. this.methodName = orig.methodName;
  36. this.packageName = orig.packageName;
  37. this.params = new LinkedHashMap<String,String>(orig.params);
  38. this.interceptors = new ArrayList<InterceptorMapping>(orig.interceptors);
  39. this.results = new LinkedHashMap<String,ResultConfig>(orig.results);
  40. this.exceptionMappings = new ArrayList<ExceptionMappingConfig>(orig.exceptionMappings);
  41. this.allowedMethods = new HashSet<String>(orig.allowedMethods);
  42. }
  43.  
  44. public String getName() {
  45. return name;
  46. }
  47.  
  48. public String getClassName() {
  49. return className;
  50. }
  51.  
  52. public List<ExceptionMappingConfig> getExceptionMappings() {
  53. return exceptionMappings;
  54. }
  55.  
  56. public List<InterceptorMapping> getInterceptors() {
  57. return interceptors;
  58. }
  59.  
  60. public Set<String> getAllowedMethods() {
  61. return allowedMethods;
  62. }
  63.  
  64. /**
  65. * Returns name of the action method
  66. *
  67. * @return name of the method to execute
  68. */
  69. public String getMethodName() {
  70. return methodName;
  71. }
  72.  
  73. /**
  74. * @return Returns the packageName.
  75. */
  76. public String getPackageName() {
  77. return packageName;
  78. }
  79.  
  80. public Map<String, String> getParams() {
  81. return params;
  82. }
  83.  
  84. public Map<String, ResultConfig> getResults() {
  85. return results;
  86. }
  87.  
  88. public boolean isAllowedMethod(String method) {
  89. if (allowedMethods.size() == 1 && WILDCARD.equals(allowedMethods.iterator().next())) {
  90. return true;
  91. } else {
  92. return allowedMethods.contains(method);
  93. }
  94. }
  95.  
  96. @Override public boolean equals(Object o) {
  97. if (this == o) {
  98. return true;
  99. }
  100.  
  101. if (!(o instanceof ActionConfig)) {
  102. return false;
  103. }
  104.  
  105. final ActionConfig actionConfig = (ActionConfig) o;
  106.  
  107. if ((className != null) ? (!className.equals(actionConfig.className)) : (actionConfig.className != null)) {
  108. return false;
  109. }
  110.  
  111. if ((name != null) ? (!name.equals(actionConfig.name)) : (actionConfig.name != null)) {
  112. return false;
  113. }
  114.  
  115. if ((interceptors != null) ? (!interceptors.equals(actionConfig.interceptors)) : (actionConfig.interceptors != null))
  116. {
  117. return false;
  118. }
  119.  
  120. if ((methodName != null) ? (!methodName.equals(actionConfig.methodName)) : (actionConfig.methodName != null)) {
  121. return false;
  122. }
  123.  
  124. if ((params != null) ? (!params.equals(actionConfig.params)) : (actionConfig.params != null)) {
  125. return false;
  126. }
  127.  
  128. if ((results != null) ? (!results.equals(actionConfig.results)) : (actionConfig.results != null)) {
  129. return false;
  130. }
  131.  
  132. if ((allowedMethods != null) ? (!allowedMethods.equals(actionConfig.allowedMethods)) : (actionConfig.allowedMethods != null)) {
  133. return false;
  134. }
  135.  
  136. return true;
  137. }
  138.  
  139. @Override public int hashCode() {
  140. int result;
  141. result = (interceptors != null ? interceptors.hashCode() : 0);
  142. result = 31 * result + (params != null ? params.hashCode() : 0);
  143. result = 31 * result + (results != null ? results.hashCode() : 0);
  144. result = 31 * result + (exceptionMappings != null ? exceptionMappings.hashCode() : 0);
  145. result = 31 * result + (className != null ? className.hashCode() : 0);
  146. result = 31 * result + (methodName != null ? methodName.hashCode() : 0);
  147. result = 31 * result + (packageName != null ? packageName.hashCode() : 0);
  148. result = 31 * result + (name != null ? name.hashCode() : 0);
  149. result = 31 * result + (allowedMethods != null ? allowedMethods.hashCode() : 0);
  150. return result;
  151. }
  152.  
  153. @Override public String toString() {
  154. StringBuilder sb = new StringBuilder();
  155. sb.append("{ActionConfig ");
  156. sb.append(name).append(" (");
  157. sb.append(className);
  158. if (methodName != null) {
  159. sb.append(".").append(methodName).append("()");
  160. }
  161. sb.append(")");
  162. sb.append(" - ").append(location);
  163. sb.append("}");
  164. return sb.toString();
  165. }
  166.  
  167. /**
  168. * The builder for this object. An instance of this object is the only way to construct a new instance. The
  169. * purpose is to enforce the immutability of the object. The methods are structured in a way to support chaining.
  170. * After setting any values you need, call the {@link #build()} method to create the object.
  171. */
  172. public static class Builder implements InterceptorListHolder{
  173.  
  174. private ActionConfig target;
  175.  
  176. public Builder(ActionConfig toClone) {
  177. target = new ActionConfig(toClone);
  178. }
  179.  
  180. public Builder(String packageName, String name, String className) {
  181. target = new ActionConfig(packageName, name, className);
  182. }
  183.  
  184. public Builder packageName(String name) {
  185. target.packageName = name;
  186. return this;
  187. }
  188.  
  189. public Builder name(String name) {
  190. target.name = name;
  191. return this;
  192. }
  193.  
  194. public Builder className(String name) {
  195. target.className = name;
  196. return this;
  197. }
  198.  
  199. public Builder defaultClassName(String name) {
  200. if (StringUtils.isEmpty(target.className)) {
  201. target.className = name;
  202. }
  203. return this;
  204. }
  205.  
  206. public Builder methodName(String method) {
  207. target.methodName = method;
  208. return this;
  209. }
  210.  
  211. public Builder addExceptionMapping(ExceptionMappingConfig exceptionMapping) {
  212. target.exceptionMappings.add(exceptionMapping);
  213. return this;
  214. }
  215.  
  216. public Builder addExceptionMappings(Collection<? extends ExceptionMappingConfig> mappings) {
  217. target.exceptionMappings.addAll(mappings);
  218. return this;
  219. }
  220.  
  221. public Builder exceptionMappings(Collection<? extends ExceptionMappingConfig> mappings) {
  222. target.exceptionMappings.clear();
  223. target.exceptionMappings.addAll(mappings);
  224. return this;
  225. }
  226.  
  227. public Builder addInterceptor(InterceptorMapping interceptor) {
  228. target.interceptors.add(interceptor);
  229. return this;
  230. }
  231.  
  232. public Builder addInterceptors(List<InterceptorMapping> interceptors) {
  233. target.interceptors.addAll(interceptors);
  234. return this;
  235. }
  236.  
  237. public Builder interceptors(List<InterceptorMapping> interceptors) {
  238. target.interceptors.clear();
  239. target.interceptors.addAll(interceptors);
  240. return this;
  241. }
  242.  
  243. public Builder addParam(String name, String value) {
  244. target.params.put(name, value);
  245. return this;
  246. }
  247.  
  248. public Builder addParams(Map<String,String> params) {
  249. target.params.putAll(params);
  250. return this;
  251. }
  252.  
  253. public Builder addResultConfig(ResultConfig resultConfig) {
  254. target.results.put(resultConfig.getName(), resultConfig);
  255. return this;
  256. }
  257.  
  258. public Builder addResultConfigs(Collection<ResultConfig> configs) {
  259. for (ResultConfig rc : configs) {
  260. target.results.put(rc.getName(), rc);
  261. }
  262. return this;
  263. }
  264.  
  265. public Builder addResultConfigs(Map<String,ResultConfig> configs) {
  266. target.results.putAll(configs);
  267. return this;
  268. }
  269.  
  270. public Builder addAllowedMethod(String methodName) {
  271. target.allowedMethods.add(methodName);
  272. return this;
  273. }
  274.  
  275. public Builder addAllowedMethod(Collection<String> methods) {
  276. target.allowedMethods.addAll(methods);
  277. return this;
  278. }
  279.  
  280. public Builder location(Location loc) {
  281. target.location = loc;
  282. return this;
  283. }
  284.  
  285. public ActionConfig build() {
  286. target.params = Collections.unmodifiableMap(target.params);
  287. target.results = Collections.unmodifiableMap(target.results);
  288. target.interceptors = Collections.unmodifiableList(target.interceptors);
  289. target.exceptionMappings = Collections.unmodifiableList(target.exceptionMappings);
  290. target.allowedMethods = Collections.unmodifiableSet(target.allowedMethods);
  291. ActionConfig result = target;
  292. target = new ActionConfig(target);
  293. return result;
  294. }
  295. }
  296. }

ExceptionMappingConfig:

  1. public class ExceptionMappingConfig extends Located implements Serializable {
  2.  
  3. private String name;
  4. private String exceptionClassName;
  5. private String result;
  6. private Map<String,String> params;
  7.  
  8. protected ExceptionMappingConfig(String name, String exceptionClassName, String result) {
  9. this.name = name;
  10. this.exceptionClassName = exceptionClassName;
  11. this.result = result;
  12. this.params = new LinkedHashMap<String,String>();
  13. }
  14.  
  15. protected ExceptionMappingConfig(ExceptionMappingConfig target) {
  16. this.name = target.name;
  17. this.exceptionClassName = target.exceptionClassName;
  18. this.result = target.result;
  19. this.params = new LinkedHashMap<String,String>(target.params);
  20. }
  21.  
  22. public String getName() {
  23. return name;
  24. }
  25.  
  26. public String getExceptionClassName() {
  27. return exceptionClassName;
  28. }
  29.  
  30. public String getResult() {
  31. return result;
  32. }
  33.  
  34. public Map<String,String> getParams() {
  35. return params;
  36. }
  37.  
  38. @Override
  39. public boolean equals(Object o) {
  40. if (this == o) {
  41. return true;
  42. }
  43.  
  44. if (!(o instanceof ExceptionMappingConfig)) {
  45. return false;
  46. }
  47.  
  48. final ExceptionMappingConfig exceptionMappingConfig = (ExceptionMappingConfig) o;
  49.  
  50. if ((name != null) ? (!name.equals(exceptionMappingConfig.name)) : (exceptionMappingConfig.name != null)) {
  51. return false;
  52. }
  53.  
  54. if ((exceptionClassName != null) ? (!exceptionClassName.equals(exceptionMappingConfig.exceptionClassName)) : (exceptionMappingConfig.exceptionClassName != null))
  55. {
  56. return false;
  57. }
  58.  
  59. if ((result != null) ? (!result.equals(exceptionMappingConfig.result)) : (exceptionMappingConfig.result != null))
  60. {
  61. return false;
  62. }
  63.  
  64. if ((params != null) ? (!params.equals(exceptionMappingConfig.params)) : (exceptionMappingConfig.params != null))
  65. {
  66. return false;
  67. }
  68.  
  69. return true;
  70. }
  71.  
  72. @Override
  73. public int hashCode() {
  74. int hashCode;
  75. hashCode = ((name != null) ? name.hashCode() : 0);
  76. hashCode = (29 * hashCode) + ((exceptionClassName != null) ? exceptionClassName.hashCode() : 0);
  77. hashCode = (29 * hashCode) + ((result != null) ? result.hashCode() : 0);
  78. hashCode = (29 * hashCode) + ((params != null) ? params.hashCode() : 0);
  79.  
  80. return hashCode;
  81. }
  82.  
  83. /**
  84. * The builder for this object. An instance of this object is the only way to construct a new instance. The
  85. * purpose is to enforce the immutability of the object. The methods are structured in a way to support chaining.
  86. * After setting any values you need, call the {@link #build()} method to create the object.
  87. */
  88. public static class Builder{
  89.  
  90. private ExceptionMappingConfig target;
  91.  
  92. public Builder(ExceptionMappingConfig toClone) {
  93. target = new ExceptionMappingConfig(toClone);
  94. }
  95.  
  96. public Builder(String name, String exceptionClassName, String result) {
  97. target = new ExceptionMappingConfig(name, exceptionClassName, result);
  98. }
  99.  
  100. public Builder name(String name) {
  101. target.name = name;
  102. return this;
  103. }
  104.  
  105. public Builder exceptionClassName(String name) {
  106. target.exceptionClassName = name;
  107. return this;
  108. }
  109.  
  110. public Builder result(String result) {
  111. target.result = result;
  112. return this;
  113. }
  114.  
  115. public Builder addParam(String name, String value) {
  116. target.params.put(name, value);
  117. return this;
  118. }
  119.  
  120. public Builder addParams(Map<String,String> params) {
  121. target.params.putAll(params);
  122. return this;
  123. }
  124.  
  125. public Builder location(Location loc) {
  126. target.location = loc;
  127. return this;
  128. }
  129.  
  130. public ExceptionMappingConfig build() {
  131. target.params = Collections.unmodifiableMap(target.params);
  132. ExceptionMappingConfig result = target;
  133. target = new ExceptionMappingConfig(target);
  134. return result;
  135. }
  136. }
  137.  
  138. }

参考资料:

采用Builder模式构造对象

Java方法参数太多怎么办—Part3—Builder模式

设计模式之构建者模式(Builder):初步理解的更多相关文章

  1. 构建者模式Builder创建对象

    构建者(Builder)设计模式(又叫生成器设计模式): 当一个类的内部数据过于复杂的时候(通常是负责持有数据的类,比如Config.VO.PO.Entity...),要创建的话可能就需要了解这个类的 ...

  2. 深入探索Java设计模式之构建器模式(五)

    抽丝剥茧 细说架构那些事——[优锐课] 简单的程序不需要大量的设计过程,因为它们只关注有限的解决方案,仅使用几个类.大型程序专注于广泛的设计,该设计比好的设计范例的任何其他属性都更能利用可重用性.宏伟 ...

  3. 设计模式系列之建造者模式(Builder Pattern)——复杂对象的组装与创建

    说明:设计模式系列文章是读刘伟所著<设计模式的艺术之道(软件开发人员内功修炼之道)>一书的阅读笔记.个人感觉这本书讲的不错,有兴趣推荐读一读.详细内容也可以看看此书作者的博客https:/ ...

  4. Net设计模式实例之建造者模式(Builder Pattern)

    一.建造者模式简介(Brief Introduction) 建造者模式(Builder Pattern),将一个复杂对象的构建与它的表示分离,使的同样的构建过程可以创建不同的表示. 建造者模式的优点是 ...

  5. 【原】iOS设计模式之:建造者模式Builder Pattern,用于改进初始化参数

    本文主要讨论一下iOS中的Builder Pattern.与网上很多版本不同,本文不去长篇大论地解释建造者模式的概念,那些东西太虚了.设计模式这种东西是为了解决实际问题的,不能为了设计模式而设计模式, ...

  6. iOS设计模式之:建造者模式Builder Pattern,用于改进初始化参数

    转自:http://www.cnblogs.com/wengzilin/p/4365855.html 本文主要讨论一下iOS中的Builder Pattern.与网上很多版本不同,本文不去长篇大论地解 ...

  7. 构建者模式(Builder pattern)

    构建者模式应用场景: 主要用来构建一些复杂对象,这里的复杂对象比如说:在建造大楼时,需要先打牢地基,搭建框架,然后自下向上地一层一层盖起来.通常,在建造这种复杂结构的物体时,很难一气呵成.我们需要首先 ...

  8. IOS设计模式浅析之建造者模式(Builder)

    定义 "将一个复杂对象的构建与它的表现分离,使得同样的构建过程可以创建不同的表现". 最初的定义出现于<设计模式>(Addison-Wesley,1994). 看这个概 ...

  9. 设计模式 笔记 生成器(建造者)模式 Builder

    //---------------------------15/04/08---------------------------- //builder 生成器(建造者)模式---对象创建型模式 /* ...

随机推荐

  1. transition代替简单的animation注意事项

    一. transition 和 animation  不支持    Internet Explorer 9,以及更早的版本. 二. 要变化的属性 transition-property:要变化的属性, ...

  2. ProgressDialog的使用

    ProgressDialog 继承自AlertDialog,AlertDialog继承自Dialog,实现DialogInterface接口. ProgressDialog的创建方式有两种,一种是ne ...

  3. 基于php的snmp管理端开发

    一.系统环境: 操作系统:CentOS 5.4                内核:Linux_2.6 编译环境:gcc 4.1.2                代码版本:php-5.2.8.tar ...

  4. SVN迁移到Git的过程(+ 一些技巧)

    SVN迁移到Git的过程(+ 一些技巧) 李顺利 Key Words SVN,Git,Clone,Conversion,Tips,VCS,Pro Git 关于在VCS中SVN和Git之间的迁移(Clo ...

  5. 40 网络相关函数(八)——live555源码阅读(四)网络

    40 网络相关函数(八)——live555源码阅读(四)网络 40 网络相关函数(八)——live555源码阅读(四)网络 简介 15)writeSocket向套接口写数据 TTL的概念 函数send ...

  6. 一致性哈希算法以及其PHP实现

    在做服务器负载均衡时候可供选择的负载均衡的算法有很多,包括:  轮循算法(Round Robin).哈希算法(HASH).最少连接算法(Least Connection).响应速度算法(Respons ...

  7. IIS 处理请求 原理

    有时候我们会发现当我们访问一个IIS网站时,使用网址可以正常访问,但是使用IP却不行,这是什么原因呢? 原来IIS可以使用一个IP地址和端口绑定多个网站,这些网站的IP地址与端口都一样,因此在客户端或 ...

  8. 【leetcode】Word Ladder

    Word Ladder Total Accepted: 24823 Total Submissions: 135014My Submissions Given two words (start and ...

  9. Wince下sqlce数据库开发(二)

    上次写到使用数据绑定的方法测试本地sqlce数据库,这次使用访问SQL Server的方法访问sqlce,你会发现他们是如此的相似... 参考资料:http://www.cnblogs.com/rai ...

  10. POJ 2559

    http://poj.org/problem?id=2559 题意:就是找出可以完整连接的最大的矩形面积. 思路:找出单独的一块矩形,往两边延伸,记录两边的比他高的矩形是在哪个位置,然后最右的位置减去 ...