您的位置:首页 > 产品设计 > UI/UE

Java中Builder模式的使用

2010-06-30 19:25 344 查看
今天在上课的时候老师给我们讲解了一下如何使用Builder来减少类的构造器重载,以及如何使用Builder来缓存常用对象的。

Part I

首先我们来看看以下一段代码:

1: import java.util.Date;


2:


3: public class Customer {


4:


5:     private String name;


6:     private Boolean gender;


7:     private Date birth;


8:     private Double salary;


9:


10:


11:     public Customer(String name) {


12:         this.name = name;


13:     }


14:


15:     public Customer(Boolean gender) {


16:         this.gender = gender;


17:     }


18:


19:     public Customer(Date birth, Double salary) {


20:         this.birth = birth;


21:         this.salary = salary;


22:     }


23:


24:     /*


25:      * 这里还应该有N多的构造方法被省略。


26:      */


27:


28:     public Customer(Boolean gender, Date birth, Double salary) {


29:         this.gender = gender;


30:         this.birth = birth;


31:         this.salary = salary;


32:     }


33:


34:     public Customer(String name, Boolean gender, Date birth, Double salary) {


35:         this.name = name;


36:         this.gender = gender;


37:         this.birth = birth;


38:         this.salary = salary;


39:     }


40:


41: }


看到上面的代码了吧……仅仅是四个属性就可以衍生出那么多的构造器,实在是对程序员的折磨,而且如果遇到相同类型的属性,那就会产生歧义(因为重载是根据参数列表中的参数类型来判断方法)。

接下来我们再看看下面这段代码:

1: import java.util.Date;


2:


3: public class Customer {


4:


5:     private String name;


6:     private Boolean gender;


7:     private Date birth;


8:     private Double salary;


9:


10:private Customer() {


11:         // 将构造器私有化,换句话说外部类不能实例化Customer。


12:     }


13:


14:/*


15:      * 省略了get方法


16:      */


17:


18:/**


19:      * 重写了toString方法,方便观察效果


20:      */


21:     @Override


22:     public String toString() {


23:    return "Customer [birth=" + birth + ", gender=" + gender + ", name=" + name + ", salary=" + salary + "]";


24:     }


25:


26:     public static final class CustomerBuilder {


27:    


28:         private String name;


29:         private Boolean gender;


30:         private Date birth;


31:         private Double salary;


32:


33:       public CustomerBuilder() {


34:             name = "default";


35:             gender = true;


36:             birth = new Date();


37:             salary = 0d;


38:         }


39:


40:    public Customer getCustomer() {


41:             Customer customer = new Customer();


42:             customer.name = name;


43:             customer.gender = gender;


44:             customer.birth = birth;


45:             customer.salary = salary;


46:             return customer;


47:         }


48:


49:         public CustomerBuilder setDefaultName(String name) {


50:             this.name = name;


51:             return this;


52:         }


53:


54:         public CustomerBuilder setDefaultGender(Boolean gender) {


55:             this.gender = gender;


56:             return this;


57:         }


58:


59:         public CustomerBuilder setDefaultBirth(Date birth) {


60:             this.birth = birth;


61:             return this;


62:         }


63:


64:         public CustomerBuilder setDefaultSalary(Double salary) {


65:             this.salary = salary;


66:             return this;


67:         }


68:


69:     }


70:


71: }


1: public class CustomerTester {


2:   


3:     public static void main(String[] args) {


4:    


5:         // 测试一:新建一个完全由默认值指定的对象


6:         Customer.CustomerBuilder builder = new Customer.CustomerBuilder();


7:         Customer customer = builder.getCustomer();


8:         System.out.println(customer);


9:    


10:    // 测试二:更改默认值


11:         builder.setDefaultName("Kent").setDefaultSalary(5000d); // 有点贪心


12:         Customer kent = builder.getCustomer();


13:    System.out.println(kent);


14:    


15:     }


16:


17: }


运行效果:

Customer [birth=Wed Jun 30 18:57:41 CST 2010, gender=true, name=default, salary=0.0]
Customer [birth=Wed Jun 30 18:57:41 CST 2010, gender=true, name=Kent, salary=5000.0]

通过以上的代码,我们可以看出,使用Builder来创建一个对象,可以很大程度的减少构造器的编写,并且也可以使得创建对象的时候,尽可能的减少相同参数的传递。

Part II

关于对象的缓存问题,今天老师提出了一个方案,先把今天展示的方案的代码贴出来:

1: import java.util.HashMap;


2: import java.util.Map;


3:


4: public class Grade {


5:


6:     private static Map<String, Grade> map = new HashMap<String, Grade>();


7:


8:     private String name;


9:


10:private Grade(String name) {


11:         this.name = name;


12:     }


13:


14:public static Grade getInstance(String name) {


15:         if (map.containsKey(name)) {


16:        return map.get(name);


17:    }


18:    Grade grade = new Grade(name);


19:         map.put(name, grade);


20:         return grade;


21:     }


22:


23: }


1: public class GradeTester {


2:


3:     public static void main(String[] args) {


4:    Grade grade1 = Grade.getInstance("A");


5:       Grade grade2 = Grade.getInstance("B");


6:         Grade grade3 = Grade.getInstance("A");


7:       


8:         // 结果为false,证明grade1和grade3是不同的实例对象


9:    System.out.println(grade1 == grade2);


10:    // 结果为true,证明grade1和grade3是同一个实例对象


11:         System.out.println(grade1 == grade3);


12:     }


13:


14: }


上述代码可以看出,我们已经可以把A这个等级所对应的实例对象取出来,而并不会产生两个等级相同的实例对象,这样的好处就是在同一个运行环境中只存在一个name为A的实例对象,避免重复创建相同作用的对象,减少内存开销。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: