php – 是依赖注入,这是不好的做法吗?
我有一个小框架,我这样编码.我不知道它是否被称为依赖注入.我不知道它是否像一个设计模式.我也不知道,想知道如果通过$这是param是一个糟糕的做法.
看看这个; (不是一个工作的例子,只是将这些代码写入浏览器进行说明.) /* This is engine model */ require_once('Database.class.php'); require_once('Image.class.php'); require_once('Misc.class.php'); require_once('BBCode.class.php'); class FrameWork_Engine_Model { public $database,$config,$misc,$bbcode,$controller,$image; function __construct($config) { $this->database = new Database($configParams); $this->image = new Image($this); $this->misc = new Misc($this); $this->bbcode = new BBCode($this); $this->controller = new Controller($this); //here I call Register controller depending on routing,in this case,register controller. } ... } /* This is register controller */ class Register extends Base_Controller { /*I can access anything over Engine Model in my controllers */ $this->engine->database->query(); //I access database model $this->engine->bbcode->tag('you'); //I access bbcode model $this->engine->image->sanitizeUploadedFile(); //I access image model //etc. I can access others models like this. } 基本上,我的控制器可以通过引擎模型访问任何型号.我认为依赖注入是关于将依赖关系注入控制器?像我的注册控制器需要一个数据库模型,路由模型和模板模型工作.这里有它所依赖的一切.我错了吗 有了这些话,我的问题是: >这是一个有效的依赖注入示例吗?如果不是,那是什么?它有设计模式的名称吗? PS.我知道问题中的3个问题不是stackoverflow喜欢的东西,但是我不想复制粘贴整个文本来询问它们.
你几乎在那里
问题1 不,我不认为它是一个有效的依赖注入示例.它类似于一个服务定位器(因为您正在将整个容器注入到您的服务中并使用它来“定位”依赖服务). 问题2 你在依赖注入和依赖注入容器之间造成一个小的混乱. 首先,依赖注入意味着在运行时将依赖关系推送到对象中,而不是创建/拉取它们. 举例说明: //hardcoded dependecies class BadService { public function __construct() { $this->dep1 = new ConcreteObject1(); $this->dep2 = new ConcreteObject2(); } } 所以在上面的例子中,BadService使它在运行时连接其他依赖项是不可能的,因为它们已经很难被拖入构造函数本身. //service locator pattern class AlmostGoodService { public function __construct(Container $container) { $this->dep1 = $container->getADep1(); $this->dep2 = $container->getADep2(); } } 在AlmostGoodService示例中,我们已经从前面的示例中删除了硬依赖关系,但是我们仍然依赖于容器的特定实现(这意味着我们的服务不可重用,而不提供该容器的实现).这是与您正在做的事情相匹配的示例. //dependecy injection class GoodService { public function __construct($dep1,OptionalInterface $dep2) { $this->dep1 = $dep1; $this->dep2 = $dep2; } } GoodService服务不关心创建它的具体依赖关系,并且可以在运行时轻松地“有线”地执行$dep1或$dep2的OptionalInterface的“协议”的任何依赖关系(因此名称为Inversion of Control – 依赖注入背后的基本概念). 执行此接线的组件称为dependency injection container. 现在,dependency injection container是最简单的形式,只不过是一种能够在运行时基于某种形式配置对象的对象. 我说你几乎在那里,但你的实现有一些问题: >接线应该是懒惰的(你不想让所有的工作在你的构造函数中,因为你的应用程序会随着增长而大大减慢) 问题3 有些情况下,您会发现自己想要将整个$container作为依赖关系传递给服务(即控制器或懒惰服务工厂),但一般来说,远离这种做法会更好,因为它将使您的服务更可重复使用和更容易测试.当您感觉到您的服务具有太多的依赖关系时,那么这是一个很好的迹象,即您的服务太多,这是分割它的好时机. 原型容器实现 所以,根据上面的答案,这里是一个修改(远非完美)的实现: /* This is the revised engine model */ class FrameWork_Engine_Model { function __construct($config) { $this->config = $cofig; } public function database() { require_once('Database.class.php'); return new Database($this->config['configParams']); } public function bbcode() { require_once('BBCode.class.php'); return new BBCode($this->database()); } public function image() { require_once('Image.class.php'); $this->image = new Image($this->config['extensionName']); } .... public function register_controller($shared = true) { if ($shared && $this->register_controller) { return $this->register_controller; } return $this->register_controller = new Register_Controller($this->database(),$thus->image(),$this->bbcode()); } } 现在,要使用你的服务: $container = new FrameWork_Engine_Model(); $container->register_controller()->doSomeAction() 可以改进什么?您的容器应该: >提供一种分享服务的方式 – 也就是仅将其初始化一次 准备使用DI容器实现 所有这些都有关于Dependency Injection的明确文件 > Pimple – PHP 5.3轻量级DI容器 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |