1. 程式人生 > >設計模式系列---簡單工廠、工廠方法、抽象工廠

設計模式系列---簡單工廠、工廠方法、抽象工廠

nds top exc .cn 原則 而在 類圖 opp sop

前言,最近看spring的源代碼。發現之前沒有完全弄懂(工廠方法、抽象工廠)的區別。

spring中代理對象的產生,是通過代理工廠(工廠模式),首先spring中的代理是使用jdk或者cglib的代理,只要看目標類是否實現接口。

public class ProxyFactory extends ProxyCreatorSupport {
   //createAopProxy()方法是通過AopProxyFactory獲取AopProxy(JDK,CGLIB)
    public Object getProxy() {
        return createAopProxy().getProxy();
    }
}

  這裏典型應用了工廠模式

  工廠接口:

public interface AopProxyFactory {
    AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException;
}

  目標產品:

  AopProxy

    ----CglibAopProxy------ObjenesisCglibAopProxy

    ----JdkDynamicAopProxy

  工廠實現類:

public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
    @Override
    
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { Class<?> targetClass = config.getTargetClass(); if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " + "Either an interface or a target is required for proxy creation."); } if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) { return new JdkDynamicAopProxy(config); } return new ObjenesisCglibAopProxy(config); } else { return new JdkDynamicAopProxy(config); } } }

  (這其實是一個簡單的抽象工程模式),待會再來分析。我們先進入主題

  1 簡單工程模式

  產品接口(抽象產品)

public interface AOPProxy {

}

  產品實現類(具體產品)

public class JDKAOPProxy implements AOPProxy{

}
public class CGLIBAOPProxy implements AOPProxy{

}

  工廠類(簡單工程)

public class AopProxyFactory {
    AOPProxy createJDKAOPProxy(){
        return new JDKAOPProxy();
    }
    AOPProxy createCGLIBAOPProxy(){
        return new CGLIBAOPProxy();
    }
}

  說明:這便是簡單工廠模式了,首先,符合現實中的情況;而且客戶端免除了直接創建產品對象的責任,而僅僅負責“消費”產品。下面我們從開閉原則上來分析下簡單工廠模式。當未來增加了一個AopProxy的時候(MYAOPProxy),只要符合抽象產品制定的合同,那麽只要通知工廠類知道就可以被客戶使用了。(即創建一個新的子類(MYAOPProxy),繼承抽象產品AOPProxy)那麽 對於產品部分來說,它是符合開閉原則的——對擴展開放、對修改關閉;但是工廠類不太理想,因為每增加AopProxy,都要在工廠類中增加相應的商業邏輯和判 斷邏輯,這顯自然是違背開閉原則的。

  而在實際應用中,很可能產品是一個多層次的樹狀結構。由於簡單工廠模式中只有一個工廠類來對應這些產品,所以這可能會把我們的上帝類壞了。
正如我前面提到的簡單工廠模式適用於業務簡單的情況下或者具體產品很少增加的情況。而對於復雜的業務環境可能不太適應了。這就應該由工廠方法模式來出場了!!

  2 工程方法模式

  抽象工廠角色: 這是工廠方法模式的核心,它與應用程序無關。是具體工廠角色必須實現的接口或者必須繼承的父類。在java中它由抽象類或者接口來實現。
  具體工廠角色:它含有和具體業務邏輯有關的代碼。由應用程序調用以創建對應的具體產品的對象。在java中它由具體的類來實現。
  抽象產品角色:它是具體產品繼承的父類或者是實現的接口。在java中一般有抽象類或者接口來實現。
  具體產品角色:具體工廠角色所創建的對象就是此角色的實例。在java中由具體的類來實現。

  來用類圖來清晰的表示下的它們之間的關系:

技術分享

  抽象產品

public interface AOPProxy {

}

  具體產品

public class JDKAOPProxy implements AOPProxy{

}
public class CGLIBAOPProxy implements AOPProxy{

}

  抽象工廠接口

public interface AopProxyFactory {
    AOPProxy createAOPProxy();
}

  工廠實現

public class CGLIBAopProxyFactory implements AopProxyFactory{
    @Override
    public AOPProxy createAOPProxy() {
        return new CGLIBAOPProxy();
    }
}
public class JDKAopProxyFactory implements AopProxyFactory{
    @Override
    public AOPProxy createAOPProxy() {
        return new JDKAOPProxy();
    }
}

  說明:使用開閉原則來分析下工廠方法模式。當有新的產品(MYAOPProxy)產生時,只要按照抽象產品角色、抽象工廠角色提供的合同來生成,那麽就可以被客戶使用,而不必去修改任何已有的代碼。(即當有新產品時,只要創建並基礎抽象產品;新建具體工廠繼承抽象工廠;而不用修改任何一個類)工廠方法模式是完全符合開閉原則的!

  使用工廠方法模式足以應付我們可能遇到的大部分業務需求。但是當產品種類非常多時,就會出現大量的與之對應的工廠類,這不應該是我們所希望的。所以我建議在這種情況下使用簡單工廠模式與工廠方法模式相結合的方式來減少工廠類:即對於產品樹上類似的種類(一般是樹的葉子中互為兄弟的)使用簡單工廠模式來實現。
  當然特殊的情況,就要特殊對待了:對於系統中存在不同的產品樹,而且產品樹上存在產品族(下一節將解釋這個名詞)。那麽這種情況下就可能可以使用抽象工廠模式了。

  3 抽象工廠模式

  加入現在有一個新的產品叫做OOPProxy也有兩種實現JDKOOPProxy、CGLIBOOPProxy,這樣工廠方法模式實現(工廠方法模式只有單一的產品組)。

  抽象產品AOPProxy

public interface AOPProxy {
}

  抽象產品AOPProxy實現

public class JDKAOPProxy implements AOPProxy{
}

public class CGLIBAOPProxy implements AOPProxy{
}

  抽象產品OOPProxy

public interface OOPProxy {
}

  抽象產品OOPProxy實現

public class JDKOOPProxy implements OOPProxy{
}

public class CGLIBOOPProxy implements OOPProxy{
}

  抽象工廠ProxyFacoty

public interface ProxyFactory {
    AOPProxy createAOPProxy();
    OOPProxy createOOPProxy();
}

  抽象工廠實現JDKProxyFactory

public class JDKProxyFactory implements ProxyFactory{
    @Override
    public AOPProxy createAOPProxy() {
        return new JDKAOPProxy();
    }

    @Override
    public OOPProxy createOOPProxy() {
        return new JDKOOPProxy();
    }
}

  抽象工廠實現OOPAOPFacoty

public class CGLIBProxyFactory implements ProxyFactory{
    @Override
    public AOPProxy createAOPProxy() {
        return new CGLIBAOPProxy();
    }

    @Override
    public OOPProxy createOOPProxy() {
        return new CGLIBOOPProxy();
    }
}

  

  其中:JDKAOPProxy和CGLIBAOPProxy屬於產品樹、同理JDKOOPProxy和CGLIBOOPProxy。而JDKAOPProxy和JDKOOPProxy屬於產品族。

  所以抽象工廠模式一般用於具有產品樹和產品族的場景下。

  抽象工廠模式的缺點:如果需要增加新的產品樹,那麽就要新增三個產品類,比如TOPProxy,JDKTOPProxy, CGLIBTOPProxy,修改三個工廠類。這樣大批量的改動是很醜陋的做法。

設計模式系列---簡單工廠、工廠方法、抽象工廠