王大虎

王大虎:按建造者模式生产超人

王大虎

又是一个典型的建造者模式!哎,不对呀!通用模式上抽象建造者与产品类没有关系呀!是的,我们当然可以加强了,我们在抽象建造者上使用了模板方法模式,每一个建造者都必须返回一个产品,但是产品是如何制造的,则由各个建造者自己负责。我们来看看程序,先看产品类,如代码清单30-6所示。

代码清单30-6 超人产品

 

* * *

 

public class SuperMan { //超人的躯体 private String body; //超人的特殊技能 private String specialTalent; //超人的标志 private String specialSymbol; public String getBody() { return body; } public void setBody(String body) { this.body = body; } public String getSpecialTalent() { return specialTalent; } public void setSpecialTalent(String specialTalent) { this.specialTalent = specialTalent; } public String getSpecialSymbol() { return specialSymbol; } public void setSpecialSymbol(String specialSymbol) { this.specialSymbol = specialSymbol; } }

 

 

 

超人这个产品是由三部分组成:躯体、特殊技能、身份标记,这就类似于电子产品,首先生产出一个固件,然后再安装一个灵魂(软件驱动),最后再打上产品标签。完事了!一个崭新的产品就诞生了!我们的超人也是这样生产的,先生产一个普通的躯体,然后注入特殊技能,最后打上S标签,一个超人生产完毕。我们再来看一下建造者的抽象定义,如代码清单30-7所示。

代码清单30-7 抽象建造者

 

王大虎
王大虎

 

 

public abstract class Builder { //定义一个超人的应用 protected final SuperMan superMan = new SuperMan(); //构建出超人的躯体 public void setBody(String body){ this.superMan.setBody(body); } //构建出超人的特殊技能 public void setSpecialTalent(String st){ this.superMan.setSpecialTalent(st); } //构建出超人的特殊标记 public void setSpecialSymbol(String ss){ this.superMan.setSpecialSymbol(ss); } //构建出一个完整的超人 public abstract SuperMan getSuperMan(); }

 

王大虎

 

一个典型的模板方法模式,超人的各个部件(躯体、灵魂、标志)都准备好了,具体怎么组装则是由实现类来决定。我们先来看成年超人,如代码清单30-8所示。

代码清单30-8 成年超人建造者

 

* * *

 

public class AdultSuperManBuilder extends Builder { @Override public SuperMan getSuperMan() { super.setBody(“强壮的躯体”); super.setSpecialTalent(“会飞行”); super.setSpecialSymbol(“胸前带S标记”); return super.superMan; } }

 

* * *

 

怎么回事?在第11章中讲解建造者模式的时候在产品中使用了模板方法模式,在这里怎么把模板方法模式迁移到建造者了?怎么会这样?你是不是在发出这样的疑问?别疑问了!设计模式只是提供了一个解决问题的意图:复杂对象的构建与它的表示分离,而没有具体定出一个设计模式必须是这样的实现,必须是这样的代码,灵活运用模式才是其根本,别学死板了。

我们继续看未成年超人的建造者,如代码清单30-9所示。

代码清单30-9 未成年超人建造者

 

王大虎

 

public class ChildSuperManBuilder extends Builder { @Override public SuperMan getSuperMan() { super.setBody(“强壮的躯体”); super.setSpecialTalent(“刀枪不入”); super.setSpecialSymbol(“胸前带小S标记”); return super.superMan; } }

 

* * *

 

大家注意看我们这两个具体的建造者,它们都关注了产品的各个部分,在某些应用场景下甚至会关心产品的构建顺序,即使是相同的部件,装配顺序不同,产生的结果也不同,这也正是建造者模式的意图:通过不同的部件、不同装配产生不同的复杂对象。我们再来看导演类,如代码清单30-10所示。

代码清单30-10 导演类

 

* * *

 

public class Director { //两个建造者的应用 private static Builder adu1tBuilder = new AdultSuperManBuilder(); //未成年超人的建造者 private static Builder childBuilder = new ChildSuperManBuilder(); //建造一个成年、会飞行的超人 public static SuperMan getAdultSuperMan(){ return adu1tBuilder.getSuperMan(); } //建造一个未成年、刀枪不入的超人 public static SuperMan getChildSuperMan(){ return childBuilder.getSuperMan(); } }

 

王大虎

 

这很简单,不多说了!看看场景类是如何调用的,如代码清单30-11所示。

代码清单30-11 场景类

 

* * *

 

public class Client { public static void main(String[] args) { //建造一个成年超人 SuperMan adu1tSuperMan = Director.getAdultSuperMan(); //展示一下超人的信息 adu1tSuperMan.getSpecialTalent(); } }

 

* * *

 

这个场景类的写法与工厂方法模式是相同的,但是你可以看到,在建立超人的过程中,建造者必须关注超人的各个部件,而工厂方法模式则只关注超人的整体,这就是两者的区别。

 

 

30.1.3 最佳实践

王大虎

工厂方法模式和建造者模式都属于对象创建类模式,都用来创建类的对象。但它们之间的区别还是比较明显的:

·意图不同

在工厂方法模式里,我们关注的是一个产品整体,如超人整体,无须关心产品的各部分是如何创建出来的;但在建造者模式中,一个具体产品的产生是依赖各个部件的产生以及装配顺序,它关注的是“由零件一步一步地组装出产品对象”。简单地说,工厂模式是一个对象创建的粗线条应用,建造者模式则是通过细线条勾勒出一个复杂对象,关注的是产品组成部分的创建过程。

·产品的复杂度不同

工厂方法模式创建的产品一般都是单一性质产品,如成年超人,都是一个摸样,而建造者模式创建的则是一个复合产品,它由各个部件复合而成,部件不同产品对象当然不同。这不是说工厂方法模式创建的对象简单,而是指它们的粒度大小不同。一般来说,工厂方法模式的对象粒度比较粗,建造者模式的产品对象粒度比较细。

两者的区别有了,那在具体的应用中,我们该如何选择呢?是用工厂方法模式来创建对象,还是用建造者模式来创建对象,这完全取决于我们在做系统设计时的意图,如果需要详细关注一个产品部件的生产、安装步骤,则选择建造者,否则选择工厂方法模式。

 

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注