这似乎是一个广泛的问题,但是依赖注入与在__construct()
调用中实例化类的实际用途是什么?
我基本上在需要它的类中实例化我的数据库对象:
class Example {
private $db;
function __construct() {
$this->db = db::instance();
}
}
我过去曾使用依赖注入,并且不知道是否可以简单地共享资源,例如从Model
获取以下内容。
Class ExampleModel extends Model {
function do_something() {
$user = new User($db);
$user->do_some_stuff();
}
}
那么使用什么更有利?是否有任何与绩效相关的利弊?如果您需要对问题进行更多说明,请询问。
有很多积极的&关于依赖注入的负面看法:
对于任何感兴趣的人,这就是db::instance()
的样子:
public static function instance() {
if (!self::$instance) {
$config = get_config();
self::$instance = new self(
$config['database']['host'], $config['database']['user'], $config['database']['pass'], $config['database']['db']
);
}
return self::$instance;
}
答案 0 :(得分:1)
总结我的评论 - 对我来说,如果你注入了依赖关系,那么Example
不需要知道你注入的类是什么。如果您从Example
中实例化该类,那么您需要确切地知道该类是什么。
这是一个问题/好处吗?取决于您,您的偏好和您的应用程序。我倾向于选择更抽象的方法。
例如,如果您执行了以下操作:
class Example {
public function __construct(Injected $inj) {
$this->db = $inj;
}
}
...您可以看到您输入提示您期望$inj
的内容。这可以是$inj
直接所在的类的类型,也可以是$inj
实现的接口类型 - 在这种情况下,您将知道$inj
遵循您期望的一组指令
采用以下示例:
interface Db {
public function fetch();
public function insert();
}
class MyDb implements Db {
public function fetch() {
// ...
}
public function insert() {
// ...
}
}
如果您在Example
课程中键入提示界面,则无需知道$inj
是MyDb
课程,但它实施Db
- 重要的是要知道该类将遵循一组定义的规则(一个接口),例如这将实现fetch()
和insert()
功能。没关系实际的课程 - 你只想要内容。
class Example {
public function __construct(Db $inj) {
var_dump(get_class($inj)); // string(4) "MyDb"
}
}
这是注射及其益处的全部例子。直接实例化的等价物意味着您的Example
需要了解MyDb
:
class Example {
public function __construct() {
$this->db = new MyDb; // implements Db, but you need to know exactly
// what the class is
}
}
此方法消除了您将MyDb
更改为YourDb
的灵活性,而无需更改Example
类。
再次,取决于你的情况。如果您的应用程序有可能在组件内进行更改或具有灵活性,则可能需要使用注入。如果它是合理的静态,那么你可以直接实例化。
我最后的评论是,当你对代码进行单元测试时,模拟注入的对象要比直接实例化的对象容易得多。