gpt4 book ai didi

php - 了解 IoC、DI 和引用方法

转载 作者:可可西里 更新时间:2023-11-01 12:36:33 27 4
gpt4 key购买 nike

我正在学习依赖注入(inject)和控制反转,我想我开始理解它是如何工作的:

  • 对象不应该关心自己依赖的创建
  • 应将依赖项传递给对象(通过构造函数或 setter 方法)
  • DI 容器可以完成创建具有所有必需依赖项的对象的工作

如果一切正确,我是否可以不再在我的对象中使用我所谓的“引用方法”?

这就是我所说的引用方法。假设我有两个模型用于家庭和家庭成员。我发现创建引用与该模型相关的对象的方法非常有帮助。在下面的示例中,当调用 $family->members() 时,我可以快速访问所有家庭成员。但是,这意味着我的 family 对象正在实例化 family_member 类……这不会违反 IoC 规则吗?

如果 family_member 类具有超出 family 类范围的依赖项怎么办?在这里输入将非常有用!

<?php

class family
{
public $id;

public function members()
{
// Return an array of family_member objects
}
}

class family_member
{
public $family_id;
public $first_name;
public $last_name;
public $age;
}

最佳答案

免责声明:我只是自己学习 DI。对答案持保留态度。

依赖注入(inject)只是注入(inject)依赖。如果您的面向对象设计导致 Family 对象负责创建 Member 的实例,那么一定要让 Family 对象创建Member,因为在那种情况下,Member 不再被视为 Family 的依赖项,而是 责任。因此:

class Family
{
/**
* Constructor.
*
* Since you have decided in your OO design phase that this
* object should have the responsibility of creating members,
* Member is no longer a dependency. MySQLi is, since you need
* it to get the information to create the member. Inject it.
*
*/
public function __construct($id, MySQLi $mysqli)
{
$this->id = $id;
$this->mysqli = $mysqli;
}

/**
* Query the database for members data, instantiates them and
* return them.
*
*/
public function getMembers()
{
// Do work using MySQLi
}
}

但是如果你仔细想想,Family 真的应该有创建Member 的责任吗? 更好的设计是有另一个对象,例如 FamilyMapper 创建 Family 及其成员。像这样:

class FamilyMapper
{
/**
* Constructor.
*
* A better OO design, imho is using the DataMapper pattern.
* The mapper's responsibility is instantiating Family,
* which means it's going to have to connect to the database,
* which makes MySQLi its dependency. So we inject it.
*
*/
public function __construct(MySQLi $mysqli)
{
$this->mysqli = $mysqli;
}

public function findByID($familyID)
{
// Query database for family and members data
// Instantiate and return them
}

}

class Family
{
/**
* Constructor.
*
* Family is an object representing a Family and its members,
* along with methods that *operate* on the data, so Member
* in this OO design is a dependency. Inject it.
*
*/
public function __construct($id, MemberCollection $members)
{
$this->id;
$this->members;
}

public function getMembers()
{
return $this->members;
}
}

使用此模式,您的域对象及其方法(可能包含业务逻辑)将与您的数据访问代码分离。这就是依赖注入(inject)的好处 - 它迫使您重新考虑您的 OO 设计,以便您最终得到更清晰的代码。

许多人认为使用依赖注入(inject)意味着不使用工厂等。 这是错误的!依赖注入(inject)只是注入(inject)依赖。您也可以对工厂对象使用依赖注入(inject),方法是将依赖注入(inject)工厂而不是让工厂实例化自己的依赖。

有用的链接:

  1. http://martinfowler.com/articles/injection.html
  2. Does anyone have a good analogy for dependency injection?
  3. How to explain dependency injection to a 5-year-old?

添加

同样,对下面的内容持保留态度。

另请注意,依赖注入(inject)依赖注入(inject)容器 之间存在差异。第一个是注入(inject)依赖项而不是让对象自己创建依赖项的简单概念(这会导致非常高的耦合)。我们从上面的例子中看到了这一点。

后者是处理依赖注入(inject)的框架/库的术语,因此您不必进行手动注入(inject)。容器的职责是连接依赖项,因此您不必做脏活累活。这个想法是你定义一个依赖注入(inject)配置,它告诉容器 Foo 对象有什么依赖,以及如何注入(inject)它们。容器读取文档并为您执行注入(inject)。 Pimple、SimpleDIC 等 DIC 库就是这样做的。

您可以将依赖注入(inject)容器与工厂进行比较,因为两者都是创建对象,其唯一职责是创建对象。虽然工厂通常是专门的(即 FamilyMemberFactory 创建 MemberInterface 的实例),但依赖注入(inject)容器更为通用。有人说使用依赖注入(inject)容器可以让您摆脱对工厂的需求,但您应该记住,这意味着您必须创建和维护依赖注入(inject)配置文件,这可能是数千行 XML/PHP 行。

希望对您有所帮助。

关于php - 了解 IoC、DI 和引用方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7881378/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com