以下内容來自http://www.lifevv.com/sysdesign/index.html
本文介紹設計模式中的抽象工廠(Abstract Factory)模式的概念,用法,以及實際應用中怎麼樣使用Factory Method模式進行開發。
Abstract Factory模式的概念
在大規模的系統開發過程中,考慮系統的靈活性,低耦合性,可擴充性等因素,常常不直接使用new來生成類的執行個體,而是通過一個叫做工廠(Factory)的類來專門生成類的執行個體。
我們在
設計模式之Factory Method - 工廠方法模式
一文中讨論了Factory Method模式,這裡再讨論一下一種更高層次的工廠模式:Abstract Factory模式。
Factory Method模式的主要特點是通過工廠提供的方法生成類的對象,而具體的對象的生成工作被委讓給(延遲到)子工廠,是以被稱為工廠方法模式。
Abstract Factory模式與Factory Method很相似,都是通過工廠的方法生成目标類的對象,但它們之間的也存在一些差別。
Abstract Factory模式與Factory Method模式的主要差別:
- Factory Method采用的是工廠類繼承機制(生成子工廠類,重載該工廠方法,在重載的方法中生成目标對象)。而Abstract Factory強調的是對象組合機制,由在父工廠内定義不同的“子工廠”對象來負責不同的目标對象的建立。再深入一點了解:
- Factory Method模式中,産品(目标對象)的使用者可能需要使用具體的子工廠來生成該産品;Abstract Factory模式則采用傳參數的形式直接在父工廠内決定該産品對象應該由哪一個子工廠生産。也就是說,Abstract Factory模式中,跟客戶打交道的隻有抽象工廠與抽象産品,客戶不需要知道産品由哪個工廠生産,也不需要知道被生産的是哪一種具體的産品。
- Factory Method模式中,省城的對象産品隻限定于某一類産品;Abstract Factory模式則可以提供多個生産接口生成多類産品
- Abstract Factory模式Factory Method模式的更高層次的抽象,也更最具一般性。可以把Factory Method模式看作是Abstract Factory模式的一種特殊情況
簡單一點說,Abstract Factory模式通過抽象工廠為客戶(調用者)生成多類産品,抽象工廠負責管理子工廠對象,子工廠負責生成某一類具體的産品對象。
Abstract Factory模式的應用場景:
- 存在多類産品,并需要對這些産品差別對待處理:需要分别為這些産品定義2個以上的接口或抽象類
- 用戶端隻需要與最上層的工廠(抽象工廠),與最上層的抽象産品打交道
Abstract Factory用到以下幾個概念:
- 抽象工廠類(1個):定義建立不同類執行個體的多個接口;建立與管理子工廠對象,提供統一方法以取得不同的子工廠對象
- 子工廠類(多個):生成具體的類的執行個體
- 抽象産品類(多個):對産品的抽象
- 具有繼承關系的具體的産品類(多個):繼承自抽象産品類,它們之間一般存在或多或少的依耐關系
工廠與産品的關系可以用UML類圖表示:
下面舉例說明。
Abstract Factory模式的實作範例
有一類Bus(公共汽車)系列産品Bus,ModelBus;
與另一類Truck(卡車)系列産品Truck,ModelTruck;
其中Bus與Truck可以由同一個工廠BusTruckFactory生産;ModelBus與ModelTruck可以由同一個工廠ModelFactory生産。
BusTruckFactory工廠與ModelFactory工廠由總工廠CarFactory統一管理。
我們(客戶)直接從CarFactory工廠定購Bus系列産品,與Truck(卡車)系列産品。
下面我們用Abstract Factory模式實作上面的過程
CarFactory:定義生産Bus和Truck的接口規範;管理BusTruckFactory與ModelFactory工廠。
BusTruckFactory:生産Bus和Truck的非模型車。
ModelFactory:生産Bus和Truck的模型車。
AbstractBus:公共汽車(包括模型與非模型車)父類
Bus:公共汽車。繼承自AbstractBus類。
ModelBus:公共汽車模型。繼承自AbstractBus類。
AbstractTruck:卡車(包括模型與非模型車)父類
Truck:卡車。繼承自AbstractTruck類。
ModelTruck:卡車模型。繼承自AbstractTruck類。
CarFactory.java
<script src="http://www.lifevv.com/images/code/js/shCore.js" type="text/javascript"></script> <script type="text/javascript"> </script> <script src="http://www.lifevv.com/images/code/js/shBrushJava.js" type="text/javascript"></script>
- public abstract class CarFactory {
- public static final int BUS_TRUCK = 1 ; //參數定義。生産非模型車。
- public static final int BUS_TRUCK_MODEL = 2 ; //參數定義。生産模型車。
- //定義生産公共汽車的接口
- public abstract AbstractBus createBus();
- //定義生産卡車的接口
- public abstract AbstractTruck createTruck();
- //管理子工廠類,根據參數調用不同的子工廠進行生産
- public static CarFactory getCarFactory( int carType) {
- switch (carType) {
- case BUS_TRUCK:
- return new BusTruckFactory();
- case BUS_TRUCK_MODEL:
- return new ModelFactory();
- default :
- return null ;
- }
- }
- }
public abstract class CarFactory {
public static final int BUS_TRUCK = 1; //參數定義。生産非模型車。
public static final int BUS_TRUCK_MODEL = 2; //參數定義。生産模型車。
//定義生産公共汽車的接口
public abstract AbstractBus createBus();
//定義生産卡車的接口
public abstract AbstractTruck createTruck();
//管理子工廠類,根據參數調用不同的子工廠進行生産
public static CarFactory getCarFactory(int carType) {
switch (carType) {
case BUS_TRUCK:
return new BusTruckFactory();
case BUS_TRUCK_MODEL:
return new ModelFactory();
default:
return null;
}
}
}
生産非模型車的工廠BusTruckFactory.java
- public class BusTruckFactory extends CarFactory {
- //生産公共汽車(非模型)
- public AbstractBus createBus() {
- return new Bus();
- }
- //生産卡車(非模型)
- public AbstractTruck createTruck() {
- return new Truck();
- }
- }
public class BusTruckFactory extends CarFactory {
//生産公共汽車(非模型)
public AbstractBus createBus() {
return new Bus();
}
//生産卡車(非模型)
public AbstractTruck createTruck() {
return new Truck();
}
}
生産模型車的工廠ModelFactory.java
- public class ModelFactory extends CarFactory {
- //生産公共汽車模型
- public AbstractBus createBus() {
- return new ModelBus();
- }
- //生産卡車模型
- public AbstractTruck createTruck() {
- return new ModelTruck();
- }
- }
public class ModelFactory extends CarFactory {
//生産公共汽車模型
public AbstractBus createBus() {
return new ModelBus();
}
//生産卡車模型
public AbstractTruck createTruck() {
return new ModelTruck();
}
}
産品類定義:
Bus系列産品:
- public class AbstractBus {
- public String getType() {
- return "Abstract Bus" ;
- }
- }
- public class Bus extends AbstractBus {
- public String getType() {
- return "Bus" ;
- }
- }
- public class ModelBus extends AbstractBus {
- public String getType() {
- return "ModelBus" ;
- }
- }
public class AbstractBus {
public String getType() {
return "Abstract Bus";
}
}
public class Bus extends AbstractBus {
public String getType() {
return "Bus";
}
}
public class ModelBus extends AbstractBus {
public String getType() {
return "ModelBus";
}
}
Truck系列産品:
- public class AbstractTruck {
- public String getType() {
- return "Abstract Truck" ;
- }
- }
- public class Truck extends AbstractTruck {
- public String getType() {
- return "Truck" ;
- }
- }
- public class ModelTruck extends AbstractTruck {
- public String getType() {
- return "ModelTruck" ;
- }
- }
public class AbstractTruck {
public String getType() {
return "Abstract Truck";
}
}
public class Truck extends AbstractTruck {
public String getType() {
return "Truck";
}
}
public class ModelTruck extends AbstractTruck {
public String getType() {
return "ModelTruck";
}
}
Client調用:
- public class Client {
- public static void main(String[] args) {
- //取得工廠對象
- CarFactory factory = CarFactory.getCarFactory(CarFactory.BUS_TRUCK);
- //生産公共汽車
- Bus bus = factory.createBus();
- System.out.println("生産了:" + bus.getType());
- //生産卡車
- Truck truck = factory.createTruck();
- System.out.println("生産了:" + truck.getType());
- //取得工廠對象
- factory = CarFactory.getCarFactory(CarFactory.BUS_TRUCK_MODEL);
- //生産公共汽車
- bus = factory.createBus();
- System.out.println("生産了:" + bus.getType());
- //生産卡車
- truck = factory.createTruck();
- System.out.println("生産了:" + truck.getType());
- }
- }
public class Client {
public static void main(String[] args) {
//取得工廠對象
CarFactory factory = CarFactory.getCarFactory(CarFactory.BUS_TRUCK);
//生産公共汽車
Bus bus = factory.createBus();
System.out.println("生産了:" + bus.getType());
//生産卡車
Truck truck = factory.createTruck();
System.out.println("生産了:" + truck.getType());
//取得工廠對象
factory = CarFactory.getCarFactory(CarFactory.BUS_TRUCK_MODEL);
//生産公共汽車
bus = factory.createBus();
System.out.println("生産了:" + bus.getType());
//生産卡車
truck = factory.createTruck();
System.out.println("生産了:" + truck.getType());
}
}
執行Client,輸出結果:
C:/AbstractFactory>javac *.java
C:/AbstractFactory>java Client
生産了:Bus
生産了:Truck
生産了:ModelBus
生産了:ModelTruck
C:/FactoryMethod>
小結
本文比較詳細地介紹了Abstract Factory模式的概念,并應用具體的範例讓我們更進一步地加深了對Abstract Factory模式的了解。
Abstract Factory模式的應用範圍很廣,近期我們會使用Abstract Factory模式實作支援多資料庫的DAO體系結構。