徹底分清簡單,工廠,抽象工廠模式+優化

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();
    }
}

總:
從簡單工廠到工廠模式是遵循了開閉原則,從工廠模式的抽象工廠模式是實現對多個抽象產品的場景應用,優化方法則避免多處修改,並且實現了可配置;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章