目录

一、定义

二、通用类图与通用源码

三、工厂方法模式的应用

四、工厂方法模式的扩展

五、总结


一、定义

工厂方法模式使用的频率非常高,在我们日常的开发中总能见到它的身影。其定义为:

定义一个创建对象的抽象方法/接口,让子类决定实例化哪一个类,工厂方法使一个类的实例化延迟到其子类。

二、通用类图与通用源码

工厂方法模式主要有四个要素:

  • 抽象工厂类:抽象工厂类是工厂方法模式的核心,与调用者直接交互用来提供产品,可以是接口,也可以是抽象类;
  • 具体工厂实现:工厂实现是具体的实例化对象的类,如果需要扩展新的产品种类,就增加多一个工厂的实现即可;
  • 抽象产品类:产品接口的主要目的是定义产品的规范,所有的产品实现都必须遵循产品接口定义的规范。产品接口是调用者最为关心的,产品接口定义的优劣直接决定了调用者代码的稳定性。同样,产品接口也可以用抽象类来代替,但要注意最好不要违反里氏替换原则;
  • 具体产品类:实现产品接口的具体类,决定了产品在客户端中的具体行为;

在工厂方法模式中,抽象产品类AbstractProduct负责定义产品的共性,实现对事物最抽象的定义 ;AbstractCreatorFactory是抽象工厂,具体如何创建产品类是由具体的实现工厂ConcreteCreatorFactory来完成的。下面我们一起看一个比较实用的通用源码。

抽象产品类AbstractProduct :

public abstract class AbstractProduct {public void get() {System.out.println("抽象产品类的公共方法");}//抽象方法public abstract void execute();
}

具体的产品类可以有多个,都继承于抽象产品类。

public class ConcreteProduct01 extends AbstractProduct {@Overridepublic void execute() {System.out.println("ConcreteProduct01#execute()");}
}public class ConcreteProduct02 extends AbstractProduct {@Overridepublic void execute() {System.out.println("ConcreteProduct02#execute()");}
}

抽象工厂类负责定义产品对象的产生,其代码如下:

/*** 抽象工厂类*/
public abstract class AbstractCreatorFactory {/*** 创建一个产品对象** @param tClass* @param <T>* @return*/public abstract <T extends AbstractProduct> T createProduct(Class<T> tClass);}

具体如何产生一个对象,是由具体的工厂实现类来完成的,其代码如下:

/*** 具体工厂类*/
public class ConcreteCreatorFactory extends AbstractCreatorFactory {@Overridepublic <T extends AbstractProduct> T createProduct(Class<T> tClass) {AbstractProduct product = null;try {product = (AbstractProduct) Class.forName(tClass.getName()).newInstance();} catch (Exception e) {e.printStackTrace();}return (T) product;}
}

客户端调用类:

public class Client {public static void main(String[] args) {AbstractCreatorFactory creatorFactory = new ConcreteCreatorFactory();ConcreteProduct01 product = creatorFactory.createProduct(ConcreteProduct01.class);product.execute();System.out.println("========================");ConcreteProduct02 product2 = creatorFactory.createProduct(ConcreteProduct02.class);product2.execute();}
}

该通用代码是一个比较实用的、易扩展的框架,读者可以根据实际项目的需要进行扩展。

三、工厂方法模式的应用

下面我们模拟工厂生成鼠标的过程,来说明工厂方法模式在项目中是如何应用的。

相关类图如下:

相关代码实现如下:

抽象产品类:

/*** 抽象产品类:鼠标*/
public abstract class Mouse {public abstract void click();
}

具体产品类:

/*** 具体产品类:戴尔鼠标*/
public class DellMouse extends Mouse {@Overridepublic void click() {System.out.println("戴尔鼠标点击...");}
}

抽象工厂类:

/*** 抽象工厂类:鼠标工厂*/
public abstract class AbstractMouseFactory {/*** 创建鼠标的方法*/public abstract Mouse createMouse();
}

具体工厂类:

