Java教程

设计模式--工厂方法

本文主要是介绍设计模式--工厂方法,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

创建型–工厂方法(Factory Method)

框架

在介绍工厂方法之前,先来了解一下框架的具体知识。
框架就是能完成一定功能的半成品软件。所谓半成本的意思是还不能完全实现用户需要的功能,只实现了用户需要的一部分功能,还需要进一步加工,才能成为一个满足用户需要的、完整的软件。因此框架级的软件,主要客户是开发人员,而不是最终用户。
在这里插入图片描述
实际开发中,应用程序和框架的关系:
在这里插入图片描述
框架和设计模式的关系

  • 设计模式比框架更抽象。
    框架是已经实现出来的软件了,而设计模式的重心还在于解决问题的方案上,还停留在思想的层面,因此设计模式比框架更为抽象。

  • 设计模式是比框架更小的体系结构元素
    框架是已经实现出来的软件,并实现了一系列的功能,因此一个框架,通常会包含多个设计模式的应用。

  • 框架比设计模式更加特例化
    框架是要解决一个领域的某些问题,是具体的功能,不同领域实现出来的框架是不一样的。而设计模式在不同领域都可以应用。因此框架总是针对特定领域的,而设计模式更加注重从思想上、从方法上解决问题,更加通用化

工厂方法

定义一个用于创建对象的接口,让子类决定实例化哪一个类,工厂方法使一个类的实例化延迟到其子类。
工厂方法模式的解决思路:

采用无为而治的方式:定义一个方法来创建接口对象。事实上他自己是不知道如何创建这个接口对象的,所以就定义成抽象方法,自己实现不了,就让子类去实现,这样这个对象本身就可以只是面向接口编程,而无需关系到底如何创建接口对象了。

类图

在这里插入图片描述

实现

Product接口的定义:
在这里插入图片描述
Product的实现对象:
在这里插入图片描述
创建器的定义:
在这里插入图片描述
具体的创建器实现对象:
在这里插入图片描述

工厂方法模式讲解

功能

工厂方法的主要功能是让在父类不知道具体实现的情况下,完成自身的功能调用,而具体的实现延迟到子类来实现。
这样在设计的时候,不用去考虑具体的实现,需要某个对象,把它通过工厂方法返回就好了,在使用这些对象实现功能的时候还是通过接口来操作

实现成抽象类

工厂方法的实现中,通常父类会是一个抽象类,里面包含创建所需对象的抽象方法,这些抽象方法就是工厂方法。
子类在实现这些抽象方法的时候,通常并不是真的由子类来实现具体的功能,而是在子类的方法里面做选择,选择具体的产品实现对象。
父类里面,通常会有使用这些产品对象来实现一定的功能的方法,而且这些方法所实现的功能通常都是公共的功能,不管子类选择了何种具体的产品实现,这些方法的功能总是能正确执行。

实现成具体的类

也可以把父类实现成为一个具体的类,这种情况下,通常是在父类中提供获取所需对象的默认实现方法,这样就算没有具体的子类,也能运行。
通常这种情况还是需要具体的子类来决定具体要如何创建父类所需要的对象。这种情况称为工厂方法为子类提供了挂钩,通过工厂方法,可以让子类对象来覆盖父类的实现,从而提供了更好的灵活性。

工厂方法的参数和返回

工厂方法的实现中,可能需要参数,以便决定到底选用哪一种具体的实现。也就是说通常在抽象方法里面传递参数,在子类实现的时候根据参数进行选择,看看究竟应该创建哪一个具体的实现对象
一般工厂方法返回的是被创建对象的接口对象,当然也可以是抽象类或者一个具体的类的实例。

谁来使用工厂方法创建的对象

在工厂方法模式里面,应该是创建器中的其他方法在使用工厂方法创建的对象,虽然也可以把工厂方法创建的对象直接提供给创建器 外部使用,但工厂方法模式的本意,是由创建器对象内部的方法来使用工厂方法创建的对象,也就是说,工厂方法一般不提供给创建器外部使用
客户端应该是使用创建器对象,或者是使用由创建器创建出来的对象。对于客户端使用创建器对象,这个时候工厂方法创建的对象,是创建器中的某些方法使用。对于使用那些由创建器创建出来的对象,是构成客户端需要的对象的一部分。
小结:
在工厂方法模式里面,客户端要么使用创建器对象,要么使用创建器创建的对象,一般客户端不直接使用工厂方法。当然也可以直接把工厂方法暴露给客户端操作,但是一般不这么做。

工厂方法模式的调用顺序示意图

(1)客户端使用由创建器创建出来的对象情况的调用示意图:
在这里插入图片描述

