【大圣看玩多时,问土地道:“此树有多少株数?”土地道:“有三千六百株。前面一千二百株,花微果小,三千年一熟,人吃了成仙了道,体健身轻。中间一千二百株,层花甘实,六千年一熟,人吃了霞举飞升,长生不老。后面一千二百株,紫纹缃核,九千年一熟,人吃了与天地齐寿,日月同庚。”大圣闻言,欢喜无任,当日查明了株树,点看了亭阁回府。自此后,三五日一次赏玩,也不交友,也不他游。】

在《西游记》第五回《乱蟠桃大圣偷丹 反天宫诸神捉怪》里有上面这一段关于蟠桃园里不同种类蟠桃树的描述,那么这里就用蟠桃园为例来描述一下普通工厂模式的运作方式:

蟠桃

package com.tirion.design.simple.factory;

public interface FlatPeach {

    void printLevel();

    void printCycleTime();
}

低级蟠桃

package com.tirion.design.simple.factory;

public class LowLevelFlatPeach implements FlatPeach {

    LowLevelFlatPeach(){
printCycleTime();
printLevel();
} @Override
public void printLevel() {
System.out.println("低级蟠桃");
} @Override
public void printCycleTime() {
System.out.println("三千年一熟");
} }

中级蟠桃

package com.tirion.design.simple.factory;

public class MiddleLevelFlatPeach implements FlatPeach {

    MiddleLevelFlatPeach(){
printCycleTime();
printLevel();
} @Override
public void printLevel() {
System.out.println("中级蟠桃");
} @Override
public void printCycleTime() {
System.out.println("六千年一熟");
} }

高级蟠桃

package com.tirion.design.simple.factory;

public class HighLevelFlatPeach implements FlatPeach {

    HighLevelFlatPeach(){
printCycleTime();
printLevel();
} @Override
public void printLevel() {
System.out.println("高级蟠桃");
} @Override
public void printCycleTime() {
System.out.println("九千年一熟");
} }

蟠桃园

package com.tirion.design.simple.factory;

public class FlatPeachGarden {
public static FlatPeach produce(String level) {
System.out.println("生长出...");
if ("low".equals(level)) {
return new LowLevelFlatPeach();
} else if ("middle".equals(level)) {
return new MiddleLevelFlatPeach();
} else if ("high".equals(level)) {
return new HighLevelFlatPeach();
} else {
System.out.println("没有对应等级的蟠桃");
return null;
}
}
}

王母娘娘

package com.tirion.design.simple.factory;

public class TheQueenMother {

    public static void getFlatPeach(String level) {
FlatPeach flatPeach = FlatPeachGarden.produce(level);
if (flatPeach == null) {
System.out.println("王母娘娘没有得到蟠桃");
} else {
System.out.println("王母娘娘获得了蟠桃");
}
} public static void main(String[] args) {
TheQueenMother.getFlatPeach("low");
TheQueenMother.getFlatPeach("middle");
TheQueenMother.getFlatPeach("high");
TheQueenMother.getFlatPeach("super high");
}
}

这里的蟠桃园就是一个蟠桃工厂,在这个工厂里有三种产品:三千年一熟的低级蟠桃、六千年一熟的中级蟠桃以及九千年一熟的高级蟠桃,王母娘娘需要蟠桃的时候,就可以通过调用蟠桃园的produce方法,传入她所需要的蟠桃等级,就可以获得对应等级的蟠桃。

下面是上述代码的执行结果:

生长出...
三千年一熟
低级蟠桃
王母娘娘获得了蟠桃
生长出...
六千年一熟
中级蟠桃
王母娘娘获得了蟠桃
生长出...
九千年一熟
高级蟠桃
王母娘娘获得了蟠桃
生长出...
没有对应等级的蟠桃
王母娘娘没有得到蟠桃

这个示例的类图如下:

从上图可以看出,蟠桃真正的消费者王母娘娘The Queen Mother,并不需要接触到具体的蟠桃FlatPeach。当王母娘娘需要蟠桃的时候,她只需要调用工厂类蟠桃园FlatPeachGarden的produce方法,告知它自己需要的蟠桃等级level,就可以获取到对应的蟠桃了,如果她给了蟠桃园错误的指令,则不会获取到蟠桃。

所以,普通工厂模式的优点在于,产品的消费者并不需要知道产品生产的细节,消费者只需要调用工厂类创建产品的方法就可以了,产品创建的具体逻辑交给了工厂类来独立处理,这就实现了责任的分离,消费者负责获取产品,工厂类负责创建产品。

接着我们再看一下普通工厂模式的扩展性如何:

假设现在出现了一个突发情况,蟠桃园的九千年高级蟠桃被孙悟空全部偷吃掉了,蟠桃园工厂目前提供不了九千年高级蟠桃了,我们如何在程序中体现这个逻辑的改动呢?非常简单,只需要修改蟠桃园类的生产逻辑就可以了。

package com.tirion.design.simple.factory;

