我正在研究PHP中的MVC框架,但我主要使用java,我正在寻找一个解决这个问题的解决方案,它遵循OOP原则并可以转换为其他语言。
我有一个模型抽象类,它与一些数据(数据库,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();
控制器传递一个Map对象,该对象保存有关要插入,更新,删除等项目的信息。这意味着模型和控制器是分离的,任何Model都可以注入控制器,前提是有一个实现这些方法。
在实践中使用此类时,我发现有些情况下控制器所需的操作非常独特,例如以特定方式重新排序数据。这是一个不好的解决方案:
abstract public function reorder(Map $item);
此解决方案意味着每个模型都必须实现此方法,这是不必要的。同样想象一下,如果我需要其他方法,抽象方法的数量会增长和增长,每个方法都需要实现。
另一种解决方案是:
abstract public function action(Map $item, $action)
$ action变量将是一个定义动作的字符串。所以你可以实现不同的方法,但只能用多态action()方法调用它们:
if ($action === "reorder") { $this->reorder($item); }
此解决方案的唯一问题是方法签名中的正确命令不明显。例如,$ action字符串可以是任何东西,另一个开发人员必须检查方法体(实现)以找到可接受的字符串。简单地在文档中说明它们似乎是一个脆弱的解决方案。如果将模型注入到未实现所有必需操作的控制器中,该怎么办?抛出异常?
似乎我必须错过某种非常明显的解决方案,我不想继续执行上面的那个,然后在我找到更好的解决方案时必须重新进行重构。有什么想法吗?
修改 到目前为止,使用多个接口似乎是最好的解决方案。但是存在类型安全问题。如果我要将一个实现接口ReOrderable的Model注入我的Controller类中,我希望能够做__construct(实现这些接口$ model的任何模型)。我可以创建更多抽象类,如ReOrderableModel,然后执行__construct(ReOrderableModel $ model),但可能有任意数量的接口组合,我必须为每个接口组合一个额外的抽象类。我还可以将Model转换为接口并使用多个接口继承,但实际上会出现同样的问题。我一定错过了什么。
答案 0 :(得分:1)
我将定义一个IReOrderable
接口,并让您的实际Model类实现此接口。如果它不适用于所有继承类,则不需要在抽象类级别完成。
我使用了一个abstract Model
类,然后使用了大量的Interfaces
来实现Model
个实现。
答案 1 :(得分:1)
一个选项(不确定在您的上下文中是否有意义)是模仿Java Collections。某些操作将抛出UnsupportedOperationException。麻烦的是,来电者很少知道什么时候到那里。
如果您使用第二个解决方案,第二个参数指示要采取的操作,我强烈建议使用枚举。 (php有一个等价的吗?)让另一个程序员更容易找出可能性,它绝对避免了许多错误。
答案 2 :(得分:0)
一方面,抽象类中的所有方法都不需要是抽象的。因此,可以选择创建高度专业化方法的具体版本,并让子类根据需要覆盖这些方法。根据您的需要,也许不那么吸引人,您也可以使用其他界面来补充抽象类。所述接口将由需要的子类实现。
为了说明上述内容,您可以
public void function reorder(Map $item){
//this is a concrete function that does nothing
}
因为该函数不是抽象的,所以它不必被子项覆盖。