/*** 具体工厂类:戴尔鼠标具体工厂*/
public class DellMouseFactory extends AbstractMouseFactory {@Overridepublic Mouse createMouse() {//创建一个戴尔鼠标return new DellMouse();}
}

场景类:

/*** 场景类*/
public class Client {public static void main(String[] args) {AbstractMouseFactory mouseFactory = new DellMouseFactory();Mouse mouse = mouseFactory.createMouse();mouse.click();}
}

运行结果:

戴尔鼠标点击...

上述的代码实现比较简单,当然扩展性也很强,假设我们需要新增一个生产惠普鼠标的功能,那么此时我们只需要新建一个惠普鼠标的具体产品类、新建一个生产惠普鼠标的具体工厂类就可以完成这些变更,实现代码如下:

/*** 具体产品类:惠普鼠标*/
public class HpMouse extends Mouse {@Overridepublic void click() {System.out.println("惠普鼠标点击...");}
}
/*** 具体工厂类:惠普鼠标具体工厂*/
public class HpMouseFactory extends AbstractMouseFactory {@Overridepublic Mouse createMouse() {//创建一个惠普鼠标return new HpMouse();}
}

扩展后的相关类图如下:

此时,场景类需要生产惠普鼠标的时候直接调用上述工厂类即可,可以看到工厂方法模式的扩展性还是很友好的。

四、工厂方法模式的扩展

工厂方法模式有很多扩展,而且与其他模式结合使用威力更大,下面将介绍几种扩展。

(一)、缩小为简单工厂模式

我们考虑这样一个问题:一个模块仅需要一个工厂类,没有必要把它产生出来,使用静态的方法就可以了,根据这一要求,我们把上面的例子稍微修改一下,类图如下:

可以看到,我们去掉了AbstractMouseFactory抽象类,同时把创建鼠标的方法设置为静态类型,简化了类的创建过程。

简单工厂类:

/*** 简单工厂类*/
public class MouseFactory {public static <T extends Mouse> T createMouse(Class<T> tClass) {Mouse mouse = null;try {mouse = (Mouse) Class.forName(tClass.getName()).newInstance();} catch (Exception e) {e.printStackTrace();}return (T) mouse;}}

抽象产品类、具体产品类:

/*** 抽象产品类:鼠标*/
public abstract class Mouse {public abstract void click();
}/*** 具体产品类:戴尔鼠标*/
public class DellMouse extends Mouse {@Overridepublic void click() {System.out.println("戴尔鼠标点击...");}
}/*** 具体产品类:惠普鼠标*/
public class HpMouse extends Mouse {@Overridepublic void click() {System.out.println("惠普鼠标点击...");}
}

场景类:

/*** 场景类*/
public class Client {public static void main(String[] args) {DellMouse dellMouse = MouseFactory.createMouse(DellMouse.class);dellMouse.click();System.out.println("=================");HpMouse hpMouse = MouseFactory.createMouse(HpMouse.class);hpMouse.click();}
}

运行结果没有发生变化,但是我们的类图变简单了,而且调用者也比较简单,该模式是工厂方法模式的弱化,因为简单,所以叫简单工厂模式,也叫作静态工厂模式。在实际项目中,采用这种方式的案例还是比较多的,其缺点是工厂类的扩展比较困难,不符合开闭原则,但它仍然是一个非常实用的设计模式。

(二)、替换单例模式

单例模式的核心要求就是在内存中只有一个对象,通过工厂方法模式也可以只在内存中生产一个对象。下面我们看一下怎么实现:

public class Singleton {private Singleton() {}public void doSomething() {}}
public class SingletonFactory {private static Singleton singleton;static {try {Class clazz = Class.forName(Singleton.class.getName());//获取无参构造方法Constructor constructor = clazz.getDeclaredConstructor();//设置无参构造方法是可以访问的constructor.setAccessible(true);singleton = (Singleton) constructor.newInstance();} catch (Exception e) {e.printStackTrace();}}public static Singleton getSingleton() {return singleton;}}

通过获得类的构造器,然后设置访问权限,生成一个对象,然后提供外部访问,保证内存中的对象唯一。以上通过工厂方法模式创建了一个单例模式,该框架可以继续扩展,在一个项目中可以产生一个单例构造器,所以需要产生单例的类都遵循一定的规则,然后通过扩展该框架,只要输入一个类型就可以获取唯一的一个实例。

五、总结

工厂方法模式的优点:

1、良好的封装性,代码结构清晰。如一个调用者需要一个具体的产品对象,只要知道产品类的类名、或约束字符串就可以了,不用知道创建对象的过程,降低模块间的耦合;

2、工厂方法模式的扩展性十分优秀,在增加产品类的情况下,只需要适当地修噶爱啊具体的工厂类或扩展一个工厂类,就可以完成变更。

3、屏蔽产品类。产品类的实现如何变化,调用者都不需要关心,它只关心产品的接口,只要接口保持不变,系统中的上层模块就不用发生变化。

4、工厂方法模式是典型的解耦框架。高层模块只需要知道产品的抽象类,其他的实现类都不用关系,符合迪米特法则,我不需要就不要去交流;也符合依赖倒置原则,只依赖产品类的抽象;当然也符合里氏替换原则,使用产品类的子类去替换父类,没问题。

工厂方法模式的缺点:

如果产品的生产过程并不复杂,假如直接通过new Object()就能实例化对象的,那么就无须使用工厂方法,反而让系统多了一些工厂方法接口和实现,不方便管理,可维护性差。

设计模式 ( 三 ) 工厂方法模式相关推荐

  1. 设计模式三(工厂方法模式)学习笔记

    1.创建抽象类 public abstract class Connect{public abstract void ConnectString();} 2.继承抽象类的实体类 public clas ...

  2. C#设计模式(3)——工厂方法模式

    一.引言 在简单工厂模式中讲到简单工厂模式的缺点,有一点是--简单工厂模式系统难以扩展,一旦添加新产品就不得不修改简单工厂方法,这样就会造成简单工厂的实现逻辑过于复杂,然而本专题介绍的工厂方法模式可以 ...

  3. 设计模式之工厂方法模式(创建型)