public class FlatPeachGarden {
public static FlatPeach produce(String level) {
System.out.println("生长出...");
if ("low".equals(level)) {
return new LowLevelFlatPeach();
} else if ("middle".equals(level)) {
return new MiddleLevelFlatPeach();
} else if ("high".equals(level)) {
System.out.println("高级蟠桃被孙悟空偷吃完了");
return null;
// return new HighLevelFlatPeach();
} else {
System.out.println("没有对应等级的蟠桃");
return null;
}
}
}

其他部分代码不需要改变,程序的执行结果如下:

生长出...
三千年一熟
低级蟠桃
王母娘娘获得了蟠桃
生长出...
六千年一熟
中级蟠桃
王母娘娘获得了蟠桃
生长出...
高级蟠桃被孙悟空偷吃完了
王母娘娘没有得到蟠桃
生长出...
没有对应等级的蟠桃
王母娘娘没有得到蟠桃

也就是说,对于产品生产逻辑的变更,我们只需要修改普通工厂模式的核心逻辑类——工厂类就可以了。

我们现在再假设另外一种情况,蟠桃园经过神仙们多年的精心培育,出现了新的品种——超高级蟠桃SuperHighLevelFlatPeach,我们如何改变现有代码,去体现这个变更呢?也非常方便,只需要在FlatPeach体系下增加这个新的蟠桃,然后再修改一下蟠桃园类生产对应蟠桃的逻辑就可以了:

package com.tirion.design.simple.factory;

public class SuperHighLevelFlatPeach implements FlatPeach {

    SuperHighLevelFlatPeach(){
printCycleTime();
printLevel();
} @Override
public void printLevel() {
System.out.println("超高级蟠桃");
} @Override
public void printCycleTime() {
System.out.println("一万年一熟");
} }
package com.tirion.design.simple.factory;

public class FlatPeachGarden {
public static FlatPeach produce(String level) {
System.out.println("生长出...");
if ("low".equals(level)) {
return new LowLevelFlatPeach();
} else if ("middle".equals(level)) {
return new MiddleLevelFlatPeach();
} else if ("high".equals(level)) {
return new HighLevelFlatPeach();
} else if ("super high".equals(level)) {
return new SuperHighLevelFlatPeach();
} else {
System.out.println("没有对应等级的蟠桃");
return null;
}
}
}

变更后代码的执行结果如下:

生长出...
三千年一熟
低级蟠桃
王母娘娘获得了蟠桃
生长出...
六千年一熟
中级蟠桃
王母娘娘获得了蟠桃
生长出...
九千年一熟
高级蟠桃
王母娘娘获得了蟠桃
生长出...
一万年一熟
超高级蟠桃
王母娘娘获得了蟠桃

可以看到,一万年一熟的超高级蟠桃比较容易地融入了原有的代码结构。但是这里违反了开闭原则,每次对蟠桃种类进行扩展都需要修改蟠桃园类,这一点很不方便。

以上的这些扩展均不用修改消费者的代码,说明这些代码的扩展对消费者来说是透明的,这一点在很多设计模式中都非常重要。

普通工厂模式的缺点也很明显,如果蟠桃园里的蟠桃种类非常多且经常调整的话,我们就要经常去修改蟠桃园生产蟠桃的方法,而且这个方法本身会非常复杂,效率也会非常低下。而且如果哪一天,孙悟空将这个蟠桃园捣毁了,工厂类无法继续正常运作,那么整个体系就完全瘫痪了,这一点非常不安全。同时它违反了单一职责原则,蟠桃园既要负责管理生产蟠桃的逻辑判断,又要负责蟠桃实例的创建。

为了解决这些问题,我们将会引入相对更加高级的工厂模式,请继续阅读悟空模式-java-工厂方法模式,这里对普通方法模式的介绍就到这里,你可以将它记忆为蟠桃园模式。

如果你认为文章中哪里有错误或者不足的地方,欢迎在评论区指出,也希望这篇文章对你学习java设计模式能够有所帮助。转载请注明,谢谢。

更多设计模式的介绍请到悟空模式-java设计模式中查看。

