💛原文地址為https://www.cnblogs.com/haixiang/p/12055272.html,轉載請注明出處!
簡介
工廠方法模式中考慮的是一類產品的生產,如畜牧場只養動物、電視機廠只生產電視機、計算機軟件學院只培養計算機軟件專業的學生等。
同種類稱為同等級,也就是說:工廠方法模式只考慮生產同等級的產品,但是在現實生活中許多工廠是綜合型的工廠,能生產多等級(種類) 的產品,如農場里既養動物又種植物,電器廠既生產電視機又生產洗衣機或空調,大學既有軟件專業又有生物專業等。
本節要介紹的抽象工廠模式將考慮多等級產品的生產,將同一個具體工廠所生產的位於不同等級的一組產品稱為一個產品族,
抽象工廠模式(Abstract Factory Pattern)是圍繞一個超級工廠創建其他工廠。該超級工廠又稱為其他工廠的工廠。這種類型的設計模式屬於創建型模式,它提供了一種創建對象的最佳方式。
在抽象工廠模式中,接口是負責創建一個相關對象的工廠,不需要顯式指定它們的類。每個生成的工廠都能按照工廠模式提供對象。
優缺點
-
產品易擴展(例如后面案例中擴展新的Mq、數據庫、緩存)
-
產品族擴展非常困難(例如后面案例中新增Server產品族),要增加一個系列的某一產品,既要在抽象工廠里加代碼,又要在具體的工廠類里面加代碼。
使用場景
- 當需要創建的對象是一系列相互關聯或相互依賴的產品族時,如電器工廠中的電視機、洗衣機、空調等。
- 系統中有多個產品族,但每次只使用其中的某一族產品。如有人只喜歡穿某一個品牌的衣服和鞋。
- 系統中提供了產品的類庫,且所有產品的接口相同,客戶端不依賴產品實例的創建細節和內部結構。
具體案例
一個完整成熟的系統可以采用不同的技術來解決業務層面的問題,例如數據庫可以用Mysql也可以用Oracle。本例中提供了三個產品,分別是消息隊列Mq、數據庫DataBase以及緩存Mycache三個接口,每個接口下都有自己的具體實現類,也就是工廠的產品。AbstractSystemFac作為抽象工廠類,調用了上述的三個接口,來組裝三個不同的產品。SimpleSystemFac與HugeSystemFac是兩個具體的工廠類,SimpleSystemFac是一個技術解決方案,選用MySQL數據庫、MemCache、RabbitMQ三種產品來實現自己的技術架構。而HugeSystemFac采用Oracle數據庫、Redis、Kafka三種產品,這兩個工廠類的方法一致,只不過具體調用的產品類型不同。

數據庫接口及實現類
/**
* 數據庫類型
* @author anqi
*/
public interface DataBase {
/** 初始化數據庫 */
void init();
}
public class Mysql implements DataBase {
@Override
public void init() {
System.out.println("MySQL初始化");
}
}
public class Oracle implements DataBase{
@Override
public void init() {
System.out.println("Oracle初始化");
}
}
public class OceanBase implements DataBase{
@Override
public void init() {
System.out.println("OceanBase初始化");
}
}
消息隊列接口及實現類
/**
* 消息隊列類型
* @author anqi
*/
public interface Mq {
/** 發送消息 */
void sendMessage();
}
public class RabbitMQ implements Mq {
@Override
public void sendMessage() {
System.out.println("使用RabbitMQ發送消息");
}
}
public class KafkaMQ implements Mq {
@Override
public void sendMessage() {
System.out.println("使用kafka發送消息");
}
}
緩存接口及實現類
/**
* 緩存類型
* @author anqi
*/
public interface MyCache{
/** 緩存數據 */
void cacheData();
}
public class MemCache implements MyCache {
@Override
public void cacheData() {
System.out.println("使用MemCache緩存");
}
}
public class RedisCache implements MyCache {
@Override
public void cacheData() {
System.out.println("使用redis緩存");
}
}
抽象工廠類
/**
* 抽象工廠類
*/
public abstract class AbstractSystemFac {
public abstract MyCache useCache();
public abstract Mq useMq();
public abstract DataBase useDataBase();
}
具體工廠
public class SimpleSystemFac extends AbstractSystemFac {
@Override
public MyCache useCache() {
return new MemCache();
}
@Override
public Mq useMq() {
return new RabbitMQ();
}
@Override
public DataBase useDataBase() {
return new Mysql();
}
}
具體工廠
public class HugeSystemFac extends AbstractSystemFac {
@Override
public MyCache useCache() {
return new RedisCache();
}
@Override
public Mq useMq() {
return new KafkaMQ();
}
@Override
public DataBase useDataBase() {
return new Oracle();
}
}
測試類
public class TestDemo {
public static void main(String[] args) {
AbstractSystemFac simpleFac = new SimpleSystemFac();
MyCache memcache = simpleFac.useCache();
DataBase mysql = simpleFac.useDataBase();
Mq rabbitmq = simpleFac.useMq();
memcache.cacheData();;
mysql.init();
rabbitmq.sendMessage();
AbstractSystemFac hugeFac = new HugeSystemFac();
MyCache redis = hugeFac.useCache();
DataBase oracle = hugeFac.useDataBase();
Mq kafka = hugeFac.useMq();
redis.cacheData();
oracle.init();
kafka.sendMessage();
}
}
使用MemCache緩存
MySQL初始化
使用RabbitMQ發送消息
使用redis緩存
Oracle初始化
使用kafka發送消息
我們可以靈活地擴充一個新的產品RocketMQ,或者一個新的工廠類NewSystemFac,如下圖所示

