2012-03-10 33 views
1

我正在使用PHP的MVC框架,但我主要使用java,我正在尋找解決這個問題的方法,該方法遵循OOP原則,並且可以轉換爲其他語言。MVC:我如何減少多態方法的數量?

我有一些數據(數據庫,XML,等等)進行交互的模型抽象類。繼承的類必須實現這些方法:

abstract class Model { 

abstract public function nextItem(); 

abstract public function insert(Map $item); 

abstract public function update(Map $item); 

abstract public function delete(Map $item); 

abstract public function exists(Map $item); 

abstract public function countItems(); 

abstract public function allItems(); 

控制器通過其保持關於要被插入的,更新的項目的信息的地圖對象,刪除等。這意味着模型和控制器被解耦和任何模型可以注入控制器,只要有這些方法的實現。

當使用這個類在實踐中我發現,已經出現了情況,其中由控制器所需要的操作是非常獨特的,例如以特定的方式重新排序的數據。這是一個壞的解決方案:

abstract public function reorder(Map $item); 

該解決方案意味着每個模型必須實現這種方法,這是不必要的。另外想象一下,如果我需要其他方法,抽象方法的數量將會增長並增長,每個方法都需要一個實現。

另一解決方案是這樣的:

abstract public function action(Map $item, $action) 

的$操作變量將其限定了一操作的字符串。所以,你可以實現不同的方法,但只與多態動作()方法調用它們:

if ($action === "reorder") { $this->reorder($item); } 

這種解決方案的唯一問題是,正確的命令是不能從方法簽名明顯。例如,$ action字符串可以是任何東西,另一個開發人員將不得不檢查方法體(實現)來查找可接受的字符串。簡單地在文檔中陳述它們似乎是一個簡單的解決方案。另外,如果一個模型被注入一個沒有實現所有需要的操作的控制器中呢?拋出異常?

好像我必須缺少某種真正明顯的解決方案的,我不希望繼續前進,實現上述一個,然後有在很大程度上重構後,當我找到一個更好的。有任何想法嗎?

編輯: 到目前爲止,使用多個接口似乎是最好的解決方案。雖然有一個類型安全問題。如果我要將實現接口ReOrderable的模型注入到我的Controller類中,我希望能夠執行__construct(實現這些接口$ model的任何模型)。我可以創建更多抽象類,如ReOrderableModel,然後執行__construct(ReOrderableModel $ model),但可以有任意數量的接口組合,並且我必須爲每個接口定義一個額外的抽象類。我也可以將Model變成一個接口並使用多接口繼承,但實質上卻出現了同樣的問題。我肯定錯過了什麼。

+0

當前表單中的結構違反了[單一責任原則](http://en.wikipedia.org/wiki/Single_responsibility_principle)。爲什麼? – 2012-03-14 02:37:44

回答

1

我將定義一個IReOrderable接口,並讓您的實際Model類實現此接口。如果它不是用於全部繼承類,則不需要在抽象類級別完成。

我用一個abstract Model類,然後一噸的Interfaces的實際Model實現。

+0

這似乎是最好的主意。唯一的問題是將依賴項注入到控制器構造函數中時:「__construct(Model $ model)」,我不想爲類型聲明使用IReOrderable,因爲我不想僅僅允許任何實現它的類被注入。我可以製作更多的抽象類:「ReOrderableModel類實現ReOrderable」?理想情況下,我想說__construct(實現這些接口$模型的任何模型),但這當然是不可能的。 – Jonathan 2012-03-10 02:28:19

0

一方面,抽象類中的所有方法都不是抽象的。因此,可以選擇創建高度專業化方法的具體版本,並讓子類根據需要覆蓋這些版本。也許不像你想要的那樣吸引人,你也可以使用額外的接口來補充抽象類。所述接口將由需要的子類實現。

爲了說明上述情況,你可以有

public void function reorder(Map $item){ 
    //this is a concrete function that does nothing 
} 

因爲功能不是抽象的,那麼就不必受到​​孩子們的覆蓋。

1

一個選項(不確定在你的上下文中是否有意義)是模仿Java集合。某些操作會拋出UnsupportedOperationException。麻煩的是,來電者很少知道什麼時候會到那裏。

如果你使用你的第二個解決方案,第二個參數表示要採取的行動,我強烈建議一個枚舉。 (PHP是否有相當的???)讓另一位程序員更容易找出可能性,並且它絕對避免了許多錯誤。

+0

是的,我認爲,但PHP不支持枚舉,只支持有點煩人的常量。 PHP也沒有泛型。希望將來會有他們的支持。好主意,儘管謝謝!界面的想法可能是迄今爲止最好的。 – Jonathan 2012-03-10 01:16:24