23种设计模式之--建造者模式

又是一个周三,快要下班了,老大突然拉住我,喜滋滋的告诉我:“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公司可以随意组合,它要什么顺序的车模我就必须生成什么顺序的车辆,客户就是上帝,所有我们应该找一个导演,指挥各个事件的先后顺序,然后为每种顺序指定一个代码,你说一种我们立刻给你生产处理。

 

 

posted @ 2013-12-06 17:32  水之原  阅读(630)  评论(0编辑  收藏  举报