作者:云都小生
概念
建造者模式, 本质是将一个复杂对象的创建与它的表示分离,使得同样的构建过程可以创建不同的表示。
什么是复杂对象呢?举个栗子,一个赛车游戏,里面的汽车就是复杂的对象,只不过这些复杂的对象都不一样,有不同的轮胎,不同的电池,不同的发动机等等。
建造者模式的角色
建造者模式中有这么几个角色:抽象建造者、具体建造者、产品角色、指挥者。
抽象建造者:它为创建一个产品对象(汽车)的各个部件指定抽象接口,该接口中一般会有两种方法,一种是创建各种部件,一种是返回该对象。
具体建造者:实现或继承了抽象建造者,用于构建复杂对象,实现了抽象建造者中创建各种部件的方法。
产品类:复杂对象,这个产品需要由许多复杂的对象装配而成。
指挥者者:这个指挥者,负责调用建造者中关于产品部件创建、装配的方法。
这里你可能会觉得奇怪,为什么会多出个指挥者。这个指挥者其实我们生活中也经常碰到,例如一个销售代理员,我们像一个销售代理员报出产品的参数,销售代理员只需要把型号、配置报给产家,组装与构建产品的工作它都不需要做。
范例
//汽车原型
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)