>对象不应该关注自己的依赖项的创建
>依赖项应该传递给对象(通过构造函数或setter方法)
> DI容器可以完成创建具有所有必需依赖项的对象的工作
如果这一切都正确,我可以不再使用我的对象中的“参考方法”吗?
这是我的参考方法的意思.说我有两个家庭和家庭成员模特.我发现创建引用与该模型相关的对象的方法非常有用.在下面的示例中,当调用$family-> members()时,我可以快速访问所有家庭成员.但是,这意味着我的家庭对象正在实例化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; }
依赖注入仅涉及注入依赖项.如果面向对象的设计导致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 } }
但是如果你考虑一下,家庭真的应该有责任创建会员吗?更好的设计是拥有另一个对象,例如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; } }
使用此模式,您的域对象及其方法(可能包含业务逻辑)将与您的数据访问代码分离.这是依赖注入的好处 – 它迫使你重新考虑你的OO设计,这样你最终会得到更清晰的代码.
许多人认为使用依赖注入意味着不使用工厂等.这是错的!依赖注入仅涉及注入依赖项.您也可以通过将依赖项注入工厂而不是让工厂实例化自己的依赖项来对工厂对象使用依赖项注入.
有用的链接:
> http://martinfowler.com/articles/injection.html
> Does anyone have a good analogy for dependency injection?
> How to explain dependency injection to a 5-year-old?
附加
再次,在这里拿下一粒盐.
另请注意,依赖注入和依赖注入容器之间存在差异.第一个是注入依赖项的简单概念,而不是让对象自己创建它(这导致非常高的耦合).我们从上面的例子中看到了这一点.
后者是处理依赖注入的框架/库的术语,因此您不必手动注入.容器的责任是布线依赖性,因此您不必进行肮脏的工作.我们的想法是定义一个依赖注入配置,它告诉容器Foo对象有哪些依赖关系,以及如何注入它们.容器读取文档并为您执行注射.这就是像Pimple,SimpleDIC这样的DIC库.
您可以将依赖注入容器与工厂进行比较,因为它们都是创建对象,其唯一的责任是创建对象.虽然工厂通常是专用的(即FamilyMemberFactory创建MemberInterface的实例),但依赖注入容器更为通用.有人说使用依赖注入容器可以减轻你对工厂的需求,但你应该记住,这意味着你必须创建和维护依赖注入配置文件,这可能是成千上万的XML / PHP行.
我希望这有帮助.