此篇博客参考书籍《研磨设计模式》,书的封面太丑了,用言叶之庭当封面吧,相比GoF的设计模式,此书更加通俗易懂,适合作为设计模式的入门书籍。
场景问题
在Java应用开发中,我们应该遵守“面向接口编程”的原则,而接口的思想浓缩成一句话就是“封装隔离”,此处的封装指的是“对被隔离体的行为的封装”,而隔离指的是外部的调用和内部实现,外部的调用只能通过接口来进行调用,而不知道内部的具体实现。(书上的原话,基本是照抄的,吼吼吼)
在刚学JavaSE的时候,有时会遇到如下类型的代码:
1 | // 定义一个接口 |
在客户端中有这样一句代码
1 | Api api = new Impl() |
你会发现客户端在调用时,它不但知道了接口,同时还知道了具体的实现是Impl,然而接口的思想是隔离封装,客户端不应该知道实现类是Impl,但是如果将new Impl()
去掉,Api的接口对象又无法获得。
如果将这个问题描述一下就是:在Java编程中,需要只知接口不知实现的情况,该怎么办?(为什么有这样的需要/滑稽)
解决方案
定义
用来解决上述问题的一个合理解决方案就是简单工厂,关于简单工厂的定义是这样的:提供一个创建对象实例的功能,而无需关心其具体实现。被创建实例的类型可以是接口,抽象类,也可以是具体的类
解决问题的思路
虽然不能让模块外部知道模块内部的具体实现,但是模块内部是可以知道的,那么干脆在模块内部新建一个类,在这个类里面来创建接口,然后把创建好的接口返回给客户端。
使用简单工厂重写示例
下面我们用简单工厂的模式重写实现一下刚才的代码
1 | // 定义一个接口 |
模式讲解
认识简单工厂设计模式
简单工厂的功能就是创建对象,我们在使用简单工厂的时候,通常不用创建简单工厂类的实例,而是将创建对象的方法变为静态方法,所以简单工厂又可以称为静态工厂。如果想要防止客户端无谓的创造简单工厂实例。我们还可以将构造方法私有化。
虽然从理论上讲,简单工厂可以创建任何对象,但我们再使用时,尽量将创建的范围独立成一个组建或者模块级别,否则这个工厂类会显得职责不明,有点大杂烩的感觉。
简单工厂的优点和不足
优点
帮助封装,去除了客户端与具体实现类的依赖,封装了对象的创建过程。
不足
工厂类中包含了多个实例创建的逻辑,一旦工厂出现问题,会影响到所有实例的创建。
如果想要添加一个新的实例让简单工厂来创建,就必须去修改简单工厂的创建方法,不太符合”开放-关闭”(对扩展开放,对修改关闭)原则。
增强扩展性
利用反射技术可以增强简单工厂的扩展性
1 | // 定义一个接口 |
简单工厂在JDK中的应用
在JDK中最典型的简单工厂的应用就是JDBC
将关系型数据库认为是抽象产品,将MySQL,Oracle认为是具体产品,
DriverManager是工厂类
应用程序通过JDBC接口使用关系型数据库,不需关心使用哪种数据库
直接使用DriverManager的静态方法去得到该数据库的Connection即可
1 | package com.brave.simplefactory.jdk; |