昨晚回到家里,我爸爸气冲冲地跟我诉苦,“哎!,干个装修容易么?顾客啥都不懂,还非得规定装修顺序,要先贴地板砖后刷墙,到时候贴好的地砖上全是泥,哪有这么干活的?”老爸干了一辈子的装修,一切事宜由他全权负责,难免心力憔悴。但是,我仔细想了下这个事情,如果老爸签订了一个公司,公司负责接活揽活,规定装修要求,老爸只负责执行,那不就轻松了吗?于是我就想起了建造者模式。
建造者模式的定义是:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。它允许用户通过制定的对象类型和内容来创建他们,但是用户并不需要知道这个复杂对象是如何构建的,它只需要明白通过这样做我可以得到一个完整的复杂对象实例。
建造者模式是为了将构建复杂对象的过程和它的部件解耦。因为一个复杂的对象,不但有很多大量组成部分,如汽车,有很多部件:车轮方向盘 发动机还有各种小零件等等,部件很多,但远不止这些,如何将这些部件装配成一辆汽车,这个装配过程也很复杂(需要很好的组装技术),Builder模式就是为了将部件和组装过程分开。
建造者模式主要包含四个角色:
Director:指挥者,导演类,构建一个使用Builder接口的对象。它主要是用于创建一个复杂的对象,负责调用适当的建造者来组建产品。它主要有两个作用,一是:隔离了客户与对象的生产过程,二是:负责控制产品对象的生产过程。
Builder:抽象建造者。它声明为创建一个Product对象的各个部件指定的抽象接口,一般至少会有两个抽象方法,一个用来建造产品,一个是用来返回产品。
ConcreteBuilder:具体建造者。实现抽象接口,构建和装配各个部件,按照要求组建产品和返回组建好的产品。
Product:产品角色。一个具体的产品对象。
现在假设老爸上面签订了装修公司,公司负责与客户对接,按照客户要求制定装修的细则和分派装修人员,然后按期把装修好的房子提供给顾客。那么装修公司就是Director:
package com.pattern.builder;
import java.util.List;
/**
* 装修公司相当于Director--负责安排builder和对应的装修次序
* @author
*
*/
public class BuilderCompany {
private Decorator builder;
public BuilderCompany(Decorator builder) {
this.builder = builder;
}
/**
* 公司安排装修次序-让builder去装修房子
* @param sequence
*/
public void decoration(List sequence){
this.builder.setSequence(sequence);//制定装修顺序
this.builder.getNiceHouse();//提供装修好的房子
}
}
制定一个抽象建造者,提供建造产品和过程的抽象方法:
package com.pattern.builder;
import java.util.ArrayList;
import java.util.List;
/**
* 装修者--抽象类
* 定义装修的动作 并根据动作顺序返回结果
* @author
*
*/
public abstract class Decorator {
private List sequence = new ArrayList();//装修顺序
protected abstract void designDrawing();//出设计图
protected abstract void transHydropower();//水电改造
protected abstract void brushWall();//刷墙
protected abstract void stickTiles();//贴地砖
protected abstract NiceHouse getNiceHouse();//得到装修好的漂亮房子
/**
* 根据装修公司制定的装修次序--执行动作
*/
final protected void setDecorateSequence(){
for(String s:sequence){
if(s.equalsIgnoreCase(Sequence.DRAW)){
this.designDrawing();
}else if(s.equalsIgnoreCase(Sequence.POWER)){
this.transHydropower();
}else if(s.equalsIgnoreCase(Sequence.BRUSH)){
this.brushWall();
}else if(s.equalsIgnoreCase(Sequence.TILES)){
this.stickTiles();
}
}
}
/**
* 设置装修动作顺序
* @param sequence
*/
public void setSequence(List sequence) {
this.sequence = sequence;
}
}
上述为了编程方便,定义了一个装修顺序的常量类:
package com.pattern.builder;
public class Sequence {
public static final String DRAW="draw";//出设计图
public static final String POWER="power";//水电改造
public static final String BRUSH="brush";//刷墙
public static final String TILES="tiles";//贴地砖
}
然后老爸和其他同事按照公司规定的顺序负责装修,按期交工即可:
package com.pattern.builder;
/**
* 具体建造者A
* @author
*
*/
public class DecoratorZhang extends Decorator{
@Override
protected void designDrawing() {
System.out.println("DecoratorZhang出设计图...");
}
@Override
protected void transHydropower() {
System.out.println("DecoratorZhang水电改造...");
}
@Override
protected void brushWall() {
System.out.println("DecoratorZhang刷墙...");
}
@Override
protected void stickTiles() {
System.out.println("DecoratorZhang贴地砖...");
}
@Override
public NiceHouse getNiceHouse() {
super.setDecorateSequence();
return new NiceHouse("DecoratorZhang");
}
}
package com.pattern.builder;
/**
* 具体建造者B
* @author
*
*/
public class DecoratorLi extends Decorator{
@Override
protected void designDrawing() {
System.out.println("DecoratorLi出设计图...");
}
@Override
protected void transHydropower() {
System.out.println("DecoratorLi水电改造...");
}
@Override
protected void brushWall() {
System.out.println("DecoratorLi刷墙...");
}
@Override
protected void stickTiles() {
System.out.println("DecoratorLi贴地砖...");
}
@Override
public NiceHouse getNiceHouse() {
super.setDecorateSequence();
return new NiceHouse("DecoratorLi");
}
}
定义交付的产品类,这里就是简单的装修好的房子:
package com.pattern.builder;
/**
* 相当于建造者模式中的Product
* @author
*
*/
public class NiceHouse {
public NiceHouse(String houseName) {
System.out.println(houseName+"装修房子焕然一新啦!\n");
}
}
测试类:N天后,顾客来到公司,说我的房子装修好了吗?快带我看看:
package com.pattern.builder;
import java.util.ArrayList;
import java.util.List;
/**
* 测试类 Customer
* @author
*
*/
public class Customer {
public static void main(String[] args){
/**
* 顾客来到装修公司,说我要装修两套房子
* 第一套 你先给我出个设计图,然后水电改造,刷墙,贴砖
* 第二套 你先给我水电改造,再出设计图,贴砖,刷墙
* 我们签个合同吧,按期给我装修好,BYE BYE
* 签好合同后,装修公司设计好两套房子的装修顺序,并安排老张和老李分别负责执行
*/
//第一套房子
List sequence1=new ArrayList();
sequence1.add(Sequence.DRAW);
sequence1.add(Sequence.POWER);
sequence1.add(Sequence.BRUSH);
sequence1.add(Sequence.TILES);
DecoratorZhang dzhang=new DecoratorZhang();
BuilderCompany c1=new BuilderCompany(dzhang);
c1.decoration(sequence1);
//第二套房子
List sequence2=new ArrayList();
sequence2.add(Sequence.POWER);
sequence2.add(Sequence.DRAW);
sequence2.add(Sequence.TILES);
sequence2.add(Sequence.BRUSH);
DecoratorLi dli=new DecoratorLi();
BuilderCompany c2=new BuilderCompany(dli);
c2.decoration(sequence2);
}
}
可以看到,建造者模式与工厂模式是极为相似的,建造者模式仅仅只比工厂模式多了一个“导演类”的角色。如果把这个导演类看做是最终调用的客户端(客户),那么图中剩余的部分就可以看作是一个简单的工厂模式了。与工厂模式相比,建造者模式一般用来创建更为复杂的对象,因为对象的创建过程更为复杂,因此将对象的创建过程独立出来组成一个新的类——导演类。也就是说,工厂模式是将对象的全部创建过程封装在工厂类中,由工厂类向客户端提供最终的产品;而建造者模式中,建造者类一般只提供产品类中各个组件的建造,而将具体建造过程交付给导演类。由导演类负责将各个组件按照特定的规则组建为产品,然后将组建好的产品交付给客户端。
优点:
1、将复杂产品的创建步骤分解在不同的方法中,使得我们能够更加精确的控制复杂对象的产生过程。
2、将产品的创建过程与产品本身分离开来,可以使用相同的创建过程来得到不同的产品。
3、每一个具体建造者都相对独立,具有良好的扩展性,使用不同的具体建造者即可得到不同的产品对象。
4、客户端无需关心创建产品的具体细节,统一由“导演类”指定生产过程,调用建造者创建产品。
缺点:
1、建造者模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围受到一定的限制。
2、如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大。
源码下载:http://download.csdn.net/download/pelifymeng2/9994100