抽象工厂模式
1、什么是抽象工厂模式?
抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。在抽象工厂模式中,接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工厂模式提供对象。
2、抽象工厂模式特性?
(1)意图:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
(2)主要解决:主要解决接口选择的问题。
(3)何时使用:系统的产品有多于一个的产品族,而系统只消费其中某一族的产品。
(4)如何解决:在一个产品族里面,定义多个产品。
(5)关键代码:在一个工厂里聚合多个同类产品。
3、抽象工厂模式的优缺点及应用场景
(1)优点:
当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。
(2)缺点:
产品族扩展非常困难,要增加一个系列的某一产品,既要在抽象的 Creator 里加代码,又要在具体的里面加代码。
(3)使用场景:
1、QQ 换皮肤,一整套一起换。(其中,每种皮肤之中有多个区域皮肤,比如页头,标题栏)
2、生成不同操作系统的程序。(不同的操作系统里面包含多个部分,各个部分的实现可能不一样)
(4)注意事项:
产品族难扩展,产品等级易扩展。
(5)应用示例:
工作了,为了参加一些聚会,肯定有两套或多套衣服吧,比如说有商务装(成套,一系列具体产品)、时尚装(成套,一系列具体产品),甚至对于一个家庭来说,可能有商务女装、商务男装、时尚女装、时尚男装,这些也都是成套的,即一系列具体产品。假设一种情况,在您的家中,某一个衣柜(具体工厂)只能存放某一种这样的衣服(成套,一系列具体产品),每次拿这种成套的衣服时也自然要从这个衣柜中取出了。用 OOP 的思想去理解,所有的衣柜(具体工厂)都是衣柜类的(抽象工厂)某一个具体实现,而每一件成套的衣服又包括具体的上衣(某一具体产品),裤子(某一具体产品),这些具体的上衣其实也都是上衣(抽象产品),具体的裤子也都是裤子(另一个抽象产品)。
4、抽象工厂模式实现示例
(1)假设场景需求:现在要开发一个数据相关的接口,最简单的,我们需要考虑mysql、oracle等数据库,对于每种数据库,我们还需要考虑数据库连接、命令发送、获取结果.....等等内部相关内容。对于数据库内部的各种操作,我们可以认为它是一个产品,数据库是一种产品工厂,工厂内容有多个产品如数据库的各种操作,而对于数据库的各种操作即一种内部产品,每种数据库又有其自己的实现,因而内部产品也是一种接口,对于每个接口可以有不同的实现。
言归正传,假设只考虑连接和sql命令,我们可以抽象为:连接IConnection接口,命令ICommand接口,数据库工具接口IDatabaseUtils,并在数据库IDatabaseUtils接口中使用连接IConnection和命令ICommand接口方法,由此定义了接口规范。结合代码理解。
(2)示例代码如下:
业务规范接口定义:
//定义接口规范,多个接口
//连接接口
interface IConnection{
void connect();
}
//命令接口
interface ICommand{
void command();
}
//数据库接口,数据库接口可以获取连接对象和命令对象
interface IDatabaseUtils{
IConnection getConnection();
ICommand getCommand();
}
添加MySQL数据库支持实现:
//MySQL的支持
class MysqlConnection implements IConnection{
@Override
public void connect() {
System.out.println("mysql connected...");
}
}
class MysqlCommand implements ICommand{
@Override
public void command() {
System.out.println("mysql command...");
}
}
//mysql接口
class MysqlDataBaseUtils implements IDatabaseUtils{
@Override
public IConnection getConnection() {
return new MysqlConnection();
}
@Override
public ICommand getCommand() {
return new MysqlCommand();
}
}
添加Oracle数据支持实现:
//对Oracle的支持
class OracleConnection implements IConnection{
@Override
public void connect() {
System.out.println("oracle connect...");
}
}
class OracleCommand implements ICommand{
@Override
public void command() {
System.out.println("oracle command...");
}
}
class OracleDataBaseUtils implements IDatabaseUtils{
@Override
public IConnection getConnection() {
return new OracleConnection();
}
@Override
public ICommand getCommand() {
return new OracleCommand();
}
}
可以看出,添加一种数据库支持时,只需要添加对应的内部接口对象的接口实现和数据库接口实现即可。
使用测试示例:使用时,只需要调用具体的工厂实现即可,具体的工厂实现会创建对应的内部产品。
public class AbstractFactoryTest {
/**
* 场景:开发一个数据库接口,mysql,oracle....
* 连接connection,command...
*
*/
public static void main(String[] args) {
//业务流程
//下面在使用MySQL数据库时使用new MysqlDataBaseUtils()创建MySQL数据库对象,
//使用Oracle时,使用new OracleDataBaseUtils()创建Oracle数据库对象。对象之间是相互独立的。
IDatabaseUtils iDatabaseUtils = new OracleDataBaseUtils();
IConnection connection=iDatabaseUtils.getConnection();
connection.connect();
ICommand command = iDatabaseUtils.getCommand();
command.command();
}
}
示例接口如下:
oracle connect...
oracle command...
后续我们再需要添加其他数据库支持时,只需添加对应的接口实现,并在使用时指定具体的创建工厂(new XXX())即可。
总而言之,可以认为抽象工厂模式:有多个抽象产品类;一个实体工厂类可以生产多种产品类,客户可以从一个工厂获得所有想要的产品。
5、JDK中抽象工厂模式的典型应用示例
抽象工厂设计模式在JDK类的典型应用示例:
java.sql.Connection类
具体内容可查看JDK对应类源码。
本文源代码:https://github.com/JianfuYang/2020-yjf-review/tree/master/src/designpatterns/abstractfactory
声明:本文部分内容整理来源于网络,仅做个人学习使用!侵删~