依赖注入或实例化数据库 class 对象
Dependency Injection or instantiating database class object
这似乎是一个广泛的问题,但是依赖注入与在 __construct()
调用中实例化 class 的实际用途是什么?
我基本上在需要它的 classes 中像这样实例化我的数据库对象:
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();
}
}
那么用什么比较有利呢?有没有性能相关的pros/cons?如果您需要对问题进行更多说明,请询问。
对依赖注入有很多正面和负面的看法:
- Dependency Injection is EVIL
- Dependency Injections Pros/Cons/Questions
- Dependency Injection discourages object orientated programming
对于任何感兴趣的人,这就是 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;
}
总结我的评论 - 对我来说,如果您注入依赖项,那么 Example
不需要知道您注入的 class 是什么。如果您从 Example
中实例化 class 那么您需要确切地知道 class 是什么。
这是problem/benefit吗?取决于您、您的偏好和您的应用。我倾向于更抽象的方法。
例如,如果您执行了以下操作:
class Example {
public function __construct(Injected $inj) {
$this->db = $inj;
}
}
...您可以看到您输入的提示是您期望 $inj
的内容。这可以是 $inj
直接是 class 的类型,也可以是 $inj
实现的接口 - 在这种情况下,您将知道 $inj
遵循一组您期望的说明。
举个例子:
interface Db {
public function fetch();
public function insert();
}
class MyDb implements Db {
public function fetch() {
// ...
}
public function insert() {
// ...
}
}
如果您在 Example
class 中键入提示接口,您不需要知道 $inj
是 MyDb
class,但它实现了 Db
- 重要的部分是知道 class 将遵循一组定义的规则(接口),例如即会实现 fetch()
和 insert()
函数。没关系实际 class - 你只需要内容。
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
class.
同样,取决于您的情况。如果您的应用程序有可能更改或在组件内具有灵活性,您可能希望使用注入。如果它是相当静态的,那么你可以直接实例化。
我最后的评论是,当您对代码进行单元测试时,模拟注入的对象比直接实例化的对象要容易得多。
这似乎是一个广泛的问题,但是依赖注入与在 __construct()
调用中实例化 class 的实际用途是什么?
我基本上在需要它的 classes 中像这样实例化我的数据库对象:
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();
}
}
那么用什么比较有利呢?有没有性能相关的pros/cons?如果您需要对问题进行更多说明,请询问。
对依赖注入有很多正面和负面的看法:
- Dependency Injection is EVIL
- Dependency Injections Pros/Cons/Questions
- Dependency Injection discourages object orientated programming
对于任何感兴趣的人,这就是 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;
}
总结我的评论 - 对我来说,如果您注入依赖项,那么 Example
不需要知道您注入的 class 是什么。如果您从 Example
中实例化 class 那么您需要确切地知道 class 是什么。
这是problem/benefit吗?取决于您、您的偏好和您的应用。我倾向于更抽象的方法。
例如,如果您执行了以下操作:
class Example {
public function __construct(Injected $inj) {
$this->db = $inj;
}
}
...您可以看到您输入的提示是您期望 $inj
的内容。这可以是 $inj
直接是 class 的类型,也可以是 $inj
实现的接口 - 在这种情况下,您将知道 $inj
遵循一组您期望的说明。
举个例子:
interface Db {
public function fetch();
public function insert();
}
class MyDb implements Db {
public function fetch() {
// ...
}
public function insert() {
// ...
}
}
如果您在 Example
class 中键入提示接口,您不需要知道 $inj
是 MyDb
class,但它实现了 Db
- 重要的部分是知道 class 将遵循一组定义的规则(接口),例如即会实现 fetch()
和 insert()
函数。没关系实际 class - 你只需要内容。
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
class.
同样,取决于您的情况。如果您的应用程序有可能更改或在组件内具有灵活性,您可能希望使用注入。如果它是相当静态的,那么你可以直接实例化。
我最后的评论是,当您对代码进行单元测试时,模拟注入的对象比直接实例化的对象要容易得多。