抽象工厂模式是工厂方法模式的进一步抽象
在工厂模式中,客户端程序依赖(消费)一种抽象产品角色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();
}
}
测试代码
能够看得出来,下图的形式中
只须要修改一行代码,就能够作到整个产品族的切换
使用场景
抽象工厂模式,是工厂模式的进一步抽象,能够建立多个层级结构的产品
抽象工厂模式是将工厂模式拓展到他的产品族中,再也不是仅仅建立同一个产品,而是建立一个“族”
当系统中有多于一个的产品族,并且,系统在某刻只是消费其中某个产品族
也就是同属于同一个产品族中的产品 会在一块儿工做使用
这种场景下,比较适合抽象工厂模式
好比上面的例子,KFC和MCDonalds都有鸡腿和汉堡,你去了KFC点餐那就是KFC的鸡腿和汉堡
在KFC的“工厂”中,你调用鸡腿和汉堡方法,得到鸡腿和汉堡
若是你想要KFC的鸡腿和MCDonalds的汉堡的话
你或许就是以下这种形式
Factory factory1 = new KFC();
KFC.鸡腿;
Factory factory2 = new MCDonalds();
MCDonalds.汉堡;
若是是上面这种形式,须要两个工厂,这样也是能够的
可是你应该避免胡乱随便的产品等级结构混杂在一块儿使用抽象工厂模式
之因此是建立了一个产品族,而不是任意八竿子打不着的产品中 , 是由于:
若是产品等级结构变得更多,彻底没有产品族的概念,好比水果、蔬菜、主板、显示器
他们没有产品族的概念,也更不会一块儿使用,每种产品等级结构都下属不少类型
若是你像刚才那样KFC的鸡腿和MCDonalds的汉堡 混搭的话
可能使用时,要建立多个工厂实例,每一个工厂到底生产什么怕是本身都要混乱了,由于他们不是产品族,不成体系
还不如针对于每种产品等级结构一个单独的工厂模式更加条理清晰,混搭彻底不符合单一职责原则
简单想下两种场景就能够理解,好比海尔生产 冰箱洗衣机电视机微波炉等等
这些产品是同一个产品族,都是海尔XXX
哪怕有美的XX 西门子XX你都不会凌乱
可是若是A厂生产 苹果 土豆 A主板 A显示器 A显卡
另外一个B厂生产橘子 白菜 B主板 B显示器 B显卡
另外一个C厂生产水蜜桃 茄子 C主板 C显示器 C显卡
当你须要苹果白菜茄子A主板B显示器C显卡时会不会凌乱?
因此说,想要使用抽象工厂模式,必定要理清楚产品的层级结构体系以及产品族的概念
若是根本没有产品族的概念,那么不适合使用抽象工厂模式,你或许应该考虑多个不一样的工厂方法模式
总结
与工厂方法模式 最直白的差别就在于:
抽象工厂方法能够建立整个产品族,而工厂方法仅仅只能建立一种等级结构的产品
当你须要使用建立型模式的时候,若是你须要选择工厂模式
那么你应该最早考虑简单工厂模式的形式,尽管他简单到都不算是一种模式
若是简单工厂模式不能胜任,产品等级结构过于复杂或者业务逻辑复杂,能够考虑使用工厂方法模式
当产品等级结构不少,势必会出现过多的工厂方法模式,也就是过多的工厂
那么,若是这些产品中,可以组合成产品族的概念
则能够应用抽象工厂模式
换句话说,当你须要建立不一样的等级产品结构时,能够考虑抽象工厂模式
从这一点看,抽象工厂模式不就是工厂模式的进一步延伸扩展嘛
抽象工厂的核心就在于抽象工厂角色,建立了全部类型的抽象产品
抽象工厂角色建立的就是一族的抽象产品角色,就是每种抽象产品角色建立一个
有多少个产品等级结构,他就有几个方法建立对应的产品
因此必然,全部的实现类,都可以建立全部的产品类型,也就是建立的功能拓展到了产品族
前面的结构图中,没有画红色的两条,画上可能更好理解
抽象工厂模式,与产品族的概念息息相关,必需要理解产品族的概念
产品族的概念并非严格的必须是同一品牌或者同一厂家这般强关联
可是他们必须是有所关联,也就是有共同的约束,好比在同一个操做系统上使用
只有你找到了某种关联约束,能够组织成产品族,也就是前文中的产品族的产品会一块儿工做
那么才可使用抽象工厂,必定不要毫无关联并且也不是一块儿使用的产品等级结构放置在一块儿
还要确保产品等级结构不会轻易发生变化,不然,时常变更那么就意味着相关的工厂角色都须要频繁的修改
是不能忍受的
若是结构图中,去掉ProductB,这看起来是否是就是工厂模式?
因此说相对于工厂模式,抽象工厂模式最直观的变化就是,将工厂的能力范围扩展到了产品族上
一个工厂能够建立同一个产品族的多种产品
扩展产品族
若是增长新的产品族时,也就是层级结构不变,可是每种产品结构下面具体产品变多了
好比Fruit下面多了一个Banana香蕉 Vegetable 下面多了个 Carrot 胡萝卜
这就须要增长一个具体的工厂,用于生产制造Banana 和 Carrot
对于其余的代码,则不须要任何修改,知足开闭原则的要求
扩展产品等级结构
若是增长新的产品等级,好比Fruit Vegetable 又增长了一个肉类Meat 有羊肉牛肉等
怎么办?
那么,咱们须要从抽象工厂角色Creator就开始增长一个方法用于建立肉类 Meat createMeat();
最顶级的抽象角色新增了方法,也就意味着全部的具体工厂,这些实现类,都须要随之变更
扩展等级结构,显然是致命的!彻底不符合开闭原则,这是他的一大缺点
看得出来,抽象工厂模式在扩展方面向产品族的扩展倾斜,给产品族的扩展提供了方便
可是在扩展产品等级结构时,却没法提供便利,因此适用于产品等级结构不太会变更的场景