悟空模式-java-普通工厂模式的更多相关文章

  1. 悟空模式-java-抽象工厂模式

    [一朝,王母娘娘设宴,大开宝阁,瑶池中做蟠桃胜会] 有一天,王母娘娘要在瑶池办party,就需要准备大量的食材.要知道,天上的神仙也分三六九等,九曜星.五方将.二十八宿.四大天王.十二元辰.五方五老. ...

  2. !!转!!java 简单工厂模式

    举两个例子以快速明白Java中的简单工厂模式: 女娲抟土造人话说:“天地开辟,未有人民,女娲抟土为人.”女娲需要用土造出一个个的人,但在女娲造出人之前,人的概念只存在于女娲的思想里面.女娲造人,这就是 ...

  3. 学习:java设计模式—工厂模式

    一.工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的. 工厂模式在<Java与模式>中分为三类: 1)简单工厂模式(Simple Facto ...

  4. Java设计模式---工厂模式(简单工厂、工厂方法、抽象工厂)

    工厂模式:主要用来实例化有共同接口的类,工厂模式可以动态决定应该实例化那一个类.工厂模式的形态工厂模式主要用一下几种形态:1:简单工厂(Simple Factory).2:工厂方法(Factory M ...

  5. Java设计模式之(工厂模式)--简单工厂模式--工厂方法模式--抽象工厂模式

    工厂模式: 工厂模式可以分为三类: 1)简单工厂模式(Simple Factory) 2)工厂方法模式(Factory Method) 3)抽象工厂模式(Abstract Factory) 简单工厂模 ...

  6. 一张图搞定Java设计模式——工厂模式! 就问你要不要学!

    小编今天分享的内容是Java设计模式之工厂模式. 收藏之前,务必点个赞,这对小编能否在头条继续给大家分享Java的知识很重要,谢谢!文末有投票,你想了解Java的哪一部分内容,请反馈给我. 获取学习资 ...

  7. java设计模式-工厂模式(springweb为例子)

    一般而言,工厂模式分为3种,简单工厂模式,工厂方法模式,抽象工厂模式.这三种工厂模式逐层深入吧. 一,从springWeb.jar包使用抽象工厂模式的一个例子聊起 之前对spring各种痴迷,所以在需 ...

  8. Java设计模式之【工厂模式】(简单工厂模式,工厂方法模式,抽象工厂模式)

    Java设计模式之[工厂模式](简单工厂模式,工厂方法模式,抽象工厂模式) 工厂模式出现的原因 在java中,创建一个对象最简单的方法就是使用new关键字.但在一些复杂的业务逻辑中,创建一个对象不只需 ...

  9. java设计模式—工厂模式

    一.工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的. 工厂模式在<Java与模式>中分为三类:1)简单工厂模式(Simple Factor ...

  10. Java抽象工厂模式

    Java抽象工厂模式 基本定义 抽象工厂模式是所有形态的工厂模式中最为抽象和最其一般性的.抽象工厂模式可以向客户端提供一个接口,使得客户端在不必指定产品的具体类型的情况下,能够创建多个产品族的产品对象 ...

随机推荐

  1. 实现一个算法,寻找字符串中出现次数最少的、并且首次出现位置最前的字符 如"cbaacfdeaebb",符合要求的是"f",因为他只出现了一次(次数最少)。并且比其他只出现一次的字符(如"d")首次出现的位置最靠前。

    实现一个算法,寻找字符串中出现次数最少的.并且首次出现位置最前的字符如"cbaacfdeaebb",符合要求的是"f",因为他只出现了一次(次数最少).并且比其 ...

  2. php批量导出pdf文件的脚本(html-PDf)

    背景:突然有大量的文件需要导出成PDF文件,写一个批量导出pdf的脚本,同时文件的命名也需要有一定的规则 导出方式:向服务器中上传csv文件,csv文件中包含文件的地址和相对应的文件命名. 如下格式: ...

  3. PHP之旅5 php的函数

    函数的结构 php的函数和其他语言的函数基本类似,和C语言比较的话主要区别在于php是一个弱语言,对类型不敏感,在函数的表现上就是,php函数没有类型定义,不像语言即使无参也要定义为void,而且不管 ...

  4. Jmeter服务器监控 serveragent如何使用

    安装jmeter插件Plugins Managerjmeter-plugins.org推出了全新的Plugins Manager,对于其提供的插件进行了集中的管理,我们只需要安装这个管理插件,即可以在 ...

  5. 自定义android ProgressDialog

    Android系统自己提供的UI的都是比较难看的,开发中经常用到自定义对话框,下面分享个最近项目中使用的加载框.   下面是源代码,主要的原理就是准备几个图片,然后循环播放. MainActivity ...

  6. day 35 dom 编程 补充

    前情提要: dom 编程 我记得写过dom 编程的记录..找了博客发现没有内容了.. 少侠重新来过吧

  7. while 语句

    /* while循环 格式:while(循环保持条件){需要执行的语句} OC: int i = 0; int sum = 0; while (i <= 10) { sum = i++; } w ...

  8. 8.在XamarinAndroid上进一步控制包的大小

    在Android上链接 Xamarin.Android应用程序使用链接器来减小应用程序的大小.链接器使用应用程序的静态分析来确定哪些程序集.类型.成员被实际使用.链接器的行为就像一个GC,不断寻找被引 ...

  9. 【Java并发编程】:内存可见性

    加锁(synchronized同步)的功能不仅仅局限于互斥行为,同时还存在另外一个重要的方面:内存可见性.我们不仅希望防止某个线程正在使用对象状态而另一个线程在同时修改该状态,而且还希望确保当一个线程 ...

  10. [转]ASP.NET MVC 4 最佳实践宝典

    原文:http://www.cnblogs.com/sonykings/archive/2013/05/30/3107531.html ASP.NET MVC最佳实践 本文档提供了一套旨在帮助创建最佳 ...