2010-11-22 34 views
0

我已經交給的代碼庫使用的功能是一個從MDB2繼承的數據庫類。這構成了使用MVC框架(一個定製的事務)的基礎,而模型又從db繼承。修改一個類來封裝而不是繼承

正如我確信你們中的一些人已經注意到,這導致了一個相當大的問題。每次您實例化一個模型時,結果都會創建一個新的數據庫連接。這顯然很浪費。這也意味着我無法按預期使用事務,因爲如果一個事務在模型的一個實例中啓動,其效果對其他實例是不可見的,直到發生提交。

我的計劃是更改db類來封裝MDB2而不是繼承它,然後讓它通過其單例功能來維護單個MDB2實例。

但是,MDB2是一個有很多方法的大型庫,代碼庫中的很多東西依賴於能夠訪問MDB2方法。

是否有方法來封裝MDB2類並將調用傳遞給它,而無需修改更高層,也無需爲MDB2中的每個方法編寫包裝器方法?

+0

請問您可以展示一個示例模型類,以便我們可以看到它們的耦合程度? – Gordon 2010-11-22 10:35:26

回答

3

因爲您還沒有提供任何代碼,所以這是一個盲目的建議,您可以用很少的代碼去除繼承,同時保持完整的功能並確保MDB類僅實例化一次。

class Db 
{ 
    protected static $_mdb; 
    public function __construct() 
    { 
     if(self::_mdb === NULL) { 
      self::_mdb = new MDB; 
     } 
    } 
    public function __call($method, $args) 
    { 
     return call_user_func_array(array(self::_mdb, $method), $args); 
    } 
} 

這基本上會讓您的DB類成爲MDB的裝飾器。在第一次實例化時,DB類將創建並存儲一個MDB的靜態實例。這將在任何數據庫實例中共享,包括子類。在這裏沒有理由使用Singleton。

__call攔截器將確保您在DB中調用的方法將被捕獲並委派給MDB實例。魔術方法可能會對性能造成嚴重影響,所以當您發現任何性能影響時,請將所有調用的方法添加到數據庫類並從中進行委派。不用說,這仍然不是最好的解決方案,因爲你的數據庫實例仍然與你的模型類緊密耦合。如果你可以承受更多的重構,我會建議讓當前從DB繼承的所有類封裝數據庫實例(除非它們是ActiveRecords)。然後使用依賴注入來使數據庫實例可用。