工厂方法模式(Factory Method Pattern)理论篇
Posted 古月书斋
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了工厂方法模式(Factory Method Pattern)理论篇相关的知识,希望对你有一定的参考价值。
一、什么是工厂方法模式
工厂方法模式 属于类的创建型模式,它又被称为 多态工厂模式 ( Factory Method Pattern ) 。 工厂方法模式 的意义是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中。 核心工厂类 不再负责产品的创建,这样核心类成为一个抽象工厂角色,仅负责实现一些通用的方法和定义一些具体工厂子类必须实现的接口,这样进一步抽象化的好处是使得工厂方法模式可以使系统在不修改具体工厂角色的情况下引进新的产品。二 、模式结构和说明
工厂方法模式的结构如图3所示:![](https://image.cha138.com/20230125/d826dd0beaec48799b0f6983a681bfb6.jpg)
三、 工厂方法模式示例代码
(1) 先看看Product的定义,示例代码如下:/**
* 工厂方法所创建的对象的接口
*/
public interface Product
//可以定义Product的属性和方法
(2)
再看看具体的Product的实现对象,示例代码如下:
/**
* 具体的Product对象
*/
public class ConcreteProduct implements Product
//实现Product要求的方法
(3)接下来看看创建器的定义,示例代码如下:
/**
* 创建器,声明工厂方法
*/
public abstract class Creator
/**
* 创建Product的工厂方法
* @return Product对象
*/
protected abstract Product factoryMethod();
/**
* 示意方法,实现某些功能的方法
*/
public void someOperation()
//通常在这些方法实现中,需要调用工厂方法来获取Product对象
Product product = factoryMethod();
(4)
再看看具体的创建器实现对象,示例代码如下:
/**
* 具体的创建器实现对象
*/
public class ConcreteCreator extends Creator
protected Product factoryMethod()
//重定义工厂方法,返回一个具体的Product对象
return new ConcreteProduct();
四、 认识工厂方法模式
4.1、工厂方法模式的功能 工厂方法的主要功能是让父类在不知道具体实现的情况下,完成自身的功能调用,而具体的实现延迟到子类来实现。 这样在设计的时候,不用去考虑具体的实现,需要某个对象,把它通过工厂方法返回就好了,在使用这些对象实现功能的时候还是通过接口来操作,这非常类似于IoC/DI的思想,这个在后面给大家稍详细点介绍一下。 4.2、实现成抽象类 工厂方法的实现中,通常父类会是一个抽象类,里面包含创建所需对象的抽象方法,这些抽象方法就是工厂方法。 这里要注意一个问题,子类在实现这些抽象方法的时候,通常并不是真的由子类来实现具体的功能,而是在子类的方法里面做选择,选择具体的产品实现对象。 父类里面,通常会有使用这些产品对象来实现一定的功能的方法,而且这些方法所实现的功能通常都是公共的功能,不管子类选择了何种具体的产品实现,这些方法的功能总是能正确执行 。 4.3、实现成具体的类 当然也可以把父类实现成为一个具体的类,这种情况下,通常是在父类中提供获取所需对象的默认实现方法,这样就算没有具体的子类,也能够运行。 通常这种情况还是需要具体的子类来决定具体要如何创建父类所需要的对象。也把这种情况称为工厂方法为子类提供了挂钩,通过工厂方法,可以让子类对象来覆盖父类的实现,从而提供更好的灵活性。 4.4、工厂方法的参数和返回 工厂方法的实现中,可能需要参数,以便决定到底选用哪一种具体的实现。也就是说通过在抽象方法里面传递参数,在子类实现的时候根据参数进行选择,看看究竟应该创建哪一个具体的实现对象。 一般工厂方法返回的是被创建对象的接口对象,当然也可以是抽象类或者一个具体的类的实例。 4.5、谁来使用工厂方法创建的对象 这里首先要搞明白一件事情,就是谁在使用工厂方法创建的对象? 事实上,在工厂方法模式里面,应该是Creator中的其它方法在使用工厂方法创建的对象,虽然也可以把工厂方法创建的对象直接提供给Creator外部使用,但工厂方法模式的本意,是由Creator对象内部的方法来使用工厂方法创建的对象,也就是说,工厂方法一般不提供给Creator外部使用。 客户端应该是使用Creator对象,或者是使用由Creator创建出来的对象。对于客户端使用Creator对象,这个时候工厂方法创建的对象,是Creator中的某些方法使用。对于使用那些由Creator创建出来的对象,这个时候工厂方法创建的对象,是构成客户端需要的对象的一部分。分别举例来说明。 ①客户端使用Creator对象的情况 比如《 工厂方法模式(Factory Method Pattern) 应用篇(上) 》的示例,对于“实现导出数据的业务功能对象”的类ExportOperate,它有一个export的方法,在这个方法里面,需要使用具体的“导出的文件对象的接口对象” ExportFileApi,而ExportOperate是不知道具体的ExportFileApi实现的,那么怎么做的呢?就是定义了一个工厂方法,用来返回ExportFileApi的对象,然后export方法会使用这个工厂方法来获取它所需要的对象,然后执行功能。 这个时候的客户端是怎么做的呢?这个时候客户端主要就是使用这个ExportOperate的实例来完成它想要完成的功能,也就是客户端使用Creator对象的情况 简单描述这种情况下的代码结构如下:/**
* 客户端使用Creator对象的情况下,Creator的基本实现结构
*/
public abstract class Creator
/**
* 工厂方法,一般不对外
* @return 创建的产品对象
*/
protected abstract Product factoryMethod();
/**
* 提供给外部使用的方法,
* 客户端一般使用Creator提供的这些方法来完成所需要的功能
*/
public void someOperation()
//在这里使用工厂方法
Product p = factoryMethod();
②客户端使用由Creator创建出来的对象
另外一种是由Creator向客户端返回由“工厂方法创建的对象”来构建的对象,这个时候工厂方法创建的对象,是构成客户端需要的对象的一部分。简单描述这种情况下的代码结构如下:
/**
* 客户端使用Creator来创建客户端需要的对象的情况下,Creator的基本实现结构
*/
public abstract class Creator
/**
* 工厂方法,一般不对外,创建一个部件对象
* @return 创建的产品对象,一般是另一个产品对象的部件
*/
protected abstract Product1 factoryMethod1();
/**
* 工厂方法,一般不对外,创建一个部件对象
* @return 创建的产品对象,一般是另一个产品对象的部件
*/
protected abstract Product2 factoryMethod2();
/**
* 创建客户端需要的对象,客户端主要使用产品对象来完成所需要的功能
* @return 客户端需要的对象
*/
public Product createProduct()
//在这里使用工厂方法,得到客户端所需对象的部件对象
Product1 p1 = factoryMethod1();
Product2 p2 = factoryMethod2();
//工厂方法创建的对象是创建客户端对象所需要的
Product p = new ConcreteProduct();
p.setProduct1(p1);
p.setProduct2(p2);
return p;
在
工厂方法模式
里面,客户端要么使用
Creator对象
,要么使用
Creator创建的对象
,一般客户端不直接使用工厂方法。
当然也可以直接把工厂方法暴露给客户端操作,让客服端直接使用工厂方法,但是一般不这么做,关于此可参照《
工厂方法模式(Factory Method Pattern)应用篇(直接使用工厂方法)
》。
4.6、工厂方法模式的调用顺序示意图
由于客户端使用Creator对象有两种典型的情况,因此调用的顺序示意图也分做两种情况,
先来看客户端使用Creator对象时候的调用顺序示意图,如图5所示:
![](https://image.cha138.com/20230125/3c7de4166cb543f08f46df13c59f538d.jpg)
![](https://image.cha138.com/20230125/7c925701a49b4c2392c8ac063de865f3.jpg)
![](https://image.cha138.com/20230125/e48e7657ec834eb78f4c5aff4d5ce0b9.jpg)
以上是关于工厂方法模式(Factory Method Pattern)理论篇的主要内容,如果未能解决你的问题,请参考以下文章