【却说那七衣仙女自受了大圣的定身法术,一周天方能解脱,各提花篮,回奏王母说道:“齐天大圣使术法困住我等,故此来迟。”王母问道:“汝等摘了多少蟠桃?”仙女道:“只有两篮小桃,三篮中桃。至后面,大桃半个也无,想都是大圣偷吃了。及正寻间,不期大圣走将出来,行凶拷打,又问设宴请谁。我等把上会事说了一遍,他就定住我等,不知去向。直到如今,才得醒解回来。”王母闻言,即去见玉帝,备陈前事。】

在《西游记》第五回《乱蟠桃大圣偷丹 反天宫诸神捉怪》里,悟空将奉王母之命前去蟠桃园摘桃的七衣仙女定住,随即自己偷吃仙桃的事情也因而败露了。

悟空模式-java-普通工厂模式中,我们举了王母娘娘(消费者)从蟠桃园(普通工厂类)中获取蟠桃(产品)的例子来说明普通方法模式,我们发现蟠桃园这个类是普通方法模式的核心类,一旦出现问题,整个设计体系就崩溃了。果不其然,齐天大圣很快就捣乱了,当他把七衣仙女定住的时候,蟠桃园就停止工作,王母娘娘就没有办法获取到蟠桃了,直到过了一周天,蟠桃园恢复运行,王母才拿到几篮桃子。

那么接下来我们就尝试使用工厂方法模式来降低蟠桃系统的风险,主要的改动就是将原本作为核心的蟠桃园类修改为以抽象蟠桃园作为核心,蟠桃的产出交由各个具体的蟠桃园负责,这样某一个蟠桃园出现问题,不影响其他蟠桃园的正常运行:

蟠桃

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.factory.method;

public abstract class FlatPeachGarden {
public abstract FlatPeach produce();
}

低级蟠桃园

package com.tirion.design.factory.method;

public class LowLevelFlatPeachGarden extends FlatPeachGarden {

    @Override
public FlatPeach produce() {
return new LowLevelFlatPeach();
}
}

中级蟠桃园

package com.tirion.design.factory.method;

public class MiddleLevelFlatPeachGarden extends FlatPeachGarden {

    @Override
public FlatPeach produce() {
return new MiddleLevelFlatPeach();
}
}

高级蟠桃园

package com.tirion.design.factory.method;

public class HighLevelFlatPeachGarden extends FlatPeachGarden {

    @Override
public FlatPeach produce() {
return new HighLevelFlatPeach();
}
}

王母娘娘

package com.tirion.design.factory.method;

public class TheQueenMother {

    public static FlatPeach getLowLevelFlatPeach() {
FlatPeachGarden garden = new LowLevelFlatPeachGarden();
FlatPeach flatPeach = garden.produce();
if (flatPeach == null) {
System.out.println("王母娘娘没有得到蟠桃");
} else {
System.out.println("王母娘娘获得了蟠桃");
}
return flatPeach;
} public static FlatPeach getMiddleLevelFlatPeach() {
FlatPeachGarden garden = new MiddleLevelFlatPeachGarden();
FlatPeach flatPeach = garden.produce();
if (flatPeach == null) {
System.out.println("王母娘娘没有得到蟠桃");
} else {
System.out.println("王母娘娘获得了蟠桃");
}
return flatPeach;
} public static FlatPeach getHighLevelFlatPeach() {
FlatPeachGarden garden = new HighLevelFlatPeachGarden();
FlatPeach flatPeach = garden.produce();
if (flatPeach == null) {
System.out.println("王母娘娘没有得到蟠桃");
} else {
System.out.println("王母娘娘获得了蟠桃");
}
return flatPeach;
} public static void main(String[] args) {
TheQueenMother.getLowLevelFlatPeach();
TheQueenMother.getMiddleLevelFlatPeach();
TheQueenMother.getHighLevelFlatPeach();
}
}

在上面的代码中,我们将三种蟠桃分别交给三个不同类别的蟠桃园进行管理,每个蟠桃园负责生产某一种类的蟠桃,这样就把不同蟠桃的管理拆分开来,不再集中于一个蟠桃园,降低了系统的耦合风险。代码执行结果如下:

找到对应等级的蟠桃园
三千年一熟
低级蟠桃
王母娘娘获得了蟠桃
找到对应等级的蟠桃园
六千年一熟
中级蟠桃
王母娘娘获得了蟠桃
找到对应等级的蟠桃园
九千年一熟
高级蟠桃
王母娘娘获得了蟠桃

王母娘娘想要哪个种类的蟠桃,就派仙女去对应的蟠桃园去采摘,这就是工厂方法模式的运作方式,上例的类图如下:

现在我们将工厂方法模式与普通方法模式进行比较,看看工厂方法模式在面对一些问题时会有什么样的表现:

