1. 簡單工廠模式(靜態工廠模式)
根據客戶端傳入指定產品的參數,通過工廠類判斷該參數,直接返回相應的具體產品向上轉型對象;
角色:
抽象產品A:與客戶端交互的抽象產品;
具體產品:實現抽象產品的ProductA1 ,ProductA2,
簡單工廠:客戶端根據工廠方法傳入向的參數返回具體產品;
interface ProductA{}
class ProductA1 implements ProductA{}
class ProductA2 implements ProductA{}
class SimpleFactory{
public static ProductA getProduct(String category){
if (category.equals("a1")){
return new ProductA1();
}
if (category.equals("a2")){
return new ProductA2();
}
return null;
}
}
簡單工廠方法實現了客戶端與具體產品實現的解耦,通過抽象出抽象產品,一定程度上提高了程序的可拓展性。當我們需要添加第三種子產品時,我們只需要在工廠類增加返回相應產品的代碼,客戶端並不需要修改原來的代碼;
雖然如此,我們需要修改工廠類代碼,依然是違背了開閉原則(對拓展開放,對修改關閉);
而工廠模式則是完全遵循了開閉原則;
2. 工廠模式
工廠模式通過依賴倒轉原則,面向接口設計,實現在不修改原來的代碼的同時,對功能實現拓展;
角色:
抽象產品:(定義抽象接口,提高拓展性)
具體產品:ProductA1,ProductA2
抽象工廠:定義創建抽象產品
具體工廠:具體共產與具體產品一一,實現抽象工廠,創建具體產品;
interface Factory{
ProductA createProductA();
}
class FactoryA1 implements Factory{
@Override
public ProductA createProductA() {
return new ProductA1();
}
}
class FactoryA2 implements Factory{
@Override
public ProductA createProductA() {
return new ProductA2();
}
}
工廠方法將創建具體產品的過程封裝到具體工廠當中,這使得選擇哪種具體產品的判斷也就交個了客戶端;這也是與簡單工廠方法的區別之一;
不管是簡單工廠方法還是工廠方法,都應對的是隻用一種抽象產品的場景;
如果存在兩種抽象產品,以上方法或許可以通過複製一份的方法實現,但是複製往往是最糟糕的設計,所以抽象工廠方法便提供了更優解;
3. 抽象工廠模式
與工廠模式相比,抽象模式下的抽象工廠抽象的就是多種抽象產品創建過程,而不再是一種了;
角色:
抽象產品:ProductA,ProductB
具體產品:ProductA1,ProductB1, ProductA2,ProductB2(可以假設是產品版本)
抽象工廠:IFactory
具體工廠:Factory1,Factory2,具體工廠會提供創建兩種產品的方法;
/////抽象工廠/////
interface ProductB{}
class ProductB1 implements ProductB{};
class ProductB2 implements ProductB{};
interface IFactory{
ProductA createProductA();
ProductB createProductB();
}
class Factory1 implements IFactory{
@Override
public ProductA createProductA() {
return new ProductA1();
}
@Override
public ProductB createProductB() {
return new ProductB1();
}
}
class Factory2 implements IFactory{
@Override
public ProductA createProductA() {
return new ProductA2();
}
@Override
public ProductB createProductB() {
return new ProductB2();
}
}
以上工廠的方法的客戶端實現:
public class Client {
public static void main(String[] args) {
//simple
ProductA a1 = SimpleFactory.getProduct("a1");
//factory
Factory factory = new FactoryA1();
ProductA factoryA1 = factory.createProductA();
factory = new FactoryA2();
ProductA productA2 = factory.createProductA();
//abstract
IFactory absFactory = new Factory1();
ProductA pa1 = absFactory.createProductA();
ProductB pb1 = absFactory.createProductB();
absFactory = new Factory2();
ProductA pa2 = absFactory.createProductA();
ProductB pb2 = absFactory.createProductB();
}
}
抽象工廠方法解決了工廠方法只能創建一種抽象產品的問題,使用了抽象工廠模式創建了獲取了具體產品後,如果需要更換比如使用升級產品,我們只需要在客戶端更改抽象共產的創建代碼;從一定程度上集中了我們修改代碼的工作量。
但是,如果客戶端在多處都使用了抽象工廠模式創建對象呢?一百個地方使用到了,我們就需要修改一百個地方,所以我們可以通過以下方式優化抽象工廠模式;
4. 利用反射+配置優化抽象工廠模式
通過配置的獲取客戶端具體想要的產品版本,在使用反射的代碼創建具體的產品;代替了抽象工廠和具體工廠創建具體產品的過程;
/**
* 使用反射 + 配置方式獲取產品版本號;代替IFactory,Factory1, Factory2
*/
public class OptimiseAbstractFactory {
@Value("A_VERSION")
String A_VERSION;
@Value("B_VERSION")
String B_VERSION;
public ProductA getProductA(){
ProductA pro=null;
String clzName = "com.ed.gof.abstractFactory.ProductA"+A_VERSION;
try {
Class<?> proClz = Class.forName(clzName);
pro = (ProductA) proClz.newInstance();
} catch (ClassNotFoundException | IllegalAccessException | InstantiationException e) {
e.printStackTrace();
}
return pro;
}
public ProductB getProductB(){
ProductB pro=null;
String clzName = "com.ed.gof.abstractFactory.ProductB"+B_VERSION;
try {
Class<?> proClz = Class.forName(clzName);
pro = (ProductB) proClz.newInstance();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
return pro;
}
//client
public static void main(String[] args) {
Optimistic optimistic = new Optimistic();
ProductA productA = optimistic.getProductA();
ProductB productB = optimistic.getProductB();
productA.functionA();productB.functionB();
}
}
總:
從簡單工廠到工廠模式是遵循了開閉原則,從工廠模式的抽象工廠模式是實現對多個抽象產品的場景應用,優化方法則避免多處修改,並且實現了可配置;