设计模式- - builder 建造者模式

Builder建造者模式

建造者模式:是将一个复杂对象的创建与它的表像分离,使得同样的构建过程可以创建不同的表示。


 

 

 

我们首先理解一下建造者模式:根据他的定义,先拿人穿衣服来解释:

         我们先理解第二句话“同样的构建过程”是指对象的创建有一个固定的过程,好比穿衣服,必须是先穿内衣,然后穿外衣,然后穿袜子,然后是鞋,过程是不变的。(不要跟我提内裤后穿的例子超人,那种不适合建造者模式。也不要想先穿鞋后穿裤子或者衣服,那样太非主流也不舒服。)

         就是在这种“同样的构建过程”中,男人或者女人们穿出了不同风格的衣服,展示了不同个性的区别。

         所以:建造者模式使用的前提是对象创建过程或者流程要相同,也就是很固定。

第一句“一个复杂的对象”,这里如果用穿衣服来比喻,就是各种风格的衣服,如西装、休闲服、运动装等等,衣服风格非常多,很繁杂。

         “对象创建与它的表象分离”,说明你看到衣服的风格与穿衣服的过程是分开的。

         用穿衣服总结:将穿衣服的过程与看到衣服的款式分离,使得同样的穿衣过程可以穿出不同风格的衣服。

类图:


代码:

 

//抽象接口 -- 穿衣服
public abstract class Wear {
//  抽象方法 -- 穿上衣
    public abstract void coat(); 
//  抽象方法 -- 穿裤子
    public abstract void pants();
//  抽象方法 -- 穿袜子
    public abstract void socks(); 
//  抽象方法 -- 穿鞋子
    public abstract void shoes();   
//    形象展示
    public void show(){
        System.out.println("\n我今天的装扮是:");
        this.coat();
        this.pants();
        this.socks();
        this.shoes();
    }
}
 

 

/**
 * 西装的打扮
 */
public class Suit extends Wear {
    public void coat() {
        System.out.print("上衣是西服");
    }
    public void pants() {
        System.out.print(",下身是西裤");
    }
    public void shoes() {
        System.out.print(",黑色的袜子");
    }
    public void socks() {
        System.out.print(",黑色的皮鞋!");
    }
}
 

 

/**
 * 运动装的打扮
 */
public class SportsWear extends Wear{
    public void coat() {
        System.out.print("上身是运动服");
    }
    public void pants() {
        System.out.print(",下身是运动裤!");
    }
    public void socks() {
        System.out.print(",白色的袜子!");
    }
    public void shoes() {
        System.out.print(",白色的运动鞋");
    }
}
 

 

/**
 * 指挥者 -- 张三 
 * 根据自己的想法穿不同风格的衣服
 */
public class JoeSmith {
//    穿衣服
    private Wear wear; 
//    给人的感觉
    public void feel(){
        wear.show();
    }
    /** 
     * 张三的构造方法,必须穿衣服 
     **/
    public JoeSmith(Wear wear) {
        this.wear = wear;
    }
//    getter && setter
    public Wear getWear() {
        return wear;
    }
    public void setWear(Wear wear) {
        this.wear = wear;
    }
}
 

 

public class Client {
    public static void main(String[] args) {
//        今天上班,穿西装
        Wear wear = new Suit();
        JoeSmith js = new JoeSmith(wear);
        js.feel();
//        下班了,去健身房,换套运动装
        js.setWear( new SportsWear());
        js.feel();
    }
}
 

 

张三作为管理这,有一个构建各种风格衣服的穿衣服的建造者类,而具体的建造者是各种风格迥异的衣服,张三穿衣服出门,并且展示自己穿的一身衣服本来是一体化的,而建造者模式就是将张三在选择穿什么款式衣服出门的时候,将穿衣服的过程与最后的形象分离开了,解决了张三穿其它款式衣服时,又去建立一个穿衣流程的繁琐。

这里重点是将穿衣的过程和看到的款式进行分离。

         下面我们还有个比喻:餐馆点菜,菜谱中菜的品种类型成百上千,而顾客关心的是菜的色、香、味,做菜的过程大家都知道:配菜、炒菜、放调料、出锅。但是做的方法非常复杂,配的菜样不同,调料多少不同,烹饪时间不同等等,但是厨师却能让同样的做菜流程,做不同的口味菜肴,呈现在顾客面前,而且不同的厨师能做出不同的美味,比如川菜厨师炒菜比较好吃,两湖的厨师对蒸菜比较拿手。对于厨师来说,就是把这种菜的制作过程与顾客点的菜分离,使得同样的做菜流程可以做出各种千变万化的美味。而厨师就是菜的建造者,菜是他们的产品。而服务员就是指挥者,餐馆顾客就是客户。

 


 