    一.模式定义 工厂方法模式:又称工厂模式,也叫虚拟构造器模式,属于构建型设计模式,工厂方法模式是在简单工厂模式上进行拓展,生产产品的过程由具体工厂类实现,基类只实现接口,这使得工厂方法模式可以在不修改 ...

  4. 设计模式:工厂方法模式(Factory method)

    设计模式:工厂方法模式(Factory method) 一.问题 在前一章中通过披萨的实例介绍了简单工厂模式.在披萨实例中,如果我想根据地域的不同生产出不同口味的披萨,如纽约口味披萨,芝加哥口味披萨. ...

  5. python类是实例的工厂_Python设计模式之工厂方法模式实例详解

    本文实例讲述了Python设计模式之工厂方法模式.分享给大家供大家参考,具体如下: 工厂方法模式(Factory Method Pattern):定义一个用于创建对象的接口,让子类决定实例化哪一个类, ...

  6. 设计模式复习-工厂方法模式

     设计模式复习-工厂方法模式 相对于简单工厂,工厂方法是把算法类的实例化延迟到了调用者那去做,调用者根据自己的需要,自己实例化相关的工厂并且生产相关算法.这么做是因为简单工厂是不满足OCP的,因为如果 ...

  7. 设计模式之工厂方法模式应用例题

    设计模式之工厂方法模式应用例题 题目描述 类结构图及相关说明 程序代码 运行结果 题目描述 现需要设计一个程序来读取多种不同类型的图片格式,针对每一种图片格式都设计一个图片读取器(ImageReade ...

  8. 【设计模式】工厂方法模式(C#)

    [设计模式]工厂方法模式 1.概述 针对简单工厂中的缺点,使用工厂方法模式就可以完美的解决,完全遵循开闭原则. 定义一个用于创建对象的接口,让子类决定实例化哪个产品类对象.工厂方法使一个产品类的实例化 ...

  9. 一文叫你弄懂Java设计模式之工厂方法模式:图解+日志记录器代码实例

    文章目录 详解Java设计模式之工厂方法模式 案例引入工厂方法模式 工厂方法模式 定义 案例分析 UML类图分析 代码分析 工厂方法的重载 工厂方法的隐藏 模式优点 模式缺点 模式适用环境 详解Jav ...

  10. 设计模式之工厂方法模式、抽象工厂模式的概念和实现及使用“反射技术+读取配置文件”的方法对工厂模式进行改进(软件工程综合实践课程第三周个人作业)

    文章目录 一.实验目的 二.知识总结 1.工厂方法模式简介 2.抽象工厂模式简介 3.工厂模式小结 4.利用"反射技术+读取配置文件"的方法改进程序 三.实验内容 1. 工厂模式实 ...

最新文章

  1. 自动驾驶开发云平台业务分析
  2. 【目标检测】(6) YOLOV2 目标检测在V1基础上的改进
  3. J2SE理解之一:声明和访问控制
  4. c语言多个子函数声明,C函数在多个源文件中的声明和定义
  5. Mars 是什么、能做什么、如何做的——记 Mars 在 PyCon China 2018 上的分享
  6. php选择排序从大到小,PHP选择排序
  7. java.lang.NullPointerException org.apache.jsp.index_jsp._jspInit(index_jsp.java:22)
  8. 计算机网络工程教程:基于cisco路由器和交换机,网络工程实践教程:基于Cisco路由器与交换机...
  9. 如何使用码云Gitee上传本地项目
  10. 求职之测试开发技能准备
  11. kettle spoon 连接mysql数据库
  12. 二值化网络的发展——从原始BNN到MeliusNet
  13. 各种翻车问题——最长公共前缀
  14. 5G通讯的认知与见解
  15. 基于HTML+CSS+JavaScript技术设计的博客网站(web前端期末大作业)
  16. 计算机网络:TCP实现聊天功能
  17. docker java 内存_Java和Docker限制的那些事儿
  18. 利用OpenCV计算图像的垂直和水平积分投影
  19. 批量文档处理软件推荐,同时处理 Word、Excel、PPT、PDF 等办公文件,支持批量格式转换、重命名和查找替换等
  20. 计算机科学与技术考研双非院校排名,ESI工科高校新排名:两所双非院校跻身世界500强...

热门文章

  1. 图像特征的匹配-OpenCV3.0
  2. 价值连城 知名深度强化学习Pieter Abbeel的采访 给机器学习 深度学习 和机器人学研究者从业者的建议
  3. 算法: 239. 滑动窗口的最大值
  4. 算法:Search in Rotated Sorted Array(搜索部分顺序被翻转的数组)
  5. c语言在线读程序,用C语言编写简单程序.doc
  6. 181.超过经理收入的员工
  7. (机器学习)痛苦的Caffe配置之路(win10 教育版+vs2015+cmaker+cpu_only+python接口)
  8. erlang web服务器性能,100万并发连接服务器笔记之Erlang完成1M并发连接目标
  9. Raki的nlp-begginer 提问
  10. 51.N皇后 (力扣leetcode) 博主可答疑该问题