以下是本文的参考网址:
http://www.javacamp.org/designPattern/
http://coolxing.iteye.com/blog/1446760
http://luchar.iteye.com/blog/179619
构造模式是一种对象的创建方式,它可以将一个复杂对象的内部构造特征与内部的构建过程完全分开,构造模式的种类很多,(有多种实现方式,每个实现方式不同,但是原理是相同的)
可以总结出,构造模式主要设计四个角色:
1、客户端角色(Client):调用具体的构造器,完成对象的构建,注意,这个角色只负责构造器的创建和选择,对于产品的具体信息不知晓。
2、抽象构造器角色(Builder):这是一个抽象的构造器角色,有一组接口方法来扮演,在实际情况中,这一组接口会由一个核心的build方法(负责最终对象的创建)以及若干的辅助方法(帮助构建对象的内部属性特征)共同构成。
3、具体构造器(ProductBuilder):具体的构造器实现,具体构造器是整个构造模式的核心,其中封装了一个目标的对象实例,当核心的build方法被客户端调用时,其内部缓存的对象实例会真正返回,而在这之前,所有其他的辅助方法的调用都仅仅是将内部缓存的目标对象进行内容上的填充。
4、产品角色(Product):它是整个构造模式的产物,这个角色是构造模式执行的结果。
在实际应用中,构造模式有一种变种,当对于构造对象非常的明确,由于构造过程话的定义并不严格,我们可以省略抽象构造器接口这个角色,而直接使用一个具体构造器,客户端通过调用具体的构造器内部定义的方法,来完成对象的创建,
构造模式之所以可以产生这样的变种,其所构造对象的特性和整个构造过程有直接的联系,但是无论哪种构造器的实现,客户端,构造器,构造对象三种角色都是构造器模式不可或缺的部分,它们之间的调用关系,构成了构造模式运行的基础。
构造器的调用过程分为三个步骤:
1、构造器首先会创建一个目标对象实例加以缓存。
2、构造器依次调用建立目标对象特性的行为方法,其目的在于为目标对象搜集并设置其内在的属性。
3、构造器最终调用其核心的方法build完成目标对象的创建,并返回给客户端。
以下是构造器模式的另一种解释:构造器模式有很多的变种:
构造器概述:
构造者模式(Builder Pattern):构造者模式将一个复杂对象的构造过程和它的表现层分离开来,使得同样的构建过程可以创建不同的表示,又称为生成器模式。
在软件系统 中,有时候面临着“一个复杂对象”的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变 化,但是将它们组合在一起的算法确相对稳定。如何应对这种变化?如何提供一种“封装机制”来隔离出“复杂对象的各个部分”的变化,从而保持系统中的“稳定 构建算法”不随着需求改变而改变?
如果我们使用了构造者模式,那么用户就只需要指定需要构造的类型就可以得到它们,而具体的构造过程和细节就不需要知道了。
构造模式产生的背景:
考虑一个Person类:
1 package com.test.designpatterm;
2
3 public class Person {
4 // 必须的参数
5 private int id;
6 private String name;
7 private int age;
8
9 // 可选参数
10 private String city;
11 private String hoby;
12 private String job;
13 private String sex;
14 }
如果给这个Person类提供合适的构造函数, 应该怎么做呢?
也许我们可以提供多个构造函数, 每个构造函数都包含必须的参数, 以及0个或多个可选参数. 例如:
1 public Person(int pid, String name, int age) {
2 this.id = pid;
3 this.name = name;
4 this.age = age;
5 }
6
7 public Person(int id, String name, int age, String city) {
8 this.id = id;
9 this.name = name;
10 this.age = age;
11 this.city = city;
12 }
13
14 public Person(int id, String name, int age, String city, String hoby) {
15 super();
16 this.id = id;
17 this.name = name;
18 this.age = age;
19 this.city = city;
20 this.hoby = hoby;
21 }
22
23 public Person(int id, String name, int age, String city, String hoby,
24 String job) {
25 this.id = id;
26 this.name = name;
27 this.age = age;
28 this.city = city;
29 this.hoby = hoby;
30 this.job = job;
31 }
32
33 public Person(int id, String name, int age, String city, String hoby,
34 String job, String sex) {
35 this.id = id;
36 this.name = name;
37 this.age = age;
38 this.city = city;
39 this.hoby = hoby;
40 this.job = job;
41 this.sex = sex;
42 }
这种方法至少存在这样的问题:
1. 如果需要创建一个只指定city和sex的Person对象, 我们就必须调用public Person(int id, String name, int age, String city, String hoby, String job, String sex)方法, 然后将hoby, job都赋值为空字符串. 这是让人疑惑的, 也是丑陋的.
2. 这样的代码难以阅读, 而且臃肿不堪, 不具备良好的可伸缩性.
参考第二中解释的实例:
产品类:
1 //产品类:
2 package com.javapatterns.builder;
3
4 public class Product{
5 public Product(){
6 // System.out.println("product is initing.");
7 }
8 }
抽象类:也可以为接口
1 //抽象建造方法:
2 package com.javapatterns.builder;
3
4 abstract public class Builder{
5 public abstract void buildPart1();
6
7 public abstract void buildPart2();
8
9 public abstract Product retrieveResult();
10 }
抽象类的具体实现类:(具体构造器必须要封装一个目标的对象实例)下面的Product即为封装的目标类。
1 //具体的建造类:产品的零件制造
2 package com.javapatterns.builder;
3
4 public class ConcreteBuilder extends Builder{
5
6 private Product product = new Product() ;
7 public void buildPart1(){
8 System.out.println("build part one.");
9 }
10
11 public void buildPart2(){
12 System.out.println("build part two.");
13 }
14
15 public Product retrieveResult(){
16 return product;
17 }
18 }
产品的建造过程:(Director:指挥者,它是构建一个使用Builder接口的对象。)
1 //产品的建造过程:
2 package com.javapatterns.builder;
3
4 public class Director{
5 private Builder builder;
6
7 public Director(Builder builder){
8 this.builder = builder;
9 }
10
11 public void construct(){
12 builder = new ConcreteBuilder();
13
14 builder.buildPart1();
15
16 builder.buildPart2();
17
18 builder.retrieveResult();
19
20 //continue with other code
21 }
22 }
测试,客户端调用测试:
1 //测试:
2 package com.test.designpatterm;
3
4 public class Client {
5
6 private static Director director;
7
8 private static Builder builder = new ConcreteBuilder();
9
10 public void requestBuild() {
11 // director = new Director(builder);
12 }
13
14 public static void main(String[] args) {
15 director = new Director(builder);
16 director.construct();
17 Product product = builder.retrieveResult();//返回构造的对象
18 System.out.println(product);
19
20 }
21
22 }
----------------------------------------------------------------------------------------------------------
关于构造模式的英文讲解:
Builder
Construct a complex object from simple objects step by step.
Where to use & benefits
- Make a complex object by specifying only its type and content. The built object is shielded from the details of its construction.
- Want to decouple the process of building a complex object from the parts that make up the object.
- Isolate code for construction and representation.
- Give you finer control over the construction process.
- Related patterns include
- Abstract Factory, which focuses on the layer over the factory pattern (may be simple or complex), whereas a builder pattern focuses on building a complex object from other simple objects.
- Composite, which is often used to build a complex object.
总结: Builder模式只适合创建对象时需要指定多个可选参数的场景.