在我的课堂上,我们使用带有Java中的观察者模式的MVC创建了一个简单的应用程序,它可以工作。视图无法调用模型中未包含在(Observable)界面中的任何方法,反之亦然。
我非常喜欢PHP,并决定在PHP中使用相同(简化)的示例。我注意到即使我使用接口并将模型的引用作为接口传递,视图仍然可以在模型中调用每个方法,使整个模式无用。
有没有我忽略的东西,或者这在PHP中是不可能的?
PHP代码(每个引用,方法等与Java应用程序完全相同):
class App
{
public function __construct()
{
$model = new Model();
$controller = new Controller($model);
}
}
class Model implements Observable
{
private $view;
private $count = 1;
public function __construct()
{
echo 'Model created. <br>';
}
public function registrate(Observer $view)
{
$this->view = $view;
echo 'Model: view is registered. <br>';
}
public function addOne()
{
$this->count += 1;
$this->view->modelChanged($this);
}
public function getCounter()
{
return $this->count;
}
public function getMessage()
{
return 'The view should not be able to call this method.';
}
}
class Controller
{
private $view;
private $model;
public function __construct(Model $model)
{
echo 'Controller created. <br>';
$this->model = $model;
$this->view = new View($this->model);
$this->model->addOne();
}
}
class View implements Observer
{
public function __construct(Observable $model)
{
echo 'View created. <br>';
$model->registrate($this);
}
public function modelChanged(Observable $model)
{
// Should only be able to call method "getCounter()"
echo $model->getMessage();
}
}
interface Observable
{
public function registrate(Observer $view);
public function getCounter();
}
interface Observer
{
public function modelChanged(Observable $model);
}
输出,如果你运行它是:
模型已创建。
创建控制器。
查看已创建。
模型:视图已注册。
视图不应该能够调用此方法。如您所见,视图可以调用在Observable接口内声明的 not 模型的方法。
这怎么可能?为什么这不像在Java中那样在PHP中起作用?
答案 0 :(得分:1)
当然,视图可以调用您在模型上定义的每个方法:所有方法都是 public ,这意味着它们可以从任何地方调用。只需将它们定义为protected
或private
而不是......
当然,这会限制您在其他组件(例如控制器)中使用该模型的方式。要解决这个问题,一个简单的解决方法是创建一个包装器,当您将模型传递给视图时,可以将其包裹起来:
class View implements Observable
{
public function __construct(ViewObservable $model)
{
//do stuff here
}
}
//Wrapper:
class ViewObservable
{
/**
* @var Model
*/
protected $payload = null;
public class __construct(Observable $model)
{
$this->payload = $model;
}
public function getCounter()
{
return $this->payload->getCounter();
}
}
但实际上,你可能想重新考虑一件事情或者2.使用接口是好的,但是对于所有组件来说,(至少对我来说)没有多大意义。 MVC架构实现相同的接口。所有组件都有不同的工作要执行,因此应具有不同的接口要求。