【发布时间】:2014-05-05 12:13:10
【问题描述】:
我研究了很多次,向stackoverflow专家寻求最佳实践,但我仍然找不到解决方案,我可能已经得到了正确的答案,但我没有得到它。
我一直想创建一个“正确”的 MVC 模式来处理我的项目,例如我一直在研究这个 http://www.phpro.org/tutorials/Model-View-Controller-MVC.html 但我被告知这是一个糟糕的设计,我应该不再使用注册模式。
所以我查看了 teresko 的答案,尽管它很旧,但可以在这里看到 How should a model be structured in MVC?,我在那里有了想法,使用全球工厂,这将创建其他工厂
我从那里得到的想法是有一个大工厂,称为ServiceFactory,它将创建其他工厂的实例,例如 ModelFactory,它将创建服务于模型层的类的实例,以及一个 ViewFactory,它将服务于视图(我认为目前非常无用)。
但是得到了这样的东西:
namespace library\application;
use library\application\exceptions\ClassNotFoundException;
use library\application\exceptions\PackageNotFoundException;
class ServiceFactory {
private $mapper;
private $package;
private $services = array();
public function __construct(DataMapper $mapper) {
$this->mapper = $mapper;
}
/**
* Setting a default package
* @param $package string Package path
* @throws exceptions\PackageNotFoundException
*/
public function setDefaultPackage($package) {
if (is_dir('library' . $package)) {
$this->package = 'library' . $package;
return;
}
throw new PackageNotFoundException("The package: " . $package . " was not found.");
}
/**
* @param $name string Class name
* @param null $constructor IF the class needs constructor parameters, use it.
* @return Factory
* @throws exceptions\ClassNotFoundException
*/
public function create($name, $constructor = null) {
$path = $this->package . "\\" . $name;
if (file_exists($path)) {
if ($constructor) {
return new $path($constructor);
}
return new $path;
}
throw new ClassNotFoundException("The requested class was not found: " . $path);
}
/**
* @param $name string Class name
* @param $object object Object to register
*/
public function register($name, $object) {
$this->services[$name] = $object;
}
/**
* @param $name string Class name
* @return Factory
*/
public function get($name) {
if (isset($this->services[$name])) {
return $this->services[$name];
}
return null;
}
}
这实际上很棒,但在我看来,从面向对象的角度来看,这是完全错误的,因为它不是面向对象友好的,因为 S ServiceFactory::create() 的返回对象是匿名的,很好,它不再是匿名的,因为该类的目的是创建工厂的实例,当然,只是添加了工厂的接口作为回报。
但是现在下一个问题,当我想使用工厂创建对象时,不应该有相同的接口,这会给我的 IDE 带来问题,因为它不知道是什么我要返回的对象,可以是 Foo,可以是 Car,有一天它可以是 HelloWorld。
所以在控制器中使用对象时,我总是必须用对象声明一个变量:
/**
* @var $items Items
* @var $categories CategoryModel
*/
$items = parent::getModelFactory()->create('Items');
$items->setDb(parent::getDatabase());
$categories = parent::getModelFactory()->create('Categories');
$categories->setDb(parent::getDatabase());
现在在Teresko 的答案之一中,它说以下规则:A controller can not create instances of the Model layer
所以我假设他的意思是控制器中的$foo = new Foo(); $foo->method($db);,但为什么不呢?控制器应该如何与模型层进行实际通信?
我创建那个上帝工厂类的主要目的是防止在控制器类中执行new Object(),但是由于它调用了创建实例的工厂,所以它仍然被认为是我正在创建模型的实例控制器中的层(我认为)。
我也可以缓存对象,使用ServiceFactory::register() 方法,但这并不能改变这种情况。
那么ServiceFactory 和工厂的想法好吗?控制器和模型层之间的正确通信方式是什么?
【问题讨论】:
标签: php oop design-patterns model-view-controller factory