Chinaunix首页 | 论坛 | 博客
  • 博客访问: 841935
  • 博文数量: 372
  • 博客积分: 10063
  • 博客等级: 中将
  • 技术积分: 4220
  • 用 户 组: 普通用户
  • 注册时间: 2012-02-24 11:36
文章分类

全部博文(372)

文章存档

2012年(372)

分类: 云计算

2012-03-09 19:36:01

coolxing按: 转载请注明作者和出处, 如有谬误, 欢迎在评论中指正.]

创建对象的方法很多, 常见的有构造函数, 静态工厂方法, 工厂方法等.

以上三种方法不适合创建需要提供多个参数的对象, 而其中某些参数是可选的场景.

考虑一个Person类:

Java代码 复制代码 收藏代码
  1. public class Person {
  2. // 必须的参数
  3. private int id;
  4. private String name;
  5. private int age;
  6. // 可选参数
  7. private String city;
  8. private String hoby;
  9. private String job;
  10. private String ***;
  11. }
public class Person { // 必须的参数 private int id; private String name; private int age; // 可选参数 private String city; private String hoby; private String job; private String ***;}

如果给这个Person类提供合适的构造函数, 应该怎么做呢?

也许我们可以提供多个构造函数, 每个构造函数都包含必须的参数, 以及0个或多个可选参数. 例如:

Java代码 复制代码 收藏代码
  1. public Person(int pid, String name, int age) {
  2. this.id = pid;
  3. this.name = name;
  4. this.age = age;
  5. }
  6. public Person(int id, String name, int age, String city) {
  7. this.id = id;
  8. this.name = name;
  9. this.age = age;
  10. this.city = city;
  11. }
  12. public Person(int id, String name, int age, String city, String hoby) {
  13. super();
  14. this.id = id;
  15. this.name = name;
  16. this.age = age;
  17. this.city = city;
  18. this.hoby = hoby;
  19. }
  20. public Person(int id, String name, int age, String city, String hoby, String job) {
  21. this.id = id;
  22. this.name = name;
  23. this.age = age;
  24. this.city = city;
  25. this.hoby = hoby;
  26. this.job = job;
  27. }
  28. public Person(int id, String name, int age, String city, String hoby, String job, String ***) {
  29. this.id = id;
  30. this.name = name;
  31. this.age = age;
  32. this.city = city;
  33. this.hoby = hoby;
  34. this.job = job;
  35. this.*** = ***;
  36. }
public Person(int pid, String name, int age) { this.id = pid; this.name = name; this.age = age;} public Person(int id, String name, int age, String city) { this.id = id; this.name = name; this.age = age; this.city = city;} public Person(int id, String name, int age, String city, String hoby) { super(); this.id = id; this.name = name; this.age = age; this.city = city; this.hoby = hoby;} public Person(int id, String name, int age, String city, String hoby, String job) { this.id = id; this.name = name; this.age = age; this.city = city; this.hoby = hoby; this.job = job;}public Person(int id, String name, int age, String city, String hoby, String job, String ***) { this.id = id; this.name = name; this.age = age; this.city = city; this.hoby = hoby; this.job = job; this.*** = ***;}

这种方法至少存在这样的问题:

1. 如果需要创建一个只指定city和***的Person对象, 我们就必须调用public Person(int id, String name, int age, String city, String hoby, String job, String ***)方法, 然后将hoby, job都赋值为空字符串. 这是让人疑惑的, 也是丑陋的.

2. 这样的代码难以阅读, 而且臃肿不堪, 不具备良好的可伸缩性.

当然我们可以同时提供属性的getter和setter方法, 然后只保留Person(int pid, String name, int age)一个构造函数.

如此的话, 我们先通过Person(int pid, String name, int age)方法创建Person对象, 然后调用需要的setter方法给可选参数赋值.

这是不错的解决方法, 但是创建对象被分成了几个步骤, 这会带来问题: 如果一不小心可能会让将尚未完全创建的Person对象泄露出去--结果是严重的.

Builder设计模式就非常适合这样的场景:

Java代码 复制代码 收藏代码
  1. public class Person {
  2. // 必须的参数
  3. private int id;
  4. private String name;
  5. private int age;
  6. // 可选参数
  7. private String city;
  8. private String hoby;
  9. private String job;
  10. private String ***;
  11. // 私有构造函数
  12. private Person(Builder builder) {
  13. this.id = builder.id;
  14. this.name = builder.name;
  15. this.age = builder.age;
  16. this.city = builder.city;
  17. this.hoby = builder.hoby;
  18. this.job = builder.job;
  19. this.*** = builder.***;
  20. }
  21. public static class Builder {
  22. // 必须的参数
  23. private int id;
  24. private String name;
  25. private int age;
  26. // 可选参数
  27. private String city;
  28. private String hoby;
  29. private String job;
  30. private String ***;
  31. // 设置必须的参数
  32. public Builder(int id, String name, int age) {
  33. this.id = id;
  34. this.name = name;
  35. this.age = age;
  36. }
  37. // 设置可选参数, 返回Builder对象可以让调用者使用级联
  38. public Builder setCity(String city) {
  39. this.city = city;
  40. return this;
  41. }
  42. public Builder setHoby(String hoby) {
  43. this.hoby = hoby;
  44. return this;
  45. }
  46. public Builder setJob (String job) {
  47. this.job = job;
  48. return this;
  49. }
  50. public Builder set***(String ***) {
  51. this.*** = ***;
  52. return this;
  53. }
  54. public Person build() {
  55. return new Person(this);
  56. }
  57. }
  58. }
public class Person { // 必须的参数 private int id; private String name; private int age; // 可选参数 private String city; private String hoby; private String job; private String ***; // 私有构造函数 private Person(Builder builder) { this.id = builder.id; this.name = builder.name; this.age = builder.age; this.city = builder.city; this.hoby = builder.hoby; this.job = builder.job; this.*** = builder.***; } public static class Builder { // 必须的参数 private int id; private String name; private int age; // 可选参数 private String city; private String hoby; private String job; private String ***; // 设置必须的参数 public Builder(int id, String name, int age) { this.id = id; this.name = name; this.age = age; } // 设置可选参数, 返回Builder对象可以让调用者使用级联 public Builder setCity(String city) { this.city = city; return this; } public Builder setHoby(String hoby) { this.hoby = hoby; return this; } public Builder setJob (String job) { this.job = job; return this; } public Builder set***(String ***) { this.*** = ***; return this; } public Person build() { return new Person(this); } }}

如果需要一个指定city和***的Person对象, 就可以这样创建:

Java代码 复制代码 收藏代码
  1. Person.Builder builder = new Person.Builder(1, "xing", 25);
  2. Person person = builder.setCity("beijing").set***().build();
Person.Builder builder = new Person.Builder(1, "xing", 25);Person person = builder.setCity("beijing").set***().build();

在调用build方法完成之前, Person对象都没有被创建, 所以无需担心提前泄露的问题, 而且使用级联的方式使得代码简洁优雅.

总结: Builder模式只适合创建对象时需要指定多个可选参数的场景.

阅读(551) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~