Builder模式(建造者模式)
2016-01-05 20:26
375 查看
在设计模式中对Builder模式的定义是用于构建复杂对象的一种模式,所构建的对象往往需要多步初始化或赋值才能完成。那么,在实际的开发过程中,我们哪些地方适合用到Builder模式呢?其中使用Builder模式来替代多参数构造函数是一个比较好的实践法则。
我们常常会面临编写一个这样的实现类(假设类名叫DoDoContact),这个类拥有多个构造函数,
DoDoContact(String name);
DoDoContact(String name, int age);
DoDoContact(String name, int age, String address);
DoDoContact(String name, int age, String address, int cardID);
这样一系列的构造函数主要目的就是为了提供更多的客户调用选择,以处理不同的构造请求。这种方法很常见,也很有效力,但是它的缺点也很多。类的作者不得不书写多种参数组合的构造函数,而且其中还需要设置默认参数值,这是一个需要细心而又枯燥的工作。其次,这样的构造函数灵活性也不高,而且在调用时你不得不提供一些没有意义的参数值,例如,DoDoContact("Ace", -1, "SH"),显然年龄为负数没有意义,但是你又不的不这样做,得以符合Java的规范。如果这样的代码发布后,后面的维护者就会很头痛,因为他根本不知道这个-1是什么含义。对于这样的情况,就非常适合使用Builder模式。Builder模式的要点就是通过一个代理来完成对象的构建过程。这个代理职责就是完成构建的各个步骤,同时它也是易扩展的。下面是改写自Effective Java里面的一段代码:
客户程序可以这样构建对象:
我们常常会面临编写一个这样的实现类(假设类名叫DoDoContact),这个类拥有多个构造函数,
DoDoContact(String name);
DoDoContact(String name, int age);
DoDoContact(String name, int age, String address);
DoDoContact(String name, int age, String address, int cardID);
这样一系列的构造函数主要目的就是为了提供更多的客户调用选择,以处理不同的构造请求。这种方法很常见,也很有效力,但是它的缺点也很多。类的作者不得不书写多种参数组合的构造函数,而且其中还需要设置默认参数值,这是一个需要细心而又枯燥的工作。其次,这样的构造函数灵活性也不高,而且在调用时你不得不提供一些没有意义的参数值,例如,DoDoContact("Ace", -1, "SH"),显然年龄为负数没有意义,但是你又不的不这样做,得以符合Java的规范。如果这样的代码发布后,后面的维护者就会很头痛,因为他根本不知道这个-1是什么含义。对于这样的情况,就非常适合使用Builder模式。Builder模式的要点就是通过一个代理来完成对象的构建过程。这个代理职责就是完成构建的各个步骤,同时它也是易扩展的。下面是改写自Effective Java里面的一段代码:
public class DoDoContact { private final int age; private final int safeID; private final String name; private final String address; public int getAge() { return age; } public int getSafeID() { return safeID; } public String getName() { return name; } public String getAddress() { return address; } public static class Builder { private int age = 0; private int safeID = 0; private String name = null; private String address = null; // 构建的步骤 public Builder(String name) { this.name = name; } public Builder age(int val) { age = val; return this; } public Builder safeID(int val) { safeID = val; return this; } public Builder address(String val) { address = val; return this; } public DoDoContact build() { // 构建,返回一个新对象 return new DoDoContact(this); } } private DoDoContact(Builder b) { age = b.age; safeID = b.safeID; name = b.name; address = b.address; } }
客户程序可以这样构建对象:
DoDoContact ddc = new DoDoContact.Builder("Ace").age(10) .address("beijing").build(); System.out.println("name=" + ddc.getName() + "age =" + ddc.getAge() + "address" + ddc.getAddress());
相关文章推荐
- jQquery选取元素
- CodeForces 441A Valera and Antique Items
- IOS模态视图 (UI页面切换)
- easyui combobox级联(转载)
- iOS开发学习之UI篇3、UILabel
- leetcode第一刷_Unique Paths
- 优化UITableViewCell高度计算的那些事 附源码
- (转载)iOS UILabel自定义行间距时获取高度
- IOS(UI)_UIButton(按钮)和UIImageView(图片按钮)
- iOS开发学习之UI篇 1、UIView
- IOS(UI)_UILabel(标签)
- UE 无法初始化FTP组件
- 有value时,li元素序列号就是value值,没有value,则会递增
- 关于百度 UEditor的使用
- Android can only be built by versions 3.81 and 3.82
- Arduino 中断和定时器
- lintcode :implement queue by two stacks 用栈实现队列
- UIAlertController
- UIView设置指定的border
- 给UIView 的子类们 UIButton UILbel等 。。。。加一个虚线圆角的border