builder模式

学习模式最好通过真实的例子来学习

Builder模式是一步一步创建一个复杂的对象,它允许用户可以只通过指定复杂对象的类型和内容就可以构建它们.用户不知道内部的具体构建细节. 它的目的是为了将构建复杂对象的过程 和它的部件 解耦。参考http://www.jdon.com/designpatterns/builder.htm。不过里面举的例子让人看了仍然对builder模式是一头雾水,因为这个例子完全无法展示构建的复杂性,只有在构建比较复杂时才有必要使用Builder模式。

真实例子:commons-lang中的ToStringBuilder, HashCodeBuilder, EqualsBuilder.

以一个简化版的ToStringBuilder(来处Guice的ToStringBuilder)为来说明Builder:

java 代码
 
  1. public   class  ToStringBuilder {  
  2.   
  3.   // Linked hash map ensures ordering.   
  4.   final  Map new  LinkedHashMap
  5.   
  6.   final  String name;  
  7.   
  8.   public  ToStringBuilder(String name) {  
  9.     this .name = name;  
  10.   }  
  11.   
  12.   public  ToStringBuilder(Class type) {  
  13.     this .name = type.getSimpleName();  
  14.   }  
  15.   
  16.   public  ToStringBuilder add(String name, Object value) {  
  17.     if  (map.put(name, value) !=  null ) {  
  18.       throw   new  RuntimeException( "Duplicate names: "  + name);  
  19.     }  
  20.     return   this ;  
  21.   }  
  22.   
  23.   public  String toString() {  
  24.     return  name + map.toString().replace('{', '[').replace('}', ']');  
  25.   }  
  26. }  



对比使用和不使用Builder模式写toString()的方式。
不使用Builder:

java 代码
 
  1. public   class  Person {  
  2.     private  Long id;
  3.     private  String name;
  4.     private  String phone;  
  5.     private  String address;
  6. // getter and setter
  7.  
  8.     public  String toString() {
  9.         return "Person[" +
                        "id=" + (id == null ? "<null><null>" : id) + ", " +
                        "name=" + (name == null ? "<null></null></null></null>
    <null><null></null></null> <null><null>" : name) + ", " +
                        "phone=" + (phone == null ? "<null></null></null></null>
    <null><null></null></null> <null><null><null>" : phone) + ", " +
                        "address=" + (address == null ? "</null></null></null>
    <null><null></null></null> <null><null><null><null>" : address) +
                    "]"; 
    </null></null></null></null>
  10.     }  
  11. }  


使用Builder:

java 代码
 
  1. public   class  Person {  
  2.     private  Long id;  
  3.     private  String name;  
  4.     private  String phone;  
  5.     private  String address;  
  6.   
  7. // getter and setter   
  8.   
  9.     public  String toString() {  
  10.         return   new  ToStringBuilder( this .getClass())  
  11.             .add("id" , id)  
  12.             .add("name" , name)  
  13.             .add("phone" , phone)  
  14.             .add("address" , address)  
  15.             .toString();  
  16.     }  
  17. }  



很容易看到第二种方式要优于第一种方式。第一种方式相当繁琐并且容易出错(比如最后一个filed后面不能加", ",因此新加field必须记得先加上", ",然后添加新的field)。第二种方式采用builder模式,步骤固定,容易使用,因而不容易出错,添加一个新field时只要加上一个add方法就可以了。

接下来看下builder模式是如何解耦过程和部件的。要创建一个对象的toString方法,我们只需要知道这个对象中有哪些field,这就是"部件",知道了这些部件。ToStringBuilder便知道如何根据这些部件组装成需要的产品(代表某个对象的字符串),我们说它封装了“过程”。这便实现过程和部件的分离(解耦),当我们需要不同的字符串表示,只需要创建新的Builder。对于这个简单的程序我们没有这种需要,一旦有这种需示,builder应该被设计成一个接口,以便不同具体类来实现它。

(这里讲的builder和标准的builder稍微有一点区别,标准的builder用一个单独的类Director来封装过程,然而我很少在实际中看到Director的存在)

你可能感兴趣的:(设计模式)