设计模式之禅——建造者模式

建造者模式定义:
建造者模式也叫做生成器模式——将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。)

例子:我们要生产一个简单车模(汽车模型),汽车模型要有启动、停止、引擎发出声音、喇叭响等功能。现在我要让用户根据自己的喜好来选择这些功能的顺序~(接着上一篇模板方法模式的例子)

我们做出了下面的设计,见UML图
设计模式之禅——建造者模式_第1张图片

见代码

//汽车模型的抽象类
public abstract class CarModel{
//sequence就是客户要求执行的方法的顺序
    private ArrayList sequence = new ArrayList();
    protected abstract void start();
    protected abstract void stop();
    protected abstract void alarm();
    protected abstract void engineBoom();
    final public void run(){
        for(int i = 0; i < this.sequence.size(); ++i){
            String actionName = this.sequence.get(i);
            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();
            }
        }
    }
    final public void setSequence(ArrayList sequence){
        this.sequence = sequence;
    }
}
//Benz模型
public class BenzModel extends CarModel {

    @Override
    protected void start() {
        System.out.println("奔驰车开始跑。。。");

    }

    @Override
    protected void stop() {
        System.out.println("奔驰车停下。。。");


    }

    @Override
    protected void alarm() {
        System.out.println("奔驰车喇叭响...");

    }

    @Override
    protected void engineBoom() {
        System.out.println("奔驰车的引擎发出声音了。。。");

    }
}
//宝马模型
public class BMWModel extends CarModel {

    @Override
    protected void start() {
        System.out.println("宝马车开始跑。。。");

    }

    @Override
    protected void stop() {
        System.out.println("宝马车停下。。。");


    }

    @Override
    protected void alarm() {
        System.out.println("宝马车喇叭响...");

    }

    @Override
    protected void engineBoom() {
        System.out.println("宝马车的引擎发出声音了。。。");

    }

}
public class Client {


    public static void main(String[] args) {
        BenzModel benz = new BenzModel();
        ArrayList sequence = new ArrayList();
        sequence.add("engine boom");//客户要求,引擎先发出声音
        sequence.add("start");//开始跑
        sequence.add("stop");
        benz.setSequence(sequence);
        benz.run();
    }

}

ok,我们现在的设计能够满足客户的要求。可是如果有N个用户呢?可能你需要设计N个场景类来满足。当N=1000000000000时…….怎么办呢?

1、新加一个导演类!导演这里有所有的顺序,这样就可以避免根据客户临时提出来的需求来设计而手忙脚乱了。同时导演类起到封装的作用,避免高层模块深入到建造者内部的实现类。当建造者模式很大时,导演类可以有很多个。

2、然后再新加一个建造者类,建造者根据导演类的要求来生产具体的对象。

见UML图,(UML图有点小问题——导演类聚合多个汽车建造者,但不影响理解)
设计模式之禅——建造者模式_第2张图片

见代码`

//产品类——汽车模型不变
public abstract class CarModel{
    private ArrayList sequence = new ArrayList();
    protected abstract void start();
    protected abstract void stop();
    protected abstract void alarm();
    protected abstract void engineBoom();
    final public void run(){
        for(int i = 0; i < this.sequence.size(); ++i){
            String actionName = this.sequence.get(i);
            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();
            }
        }
    }
    final public void setSequence(ArrayList sequence){
        this.sequence = sequence;
    }
}
public class BMWModel extends CarModel {

    @Override
    protected void start() {
        System.out.println("宝马车开始跑。。。");

    }

    @Override
    protected void stop() {
        System.out.println("宝马车停下。。。");


    }

    @Override
    protected void alarm() {
        System.out.println("宝马车喇叭响...");

    }

    @Override
    protected void engineBoom() {
        System.out.println("宝马车的引擎发出声音了。。。");

    }

}
public class BenzModel extends CarModel {

    @Override
    protected void start() {
        System.out.println("奔驰车开始跑。。。");

    }

    @Override
    protected void stop() {
        System.out.println("奔驰车停下。。。");


    }

    @Override
    protected void alarm() {
        System.out.println("奔驰车喇叭响...");

    }

    @Override
    protected void engineBoom() {
        System.out.println("奔驰车的引擎发出声音了。。。");

    }
//我们新增的汽车建造者抽象类
public abstract class CarBuilder {
    public abstract void setSequence(ArrayList sequence);
    public abstract CarModel getCarModel();
}
//宝马建造者实现类
public class BMWBuilder extends CarBuilder {

    private BMWModel bmw;
    @Override
    public void setSequence(ArrayList sequence) {
        this.bmw.setSequence(sequence);
    }

    @Override
    public CarModel getCarModel() {
        // TODO Auto-generated method stub
        return bmw;
    }

}
//奔驰建造者实现类
public class BenzBuilder extends CarBuilder {

    private BenzModel benz = new BenzModel();

    @Override
    public void setSequence(ArrayList sequence) {
        this.benz.setSequence(sequence);
    }

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

}
//导演类
public class Director {
    private ArrayList sequence = new ArrayList();
    private BenzBuilder benzBuilder = new BenzBuilder();
    private BMWBuilder bmwBuilder = new BMWBuilder();

    public BenzModel getABenzModel(){
        this.sequence.clear();
        this.sequence.add("start");
        this.sequence.add("stop");
        this.benzBuilder.setSequence(sequence);
        return (BenzModel)this.benzBuilder.getCarModel();
    }
    public BenzModel getBBenzModel(){
        this.sequence.clear();
        this.sequence.add("start");
        this.sequence.add("alarm");
        this.sequence.add("stop");
        this.benzBuilder.setSequence(sequence);
        return (BenzModel)this.benzBuilder.getCarModel();
    }
    //好多种...

}
//场景类
public class Client {


    public static void main(String[] args) {
        Director director = new Director();
        for(int i = 0; i < 10; ++i){
            director.getABenzModel().run();
        }
        for(int i = 0; i < 10; ++i){
            director.getBBenzModel().run();
        }
    }

}

建造者模式也是有通用类图的,这个建议自己尝试一下~

建造者模式的优点

  • 封装性
  • 建造者独立,容易拓展。BenzBuilder和BMWBuilder是相互独立的,对系统的拓展非常有利。
  • 便于控制细节风险。因为具体的建造者是独立的,因此可以对建造过程逐步细化,而不对其他的模块产生影响。

    建造者模式的使用场景

  • 相同的方法,不同的顺序,产生不同的事件结果时

  • 多个部件或零件,都可以装配到一个对象中,但是产生的运行结果又不相同时
  • 产品类非常复杂,或者产品类中的调用方法的顺序不同产生了不同的效能

建造者模式的注意事项

  • 建造者模式关注的是零件类型和装配工艺(顺序),而工厂方法关心的整体的对象。二者虽然都是创建类设计模式,但还是有很大不同,不要用混了~

你可能感兴趣的:(设计模式,设计模式之禅)