设计模式_建造者模式


作者:云都小生


概念



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

什么是复杂对象呢?举个栗子,一个赛车游戏,里面的汽车就是复杂的对象,只不过这些复杂的对象都不一样,有不同的轮胎,不同的电池,不同的发动机等等。


建造者模式的角色


建造者模式中有这么几个角色:抽象建造者、具体建造者、产品角色、指挥者。

抽象建造者:它为创建一个产品对象(汽车)的各个部件指定抽象接口,该接口中一般会有两种方法,一种是创建各种部件,一种是返回该对象。

具体建造者:实现或继承了抽象建造者,用于构建复杂对象,实现了抽象建造者中创建各种部件的方法。

产品类:复杂对象,这个产品需要由许多复杂的对象装配而成。

指挥者者:这个指挥者,负责调用建造者中关于产品部件创建、装配的方法。

这里你可能会觉得奇怪,为什么会多出个指挥者。这个指挥者其实我们生活中也经常碰到,例如一个销售代理员,我们像一个销售代理员报出产品的参数,销售代理员只需要把型号、配置报给产家,组装与构建产品的工作它都不需要做。


范例



//汽车原型
public class Car {
private String wheel; //车轮
private String battery; //电池
private String engine; //发动机

    public String getWheel() {
        return this.wheel;
    }

    public void setWheel(String wheel) {
        this.wheel = wheel;
    }

    public String getBattery() {
        return this.battery;
    }
    public void setBattery(String battery) {
        this.battery = battery;
    }

    public String getEngine() {
        return this.engine;
    }
    public void setEngine(String engine) {
        this.engine = engine;
    }
}


//抽象建造者
public abstract class CarBuilder {
    //创建产品对象
    protected  Car car = new Car();

    public  abstract void buildWheel();
    public  abstract void buildBattery();
    public  abstract void buildEngine();

    //返回产品对象
    public Car createCat() {
        return  car;
    }
}

//具体建造者
public class AttackBuilder extends CarBuilder{

    public void buildWheel() 
    {
        car.setWheel("德国马牌");
    }

    public void buildBattery() 
    {
        car.setBattery("骆驼");
    }

    public void buildEngine()
    {
        car.setEngine("宝马M54");
    }
}



//指挥者
public class CarController {
     public Car construct(CarBuilder cb)
     {
            Car car;
            cb.buildWheel();
            cb.buildEngine();
            cb.buildBattery();
            car = cb.createCat();
            return car;
     }
}

//客户端
public class Client {
    public  static void main(String args[])
    {
           CarBuilder cb = new AttackBuilder();

           CarController ac = new  CarController();
           Car car = ac.construct(cb); //通过指挥者创建完整的建造者对象

           System.out.println("发动机:" + car.getEngine());
           System.out.println("电池:" + car.getBattery());
           System.out.println("车轮:" + car.getWheel());
    }
}

赛车游戏里有许多不同的汽车,汽车是由许多不同的部件组合构成的对象,这个对象的装配要与客户端分离。用户想要什么汽车,只需要向指挥者传入一个参数,把具体车的构建类传过去,剩下的事由指挥类去做。

指挥类负责调用按次序配装方法,产生不同的部件,最后将东西组装起来,返回一个完整的对象。


钩子方法



如果有一辆车不需要创建电池,不需要组装电池,它自带电池··· 类似这种情况,我们就可以用钩子方法。

//具体产品
public class Car {
    private String wheel;   //车轮
    private String battery; //电池
    private String engine;  //发动机

    public String getWheel() {
        return this.wheel;
    }

    public void setWheel(String wheel) {
        this.wheel = wheel;
    }

    public String getBattery() {
        return this.battery;
    }

    public void setBattery(String battery) {
        this.battery = battery;
    }

    public String getEngine() {
        return this.engine;
    }
    public void setEngine(String engine) {
        this.engine = engine;
    }
}

//抽象建造者
public abstract class CarBuilder {
    //创建产品对象
    protected  Car car = new Car();

    public  abstract void buildWheel();
    public  abstract void buildBattery();
    public  abstract void buildEngine();

    //钩子方法:false表示没有电池
    boolean isBattery()
    {
        return false;
    }

    //返回产品对象
    public Car createCat() {
        return  car;
    }
}

//具体建造者
public class AttackBuilder extends CarBuilder{

    public AttackBuilder()  //我本来就有电池
    {
        car.setBattery("骆驼");
    }

    public void buildWheel() 
    {
        car.setWheel("德国马牌");
    }


    public void buildEngine()
    {
        car.setEngine("宝马M54");
    }

    boolean isBattery()
    {
        return true;
    }

    public void buildBattery() {}
}

//指挥类
public class CarController {
     public Car construct(CarBuilder cb)
     {
            Car car;
            cb.buildWheel();
            cb.buildEngine();
            if(cb.isBattery())  //判断是否有电池,没有再调用
            {
                 cb.buildBattery();
            }
            car = cb.createCat();
            return car;
     }
}

//客户端
public class Client {
    public  static void main(String args[])
    {
           CarBuilder cb = new AttackBuilder();

           CarController ac = new  CarController();
           Car car = ac.construct(cb); //通过指挥者创建完整的建造者对象

           System.out.println("发动机:" + car.getEngine());
           System.out.println("电池:" + car.getBattery());
           System.out.println("车轮:" + car.getWheel());
    }
}

一旦这种汽车本身带有电池,我就不用去build电池。

上面这两个例子,我觉得还是比较容易理解的,比单例模式和原型模式只难一点点。我唯一晕的地方,在于抽象建造者中的 protected Car car = new Car();

当有一个具体的构建者从它这里继承的时候,自动就有一个car对象。还有抽象建造者中的方法createCat(),在继承(或实现)之后,没有重写这个方法。


优缺点



优点:工厂模式是创建一个简单的部件,而建造者模式是创建一个复杂的整体,后者在复杂对象的创建下更适用一些。建造者模式中的指挥类,还会按次序构建部件,逻辑清晰。

建造者模式和三个工厂模式有些优点是相同的,例如对象创建不在客户端、客户端不需要知道产品内部建造的细节。

我们新增一个具体的产品,就需要新增一个具体的建造者,几乎无论怎么增加,我们都不用修改之前的建造者和产品。

缺点:
如果产品差异太大,它们的建造者就不一样,这样不适用了。想一想,汽车和飞机,都是不同的复杂对象,我们的建造者不能从汽车的抽象建造者类继承。

2017/10/14 9:37:04 @Author:云都小生(Cloudking)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值