4.建造者模式(Builder Pattern)
GOF中各种构造模式的目的都是获取最终产品。在Terran章节中介绍了三种工厂模式的关注点仅仅是最终产品;而本章所介绍的建造者模式,关注的除了产品之外,它还关心着产品构造的细节,这一点是Builder模式和Factory模式最显著的区别。
在上一章中,我们曾经说过“使用者通常是不关心产品具体成员的创建过程的,因此也不应当把各个产品的创建过程揉合到具体逻辑之中”。大多数情况确实是这样的,但是可以想象一些特殊情况:譬如你使用Builder模式去调配一杯鸡尾酒,应当希望可以调整内部各种掺酒的比例;又或者你使用Builder模式去装配一部汽车,不幸汽车出厂时发现质量有问题,你肯定希望能快速的诊断到底是装配的时候发动机出了问题,还是装配的轮胎或者挡风玻璃有问题。
目的:
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
场景:
Sarah Kerrigan(剧情中Zerg的刀锋女王)的部落现在还弱小,而且正在受到Jim Raynor的持续压制,为了能扭转不利的局面,Kerrigan升级了Overlord的速度与运输技能,很明显,Kerrigan要空投了。
根据当前的科技状况,Kerrigan能掌握的部队有:
Overlord:领主,现在主要充当运输机的角色。
Zergling:小狗,Zerg的初级近战兵种。
Hydralisk:刺蛇,Zerg的初级远程兵种。
Lurker:潜伏者,Zerg的中级兵种,擅长范围攻击。
分析:
Kerrigan的空投策略是多点小规模同时骚扰,这需要多组空投部队(最终产品),每组空投部队都由一个Overload装在着,外表看起来是一样的,执行的行为也都是攻击、破坏、骚扰;但是我们可以根据战场实际情况,调整装配进各个Overload中的部队的细节,获得更好的效果。
当前为了演示需要,制定了SceneA和SceneB两种场景说适合的兵力配置,先看看以下UML图和代码:
图4.1 战斗部队及建造者的UML图
下面是一个Zerg战斗部队(最终产品)的代码,这支部队各个兵种的数量是可调整的:
/**
* Builder的产品,代表一组骚扰部队
*/
public class ZergProduct {
private int overload;
private int zergling;
private int hydralisk;
private int lurker;
public int getOverload() {
return overload;
}
public void setOverload(int overload) {
this.overload = overload;
}
public int getZergling() {
return zergling;
}
public void setZergling(int zergling) {
this.zergling = zergling;
}
public int getHydralisk() {
return hydralisk;
}
public void setHydralisk(int hydralisk) {
this.hydralisk = hydralisk;
}
public int getLurker() {
return lurker;
}
public void setLurker(int lurker) {
this.lurker = lurker;
}
public String toString() {
return "当前部队包括:" + overload + "个Overload; " + zergling + "个Zergling; " + hydralisk + "个Hydralisk; " + lurker + "个Lurker";
}
}
|
接着,我们建立了2中不同的场景使用不同的空投部队去应对:
场景A空投了1个Overload; 2个Zergling; 1个Hydralisk; 1个Lurker
场景B空投了1个Overload; 4个Hydralisk
有一点需要说明一下,在实际情况下,两种产品的不同一般不会仅仅体现在产品组成部分的数量变化上,事实上如果仅仅是数量的不一致,那可以把这种区别看作是装配期间才需要关心的职责,放入到Director中完成。这里的A、B场景建造者只保留数量上的区别主要是为了简易起见,实际情况下我们可以在这里处理更本质的差异,譬如除了放入不同Overload中Zergling个数不一样外,还可以根据不同情况将“吃粗粮长大的Zergling”、“吃奶粉长大的Zergling”放入不同的Overload中。
建立这2种建造者的实现代码如下:
/**
* 适应场景A的装配器
*/
public class SceneABuilder implements ArmyBuilder {
ZergProduct product = new ZergProduct();
public void buildHydralisk() {
product.setHydralisk(1);
}
public void buildLurker() {
product.setLurker(1);
}
public void buildOberload() {
product.setOverload(1);
}
public void buildZergling() {
product.setZergling(2);
}
public ZergProduct getResult() {
ZergProduct finlishProduct = product;
product = new ZergProduct();
return finlishProduct;
}
}
/**
* 适应场景B的装配器
*/
public class SceneBBuilder implements ArmyBuilder {
ZergProduct product = new ZergProduct();
public void buildHydralisk() {
product.setHydralisk(4);
}
public void buildLurker() {
product.setLurker(0);
}
public void buildOberload() {
product.setOverload(0);
}
public void buildZergling() {
product.setZergling(0);
}
public ZergProduct getResult() {
ZergProduct finlishProduct = product;
product = new ZergProduct();
return finlishProduct;
}
}
|
同时,我们将具体的建造过程放到Director里面以便分离职责。这样当日后部队建造顺序需要调整,譬如要求先建造Zergling,再建立Hydralisk我们仅需要调整Director的内容。又或者产品的某一部分不需要或者不可用的时候,譬如当虫族Spawning
Pool(血池,制造Zergling的必须建筑)被破坏之后,我们要达到不能再使用Zergling这种兵种的效果,就不需要修改每个具体的建造者,只需要在Director中把builder.buildZergling();这句去掉就可以生产出来的产品不再包含Zergling。
Director的实现代码如下:
/**
* 描述建造者的建造过程
*/
public class Director {
public void construct(ArmyBuilder builder) {
builder.buildOberload();
builder.buildHydralisk();
builder.buildZergling();
builder.buildLurker();
}
}
|
然后再看一下Builder模式是如何被使用的:
/**
* 模拟建造两只部队
*/
public class WarField {
public static void main(String[] args) {
Director director = new Director();
ArmyBuilder builderA = new SceneABuilder();
ArmyBuilder builderB = new SceneBBuilder();
director.construct(builderA);
director.construct(builderB);
System.out.println(builderA.getResult());
System.out.println(builderB.getResult());
}
}
|
从上面的过程可以看到,Builder模式与Abstract Factory模式从目的上讲是相当类似的,都是为了生产出复杂产品(两个例子的产品都是一组多兵种组合的协同小组),他们的主要区别就是Abstract Factory模式的建造过程完全封装在工厂之内,使用时调用工厂立刻获取到产品。而Builder模式将生产过程放在Director之中,可以精细控制最终产品的生产过程,使用的时候是一步一步的得到最终产品。
最后,展示一下程序的最终运行结果:
图 4.2 两种兵种组合
总结:
所谓设计模式就是人们总结出来,可以在特定上下文环境下解决一些常见问题的最佳实践。六种构造模式的目的都是生产产品,就像无论在Terran还是Zerg,使用的是何种方法都是需要生产部队才能赢得比赛,但只有根据种族的特点,采取最佳的营运与配搭,才能获得快速的发展。使用模式也一样,在实际编写代码时,我们是为了解决上下文遇到的问题而去使用模式,而不要脱离上下文、脱离具体问题为了使用模式而使用模式。
我看来,打星际争霸学会几种开局不难,难的是应变。把每种模式的框架背下来写代码中套用上也不难,真正掌握了模式的标准应当是使用的时候能否做到“顺势而动、行云流水”。
从本章开始介绍的三种Factory模式以外的构造模式,也让Zerg的发展正式走进了我们的剧情之中,现在让我们一起看看Zerg中一些很神奇部队生产方式,去学习下一种构造模式。
- 大小: 11.5 KB
- 大小: 22.7 KB
分享到:
相关推荐
这个http://blog.csdn.net/dawanganban/article/details/9990405博客中java设计模式的源代码。下载前请先看《设计模式——建造者模式》一文。
设计模式之建造者模式代码示例,
设计模式实验报告-建造者,有代码实例和运行结果
java设计模式【之】建造者模式【源码】【场景:车辆组装】 将复杂的对象构建,与对象的使用进行分离 用户只需要通过简单流程即可创建出对象 方法调用顺序,步骤的不同实现 优点:封装性号,创建和使用分离,扩展性...
设计模式C++学习之建造者模式(Builder)
java23中常用设计模式之建造者模式,详细源码分析请见: http://blog.csdn.net/github_22022001/article/details/42120867
java23种设计模式 工厂模式 ,抽象工厂,建造者模式,单态模式,原型模式
设计模式专题之(四)建造者模式---设计模式建造者模式示例代码(python--c++)
C#设计模式之建造者模式应用实例
Java设计模式-建造者模式详解
设计模式之代理模式,请求的链式处理——职责链模式,请求发送者与接收者解耦——命令模式,自定义语言的实现——解释器模式,遍历聚合对象中的元素——迭代器模式,协调多个对象之间的交互——中介者模式,撤销功能...
用一个建造房屋的生动实例讲述了设计模式中常用的建造者模式的真谛,跟大家一起交流。附有相应类图
NULL 博文链接:https://wy649898543.iteye.com/blog/1431751
3. 建造者模式(Builder) 4. 工厂方法模式(Factory Method) 5. 原型模式(Prototype) 结构型: 6. 适配器模式(Adapter Pattern) 7. 桥接模式(Bridge Pattern) 8. 装饰模式(Decorator Pattern) 9. ...
设计模式例子,观察者模式,建造者模式,一些实践的例子,通俗易懂.
C#设计模式之建造者(Builder)模式示例源代码
本文实例讲述了Python设计模式之建造者模式。分享给大家供大家参考,具体如下: 建造者模式(Builder Pattern):将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示 下面是一个建造者模式的...
设计模式-建造者模式,该模式涉及产品,构造者,指挥者、调用者等几个角色,职责明确,在实际项目中使用得比较多。
c++实现建造者模式,可直接运行