抽象工厂模式 创建型 设计模式(四)
抽象工厂模式是工厂方法模式的进一步抽象
在工厂模式中,客户端程序依赖(消费)一种抽象产品角色Product
所有的ConcreteCreator的返回类型都是Product,因为抽象工厂角色Creator就是返回Product
但是,如果一个系统需要依赖多个不同的抽象产品角色怎么办?
也就是需要Product1 Product2 ... 他们是不同的抽象角色,工厂模式就歇菜了,简单工厂模式也只是一种类型
此时,就需要抽象工厂模式,抽象工厂模式可以创建多种类型的产品
简言之,工厂模式只能生产一种产品,比如青岛啤酒厂生产各式样的啤酒,他不可能生产大米
抽象工厂角色就可以生产啤酒和大米
我们举例说明
比如实际项目中,DAO(数据库访问层)都有CRUD 操作(增查改删)
但是有不同的数据库,假设使用MYSQL和ORACLE两种数据库
那么对于CRUD操作都有两种类型 MYSQL和ORACLE
产品的等级结构如下图所示
CRUD操作四个操作对应四个等级产品(简单理解就是四种类型产品)
四个等级中的MYSQL 就组成了一个产品族
四个等级中的ORACLE 也组成了一个产品族
再比如 快餐店经常都有销售鸡腿和汉堡(两种产品)
但是有不同的快餐店,比如KFC和Mcdonalds
产品的等级结构如下图
鸡腿和汉堡对应两个产品等级体系结构
两个等级结构中的KFC组成了一个产品族
两个等级结构中的Mcdonalds组成了一个产品族
再比如,计算机中有文字处理软件和图像处理软件
但是计算机有不同的操作系统平台,比如Windows和Linux
有文字处理和图像处理两种产品等级结构
两个等级结构中的windows平台下软件组成了一个产品族
两个等级结构中的Linux平台下软件组成了一个产品族
所以说,不同类型的产品,就是不同的等级结构
水果是一个等级,蔬菜是一个等级,PC是一个等级
不同等级结构中,相关联的一组功能就是一个产品族
相关联的含义是有一些公共的限制约束或者特性
水果是一个等级,蔬菜是一个等级
热带水果和热带蔬菜,产地都是南方属于热带地区 , 这就是一个产品族
主板是一个等级,有多种厂家生产,比如华硕 戴尔
显示器是一个等级,有多种厂家生产,比如华硕 戴尔
主板和显式器可以组成电脑的一部分
华硕主板和华硕显示器都是华硕品牌的,是一个产品族
简单理解就是:每个类型来一个,就构成了一个产品族
想要使用工厂模式,首先就是要理清楚产品的等级结构
简单工厂和工厂方法模式都只能创建一种等级结构的产品
如果想要创建多个等级结构的产品,你可以借助于多个工厂方法模式
另外,如果有产品族的概念,你可以考虑抽象工厂模式
需要特别关注是否有关联和共同约束限制条件,也就是是否能够成为产品族
产品族与产品等级
想要理解抽象工厂的本质,需要先介绍两个概念 产品族和产品等级结构产品等级结构指的是产品的分类划分结构 功能相关联的不同产品(位于不同的等级结构)就组成了一个产品族 |
一个产品族中,有多少个产品,跟产品等级结构的个数是一致的 也就是说有多少种产品,一个产品族就有多少个 有CRUD四个产品等级,一个mysql产品族就有四个产品 有鸡腿汉堡两个产品等级,KFC产品族就有两种产品 |
产品族就是一个产品类别中拿出来一个 所以就是一个类型有多少种,就是有多少个产品族 |
意图
提供一个创建一系列相关或者相互依赖对象的接口,而无需指定他们具体的类。 其实就是工厂方法模式中一个方法,创建一个类型,此处多个方法,创建多个类型,简单理解就是这样结构
说完了产品等级结构和产品族的概念 我们看下抽象工厂模式的结构产品等级结构product ProductA和ProductB 他们分别有对应的两种类型的产品 ConcreteProductA1 和 ConcreteProductA2 ConcreteProductB1 和 ConcreteProductB2 |
抽象工厂角色Creator Creator可以创建ProductA和ProductB两种抽象类型 他有两个实现类工厂ConcreteCreator1和 ConcreteCreator2 |
具体的工厂ConcreteCreator 每一个ConcreteCreator都可以生产一个产品族的产品 也就是ConcreteCreator1可以生产ConcreteProductA1 和 ConcreteProductB1 |
角色介绍
抽象工厂角色(Abstract Factory) 工厂方法的核心,与系统具体逻辑无关,通常是java接口或者抽象类 所有的具体的工厂都需要实现它,也就是上图中的Creator 具体工厂角色(Concrete Factory) 直接接受客户端程序请求,创建产品的实例,它可以创建一个产品族的实例对象 抽象产品角色(Abstract Product) 为一类产品对象声明一个抽象表示 具体产品角色(Concrete Product) 定义一个被创建的具体的对象的类型,实现Abstract Product接口 类似工厂模式,具体的工厂角色可以有多个,分别对应不同的产品族 有几个产品族就会有几个具体的工厂示例代码
有两个产品等级结构 Fruit和Vegetable 也就是有水果和蔬菜两种商品 假设有两个商店,他们都提供水果和蔬菜 第一个商店提供的水果和蔬菜是苹果和土豆 第二个商店提供的水果和蔬菜是橘子和白菜 也就是苹果Apple和土豆Potato是一个产品族,由一个店铺在卖 橘子Orange和大白菜Cabbage是一个产品族,由一个店铺在卖 产品类Fruit以及Apple和Orange与工厂模式中示例代码一样 Vegetable表示蔬菜的抽象角色 Potato和Cabbage为具体的蔬菜 有抽象工厂角色Factory 以及具体的工厂ConcreteFactory1 和 ConcreteFactory2 Fruit产品结构体系package abstractFactory; /** * Created by noteless on 2018/10/9. * Description: */ public interface Fruit { String description(); }
package abstractFactory; /** * Created by noteless on 2018/10/9. * Description: */ public class Apple implements Fruit { @Override public String description() { return "apple"; } }
package abstractFactory; /** * Created by noteless on 2018/10/9. * Description: */ public class Orange implements Fruit { @Override public String description() { return "Orange"; } }蔬菜产品结构体系
package abstractFactory; /** * Created by noteless on 2018/10/10. * Description: */ public interface Vegetable { String description(); }
package abstractFactory; /** * Created by noteless on 2018/10/10. * Description: */ public class Potato implements Vegetable { @Override public String description() { return "potato"; } }
package abstractFactory; /** * Created by noteless on 2018/10/10. * Description: */ public class Cabbage implements Vegetable { @Override public String description() { return "cabbage"; } }工厂体系
package abstractFactory; /** * Created by noteless on 2018/10/9. * Description: */ public interface Factory { Fruit createFruit(); Vegetable createVegetable(); }
package abstractFactory; /** * Created by noteless on 2018/10/10. * Description: */ public class ConcreateFactory1 implements Factory { @Override public Fruit createFruit() { return new Apple(); } @Override public Vegetable createVegetable() { return new Potato(); } }
package abstractFactory; /** * Created by noteless on 2018/10/10. * Description: */ public class ConcreateFactory2 implements Factory { @Override public Fruit createFruit() { return new Orange(); } @Override public Vegetable createVegetable() { return new Cabbage(); } }测试代码 可以看得出来,下图的形式中 只需要修改一行代码,就可以做到整个产品族的切换