现在蟠桃园出现了同样的情况,悟空把高级蟠桃园里的桃子全部偷吃光了,又把中间蟠桃园的仙女用定身法术定住了,我们如何处理这样的变化呢?方法如下:

修改高级蟠桃园类和中级蟠桃园类

package com.tirion.design.factory.method;

public class HighLevelFlatPeachGarden extends FlatPeachGarden {

    @Override
public FlatPeach produce() {
System.out.println("高级蟠桃被齐天大圣偷吃光了!");
return null;
// return new HighLevelFlatPeach();
}
}
package com.tirion.design.factory.method;

public class MiddleLevelFlatPeachGarden extends FlatPeachGarden {

    @Override
public FlatPeach produce() {
System.out.println("齐天大圣把中级蟠桃园的仙女定住了,没办法取蟠桃!");
return null;
// return new MiddleLevelFlatPeach();
}
}

其他类不变,再来看代码的允许结果:

找到对应等级的蟠桃园
三千年一熟
低级蟠桃
王母娘娘获得了蟠桃
找到对应等级的蟠桃园
齐天大圣把中级蟠桃园的仙女定住了,没办法取蟠桃!
王母娘娘没有得到蟠桃
找到对应等级的蟠桃园
高级蟠桃被齐天大圣偷吃光了!
王母娘娘没有得到蟠桃

也就是说,哪个具体的工厂类出现了变化,我们就修改对应的工厂类就可以了,这样代码修改不会影响其他没有发生变化的业务代码逻辑,符合“单一职责原则”。产品的选择方案与工厂本身分离开来,工厂只要负责创建产品实例就可以了。

我们再来看另外一种情况,高级蟠桃被悟空吃掉了之后,也许是被齐天大圣的灵气所激发,部分果核后来居然生长出了一种新的蟠桃树,一万年一熟,我们叫它超高级蟠桃。下面我们将对工厂方法模式的蟠桃园体系进行调整,以适应蟠桃品种的变化:

超高级蟠桃

package com.tirion.design.factory.method;

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.factory.method;

public class SuperHighLevelFlatPeachGarden extends FlatPeachGarden {

    @Override
public FlatPeach produce() {
return new SuperHighLevelFlatPeach();
}
}

这样,我们就把这种新的蟠桃品种加入进来了。王母娘娘暂时还不知道有了新的蟠桃,哪天她知道了,就派人去超高级蟠桃园去采摘就可以了。

从上面可以看出,增加一个新的蟠桃品种只需要增加一个新的产品类(超高级蟠桃)和一个新的产品工厂(超高级蟠桃园),而不必更改原有体系中任何一个类的代码,这样就符合了“开闭原则”。

所以说,工厂方法模式是普通工厂模式为了适应更多的未来变化而衍生出来的更高级的工厂模式,它解决了一些普通工厂模式违背的设计原则问题,即单一职责原则开闭原则

但是,工厂方法模式也有它的缺陷,那就是随着产品越来越多,每个产品都需要新建一个产品类和对应的工厂类,这样最终会导致类非常多。消费者也很难管理这些类。以上面的例子来说,就是最终蟠桃园里有好几十种蟠桃,王母娘娘也搞不清楚到底要哪些蟠桃,派仙女去哪些蟠桃园去采摘,最终引发体系混乱,代码修改难度加大,风险也随之上升。

为了解决这个问题,我们引入了悟空模式-java-抽象工厂模式,关于工厂方法模式的介绍就到这里,你可以将它记忆为多蟠桃园模式

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

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