根据这个类图,我们模拟一个流程,顾客点了菜。服务员记下后通知厨房的厨师做菜,厨房里的张师傅会做川菜,而李师傅会做蒸菜。厨师做好菜后就传菜给服务员,服务员将菜给顾客端上。让我们看看代码如何实现:

 

 

/** 服务员 */
public class Waiter {
//    做菜
    public void carte(Master master) {
        master.garnish();
        master.cooking();
        master.condiments();
        master.pan();
    }
}
 

 

/**
 * 建造者抽象接口--厨师
 */
public abstract class Master {
//    配菜
    public abstract void garnish();
//    做菜
    public abstract void cooking();
//    放入调料
    public abstract void condiments();
//    出锅
    public abstract void pan();
//    传菜
    public abstract Vegetables pantry();
}
 

 

/**
 * 厨师--李师傅
 */
public class ChefLee extends Master {
protected Vegetables vegetables 
= new Vegetables();
//  配菜
    public void garnish(){
        vegetables.add("配好原料了");
    }
//    做菜
    public void cooking(){
        vegetables.add("蒸菜");
    }
//    放入调料
    public void condiments(){
        vegetables.add("放调料");
    }
//    出锅
    public void pan(){
        vegetables.add("菜炒好了!");
    }
//    传菜
    public Vegetables pantry(){
        return vegetables;
    }
}
 

 

/**
 * 具体建造者--张师傅
 */
public class ChefZhang extends Master{
protected Vegetables vegetables 
= new Vegetables();
//  配菜
    public void garnish(){
        vegetables.add("配好原料了");
    }
//    做菜
    public void cooking(){
        vegetables.add("下锅炒");
    }
//    放入调料
    public void condiments( ){
        vegetables.add("放调料");
    }
//    出锅
    public void pan(){
        vegetables.add("炒好了!");
    }
//    传菜
    public Vegetables pantry(){
        return vegetables;
    }
}
 

 

/**
 * 具体产品--菜
 */
public class Vegetables {
//    菜的信息
    private List<String> info = new ArrayList<String>();
//    菜的完成过程
    public void add(String str){
        info.add(str);
    }
    //做菜情况说明
    public void explain(){
        System.out.println("做菜流程:");
        for(String s : info){
            System.out.print(" " + s); 
        }
    }
}

 

 

/**
 * 客户端测试
 */
public class Client {
    public static void main(String[] args) {
//        点菜
        Waiter waiter = new Waiter();
        Master zhang = new ChefZhang();
        Master lee = new ChefLee();
//        通知张师傅做菜
        waiter.carte(zhang);
        Vegetables spicy = zhang.pantry();
//        菜做好了
        spicy.explain();
//        通知李师傅做菜
        waiter.carte(lee);
        Vegetables fish = lee.pantry();
//      菜做好了
        fish.explain();
    }
}
 

 

适用性:

1 创建复杂对象的算法需要独立于对象各个部分的创建和组合方式。

2 对象的构造过程允许被构造的对象有不同的表现形式时

 

 

实现要点:

1 组装和创建接口:Builder类的接口要足够泛化,能够实现各个具体的builder

2 产品没有抽象类:这是因为创建对象的算法复杂或是形式多样,因此没有必要也无可能抽象出一个抽象类 

3 Builder中的默认空函数,而不是纯虚函数:在C++中在派生类里只要改变感兴趣的方法,而不需要重新定义整个类的所有方法。

4 Builder模式 主要用于“分步骤构建一个复杂的对象”。在这其中“分步骤”是一个稳定的乘法,而复杂对象的各个部分则经常变化。

 

5 Builder模式主要在于应对“复杂对象各个部分”的频繁需求变动。其缺点在于难以应对“分步骤构建算法”的需求变动。

 

6 Abstract Factory模式解决“系列对象”的需求变化,Builder模式解决“对象部分”的需求变化。Builder模式通常和Composite模式组合使用

 

 

 

参考文章:http://www.cnblogs.com/CS106A/archive/2012/06/03/2532763.html

 

猜你喜欢

转载自chwshuang.iteye.com/blog/1632073