Java设计模式--建造者模式【Builder Pattern】

来源:互联网 发布:童年电视剧主题曲 知乎 编辑:程序博客网 时间:2024/05/18 15:28

        昨晚回到家里,我爸爸气冲冲地跟我诉苦,“哎!,干个装修容易么?顾客啥都不懂,还非得规定装修顺序,要先贴地板砖后刷墙,到时候贴好的地砖上全是泥,哪有这么干活的?”老爸干了一辈子的装修,一切事宜由他全权负责,难免心力憔悴。但是,我仔细想了下这个事情,如果老爸签订了一个公司,公司负责接活揽活,规定装修要求,老爸只负责执行,那不就轻松了吗?于是我就想起了建造者模式。

      建造者模式的定义是:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示它允许用户通过制定的对象类型和内容来创建他们,但是用户并不需要知道这个复杂对象是如何构建的,它只需要明白通过这样做我可以得到一个完整的复杂对象实例。

     建造者模式是为了将构建复杂对象的过程和它的部件解耦。因为一个复杂的对象,不但有很多大量组成部分,如汽车,有很多部件:车轮方向盘 发动机还有各种小零件等等,部件很多,但远不止这些,如何将这些部件装配成一辆汽车,这个装配过程也很复杂(需要很好的组装技术),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<String> 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<String> sequence = new ArrayList<String>();//装修顺序   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<String> 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{@Overrideprotected void designDrawing() {System.out.println("DecoratorZhang出设计图...");}@Overrideprotected void transHydropower() {System.out.println("DecoratorZhang水电改造...");}@Overrideprotected void brushWall() {System.out.println("DecoratorZhang刷墙...");}@Overrideprotected void stickTiles() {System.out.println("DecoratorZhang贴地砖...");}@Overridepublic NiceHouse getNiceHouse() {super.setDecorateSequence();return new NiceHouse("DecoratorZhang");}}
package com.pattern.builder;/** * 具体建造者B * @author  * */public class DecoratorLi extends Decorator{@Overrideprotected void designDrawing() {System.out.println("DecoratorLi出设计图...");}@Overrideprotected void transHydropower() {System.out.println("DecoratorLi水电改造...");}@Overrideprotected void brushWall() {System.out.println("DecoratorLi刷墙...");}@Overrideprotected void stickTiles() {System.out.println("DecoratorLi贴地砖...");}@Overridepublic 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<String> sequence1=new ArrayList<String>();    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<String> sequence2=new ArrayList<String>();    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

   
原创粉丝点击