悟空模式-java-工厂方法模式的更多相关文章

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

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

  2. Java设计模式学习记录-简单工厂模式、工厂方法模式

    前言 之前介绍了设计模式的原则和分类等概述.今天开启设计模式的学习,首先要介绍的就是工厂模式,在介绍工厂模式前会先介绍一下简单工厂模式,这样由浅入深来介绍. 简单工厂模式 做法:创建一个工厂(方法或类 ...

  3. JAVA设计模式(01):创建型-工厂模式【工厂方法模式】(Factory Method)

    简单工厂模式尽管简单,但存在一个非常严重的问题.当系统中须要引入新产品时,因为静态工厂方法通过所传入參数的不同来创建不同的产品,这必然要改动工厂类的源码,将违背"开闭原则".怎样实 ...

  4. 设计模式(三)——Java工厂方法模式

    工厂方法模式 1 看一个新的需求 披萨项目新的需求:客户在点披萨时,可以点不同口味的披萨,比如 北京的奶酪 pizza.北京的胡椒 pizza 或者是伦敦的奶酪 pizza.伦敦的胡椒 pizza. ...

  5. Java工厂方法模式

    工厂方法模式: /** * 工厂方法模式:也叫工厂模式,属于创建型模式,父类工厂(接口)负责定义产品对象的公共接口, * 而子类工厂负责创建具体的产品对象. * 目的:是为了把产品的实例化操作延迟到子 ...

  6. 设计模式---对象创建模式之工厂方法模式(Factory Method)

    前提:“对象创建”模式 通过“对象创建”模式绕开new,来避免对象创建(new)过程中所导致的紧耦合(依赖具体类),从而支持对象创建的稳定.它是接口抽象之后的第一步工作. 典型模式(表现最为突出) 工 ...

  7. PHP简单工厂模式、工厂方法模式和抽象工厂模式比较

    PHP工厂模式概念:工厂模式是一种类,它具有为您创建对象的某些方法.您可以使用工厂类创建对象,而不直接使用 new.这样,如果您想要更改所创建的对象类型,只需更改该工厂即可.使用该工厂的所有代码会自动 ...

  8. PHP简单工厂模式、工厂方法模式和抽象工厂模式

    PHP工厂模式概念:工厂模式是一种类,它具有为您创建对象的某些方法.您可以使用工厂类创建对象,而不直接使用 new.这样,如果您想要更改所创建的对象类型,只需更改该工厂即可.使用该工厂的所有代码会自动 ...

  9. iOS常用设计模式——工厂方法(简单工厂模式,工厂方法模式, 抽象工厂模式)

    1. 简单工厂模式 如何理解简单工厂,工厂方法, 抽象工厂三种设计模式? 简单工厂方法包含:父类拥有共同基础接口,具体子类实现子类特殊功能,工厂类根据参数区分创建不同子类实例.该场景对应的UML图如下 ...

  10. iOS经常使用设计模式——工厂方法(简单工厂模式,工厂方法模式, 抽象工厂模式)

    1. 简单工厂模式 怎样理解简单工厂,工厂方法. 抽象工厂三种设计模式? 简单工厂的生活场景.卖早点的小摊贩.他给你提供包子,馒头,地沟油烙的煎饼等,小贩是一个工厂.它生产包子,馒头,地沟油烙的煎饼. ...

随机推荐

  1. jQuery基础笔记(5)

    day56 参考:https://www.cnblogs.com/liwenzhou/p/8178806.html#autoid-1-9-5 文档处理 添加到指定元素内部的后面 $(A).append ...

  2. matplotlib实现三维柱状图

    matplotlib实现三维柱状图 import cv2 img = cv2.imread("1.png", 0) #特征点在图片中的坐标位置 m = 448 n = 392 im ...

  3. FunDA(8)- Static Source:保证资源使用安全 - Resource Safety

    我们在前面用了许多章节来讨论如何把数据从后台数据库中搬到内存,然后进行逐行操作运算.我们选定的解决方案是把后台数据转换成内存中的数据流.无论在打开数据库表或从数据库读取数据等环节都涉及到对数据库表这项 ...

  4. 日志分析与splunk浅谈

    难易程度:★★★ 阅读点:linux;python;web安全;日志分析; 文章作者:xiaoye 文章来源:i春秋 关键字:网络渗透技术 前言 linux下的日志分析对企业来说非常重要,对我们分析p ...

  5. SecureCRT连接Ubuntu,centos失败解决

    SecureCRT连接Ubuntu,centos失败,长时间的重新连接,连接不了. Ubuntu,centos默认未安装ssh远程加密连接服务.使用命令,安装即可. 1.sudo apt-get in ...

  6. 消息队列 MQ 入门理解

    功能特性: 应用场景: 消息队列 MQ 可应用于如下几个场景: 分布式事务 在传统的事务处理中,多个系统之间的交互耦合到一个事务中,响应时间长,影响系统可用性.引入分布式事务消息,交易系统和消息队列之 ...

  7. OpenCV --- 修改图像的对比度、亮度 、RGB转Gray图像、修改图像的尺寸

    #include <opencv2/core.hpp> #include <opencv2/imgcodecs.hpp> #include <opencv2/highgu ...

  8. (转)AIX的Dump文件学习笔记

    原文:http://czmmiao.iteye.com/blog/1144999 DUMP文件概述 为了增强故障分析能力,IBM的服务器增加了对设备故障当前环境的保存功能,就是保存一份设备故障时的内存 ...

  9. 11 - JavaSE之GUI

    GUI(念法 gu yi) AWT AWT(Abstract Window Toolkit 抽象窗口开发包,在C# 或者 linux窗口开发类之上又封装一层,达到跨平台的目的)包括了很多类和接口,用于 ...

  10. docker 使用swarm overlay网络时,报“network xx not manually attachable”错误解决

    当使用swarm的overlay网络,在该网络中运行容器时报“network xx not manually attachable”的错误 docker network create -d overl ...