23種設計模式之--建造者模式

水之原發表於2013-12-06

又是一個週三,快要下班了,老大突然拉住我,喜滋滋的告訴我:“XX公司很滿意我們做的模型,又簽訂了一個合同,把賓士、寶馬的車輛模型都交給我們公司製作了,不過這次又額外增加了一個需求:汽車的啟動、停止、喇叭聲音、引擎聲音都由客戶自己控制,他想什麼順序就什麼順序, 這個沒問題吧?”

又是一個時間緊,工程量大的專案。首先,我們分析一下需求,賓士、寶馬都是一個產品,它們有共有的屬性,XX公司關心的是單個模型的執行過程:賓士模型A先有引擎聲音,然後再響喇叭;賓士B是先啟動起來,然後再有引擎聲音,這才是XX公司要關心的。那到我們老大這邊呢,就是滿足人家的要求,要什麼順序就立馬能產生什麼順序的模型出來,我就負責老大的要求實現出來,而且還要批量的,也就是說XX公司下單訂購寶馬A車模,我們老大馬上就找我“生產一個這樣的車模, 啟動完畢後,喇叭響一下”,然後我們就準備開始批量生產這些模型。

看起來需求還是比較複雜,我們一個個解決,先從產品類入手。

public abstract class CarModel
{
    private List<String> sequence = new ArrayList<String>();

    final public void setSequence( List<String> sequence )
    {
        this.sequence = sequence;
    }

    protected abstract void start();

    protected abstract void stop();

    protected abstract void alarm();

    protected abstract void engineBoom();

    final public void run()
    {
        for ( String actionName : sequence )
        {
            if ( actionName.equalsIgnoreCase( "start" ) )
            {
                this.start();
            } else if ( actionName.equalsIgnoreCase( "stop" ) )
            {
                this.stop();
            } else if ( actionName.equalsIgnoreCase( "alarm" ) )
            {
                this.alarm();
            } else if ( actionName.equalsIgnoreCase( "engine boom" ) )
            {
                this.engineBoom();
            }
        }
    }
}

 

CarModel的設計原理是這樣的,setSequence方法是允許客戶自己設定一個順序,是要先啟動響一下喇叭再跑起來,還是要先響一下喇叭再啟動。對於一個具體的模型永遠都固定的,但是對於N多個模型就是動態的了。在子類中實現父類的基本方法,run方法讀取sequence, 然後遍歷sequence中的字元呂,哪個字串在先,就先執行哪個方法。

 

賓士模型程式碼:

public class BenzModel extends CarModel
{
    @Override
    protected void alarm()
    {
        System.out.println( "Benz alarmming" );
    }

    @Override
    protected void engineBoom()
    {
        System.out.println( "Benz startup engine boom" );
    }

    @Override
    protected void start()
    {
        System.out.println( "Benz startting" );
    }

    @Override
    protected void stop()
    {
        System.out.println( "Benz Stopping" );
    }
}

寶馬模型程式碼:

public class BWMModel extends CarModel
{
    @Override
    protected void alarm()
    {
        System.out.println( "BWM alarmming" );
    }

    @Override
    protected void engineBoom()
    {
        System.out.println( "BWM startup engine boom" );
    }

    @Override
    protected void start()
    {
        System.out.println( "BWM startting" );
    }

    @Override
    protected void stop()
    {
        System.out.println( "BWM Stopping" );
    }
}

兩個產品類實現都完成,我們來模擬一下XX公司的要求:生產一個賓士模型,要求跑的時候,先發動引擎,然後再掛擋啟動,然後停下來,不需要喇叭。

public class Client
{
    public static void main( String[] args )
    {
        CarModel benz = new BenzModel();
        List<String> sequence = new ArrayList<String>();
        sequence.add( "engine boom" );
        sequence.add( "start" );
        sequence.add( "stop" );
        benz.setSequence( sequence );
        benz.run();
    }
}

 

看, 我們組裝了這樣的一輛汽車,滿足了XX公司的需求。但是想想我們的需求, 汽車動作順序是要能夠隨意調整的。所有我們應該為產品模型定義一個建造者,你要啥順序直接告訴建造者,由建造者建造。

這樣才以批量生產某種型別的汽車。

public abstract class CarBuilder
{
    public abstract void setSequence( List<String> sequence);
    public abstract CarModel getCarModel();
}
public class BenzBuilder extends CarBuilder
{
    private CarModel benz = new BenzModel();

    @Override
    public CarModel getCarModel()
    {
        return this.benz;
    }

    @Override
    public void setSequence( List<String> sequence )
    {
        this.benz.setSequence( sequence );
    }
}
public class BWMBuilder extends CarBuilder
{
    private CarModel bwm = new BWMModel();

    @Override
    public CarModel getCarModel()
    {
        return this.bwm;
    }

    @Override
    public void setSequence( List<String> sequence )
    {
        this.bwm.setSequence( sequence );
    }
}

現在我們生產同一種型別的汽車就容易多了

public class Client
{
    public static void main( String[] args )
    {
        List<String> sequence = new ArrayList<String>();
        sequence.add( "engine boom" );
        sequence.add( "start" );
        sequence.add( "stop" );

        BenzBuilder benzBuilder = new BenzBuilder();
        benzBuilder.setSequence( sequence );

        CarModel benz = benzBuilder.getCarModel();
        benz.run();
    }
}

 

我們做專案時,經常會有一個共識:需求是無底洞,是無理性的,不可能你告訴它不增加需求就不增加,這4個過程(start,stop,alarm,engineBoom)按照排列組合有很多種,XX公司可以隨意組合,它要什麼順序的車模我就必須生成什麼順序的車輛,客戶就是上帝,所有我們應該找一個導演,指揮各個事件的先後順序,然後為每種順序指定一個程式碼,你說一種我們立刻給你生產處理。

 

 

相關文章