2012-03-10 30 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