这是一个普遍的场景。我有“任务”和“任务事件”。我为每个创建了一个数据库表。我还创建了一个模型来处理从数据库中获取记录。
对于“任务事件”,我有几种类型:已创建、已接受、已评论、已关闭。
目前,我做了一些简单的事情,比如$task = new Task($task_id);
从数据库中获取任务,并获取该任务$task_events = new Tasks_Events($task_id);
的事件。然后,我实现了 Iterator 所以我可以做到foreach($task_events as $e) { ... }
这一切都很好。
但是,我发现我需要一些专门的处理程序来处理一些事件类型。例如,我创建了扩展 Tasks_Events 的 Tasks_Events_Comments,并对 Comment 事件类型进行了一些额外的处理。我现在意识到的是,当我收集事件集合时,我确实需要它们是子类型,因此如果在事件上调用方法,则会调用子类型的正确覆盖。
这是一个简单的例子:
class Model {
public function __construct($search = null) {
// Hypothetical example, basically query the DB and populate data.
if (!is_null($search)) { $this->search($search); }
}
protected function onAfterUpdate() { }
}
class Tasks_Events extends Model {
protected function onAfterUpdate() { /* Task Event Specific */ }
}
class Tasks_Events_Comments extends Tasks_Events {
protected function onAfterUpdate() { /* Task Event Comment Specific */ }
}
然后,一个假设的用例:
class Controller {
public function updateEvent($task_id, $event_id, $params) {
$task = new Tasks($task_id);
$task_event = new Tasks_Events($event_id);
// Some Analysis of Params
$task_event->status = $new_status;
$task_event->save();
}
}
所以,这里是关键。这样做会调用 Tasks_Events onAfterUpdate()...
我的问题是,什么是我可以使用的模型、范式、哲学和方法,以便当我有一组任务事件并且我对其中一个事件采取行动时,即使我使用的是基类引用,我也需要拥有子类函数调用。
我真的很喜欢$e = new Tasks_Events(3); $e->status = 4; $e->save();
我不喜欢的一种解决方案的简单性,就是执行类似$e = Tasks_Events::Get($id);
Tasks_Events 查询数据库、确定类型、然后执行“切换”并创建要返回的正确类型的操作。
我不喜欢这样的另一个原因是因为我已经建立了模型来做一些很酷的事情,比如$tasks = new Tasks(array('user_id' => 5, 'status' => Tasks::STATUS_OPEN));
它会构建正确的数据库查询,并填充用户 5 的所有打开的任务。然后我可以做foreach($tasks as $t) { echo $t->subject; }
等等。所以,我很想能够保持这种系统....但我不确定我是否可以利用子类型的继承。
恐怕我可能需要一个工厂模式,但我希望我可能会遗漏一些东西。
PS如果您能想到更好的标题,请随时更改。