(2)客户端使用创建器对象时候的调用顺序示意图:
在这里插入图片描述

工厂方法模式与IOC/DI

IOC:控制反转
DI:依赖注入

1. IOC/DI的参与者都有谁?
一般有三方参与者,一个是某个对象;一个是IOC/DI容器;另一个是某个对象的外部资源
某个对象指的是任意的、普通的Java对象;IOC/DI容器简单点说就是指用来实现IOC/DI功能的一个框架程序;对象的外部资源指的是对象需要的,但是是从对象外部获取的,都统称为资源,比如:对象需要的其他对象、或者是对象需要的文件资源等。
2. 依赖注入中是是谁依赖谁?
某个对象依赖于IoC/DI容器。
3. 为什么需要依赖?
对象需要IOC/DI的容器来提供对象需要的外部资源。
4. 依赖注入中谁注入谁?
IOC/DI的容器注入某个对象。
5. 到底注入什么?
就是注入某个对象所需要的外部资源。
6. 控制反转中谁控制谁?
IOC/DI的容器来控制对象。
7. 控制什么?
IOC/DI的容器来控制对象。
8. 为何叫反转?
如果要在A里面使用C,如果是反向的话,就是A类不再主动去获取C,而是被动等待,等待IOC/DI的容器获取一个C的实例,然后反向的注入到A类中。
正向的示意图:
在这里插入图片描述
反向的示意图:
在这里插入图片描述
依赖注入和控制反转是同一个概念吗?
依赖注入和控制反转是对同一事件的不同描述。依赖注入是在应用程序的角度在描述,应用程序依赖容器创建并注入它所需要的外部资源;而控制反转是从容器的角度在描述,容器控制应用程序,由容器反向的向应用程序注入应用程序所需要的外部资源
小结:
原本的思想是应用程序要获取什么资源都是主动出击,但是在IOC/DI思想中,应用程序就变成被动的了,被动的等待IOC/DI容器来创建并注入它所需要的资源。
这样有效的分离了对象和它所需要的外部资源,使得他们松耦合,有利于功能复用,更重要的是使得应用程序的整个体系结构变得非常的灵活。

工厂方法的优缺点

  • 可以在不知具体实现的情况下编程
    工厂方法模式可以让你在实现功能的时候,如果需要某个产品的对象,只需要使用产品的接口即可,而无需关心具体的实现,选择具体实现的任务延迟到子类去完成
    更容易扩展对象的版本
    工厂方法给子类提供了一个挂钩,使得扩展新的对象版本变得非常容易。只需要新加入一个子类来提供新的工厂方法实现,然后在客户端使用这个新的子类即可。
  • 连接平行的类层次
    工厂方法除了创建产品对象外,在连接平行的类层次上也是大显身手。
  • 具体产品对象和工厂方法的耦合性
    在工厂方法模式里面,工厂方法是需要创建产品对象的,也就是需要选择具体的产品对象,并创建他们的实例,因此具体产品对象和工厂方法是耦合的。

工厂方法的进一步思考

1. 工厂方法模式的本质
延迟到子类来实现。工厂方法本身并不会去实现产品接口,具体的产品实现是已经写好的了,工厂方法只是去选择实现就好了。
与简单工厂非常类似,具体实现上都是在选择实现,但是也有不同点,简单工厂是直接在工厂类里面选择实现;而工厂方法会把这个工作延迟到子类来实现。工厂类里面使用工厂方法的地方是依赖于抽象而不是具体实现,从而使得系统更加灵活,具有更好的可维护性和可扩展性。
如果把工厂方法模式中的创建器退化一下,只提供工厂方法,并且这些工厂方法还都提供默认的实现,就会变成简单工厂模式。可认为简单工厂是工厂方法的一种特例,本质是相同的。
2. 设计原则的体现
该模式很好的体现了依赖倒置原则
该原则告诉我们依赖抽象,不要依赖具体类,就是不能让高层组件依赖于底层组件,而且不管高层组件还是底层组件,都应该依赖抽象
倒置就是这个接口的所有权,接口定义的功能都是高层组件需要的功能,但是高层组件只提出要求,并不关心具体实现,而底层组件,就是真正实现高层组件所以去哦去的接口功能的。所以,底层实现的接口的所有权并不在底层组件手中,而是倒置到高层组件中去了
3. 何时使用工厂方法模式

  • 如果一个类需要创建某个接口的对象,但是又不知道具体的实现,可以选用工厂方法模式,把创建对象的工作延迟到了子类去实现。
  • 如果一个类本身就希望,由他的子类来创建所需要的对象的时候,应该使用工厂方法模式。

感谢并参考:
https://www.jianshu.com/p/f1960652b64b

这篇关于设计模式--工厂方法的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!