【问题标题】:getting rid of constructor circular dependency摆脱构造函数循环依赖
【发布时间】:2014-06-09 20:05:47
【问题描述】:

这是我第一次使用 StackOverflow,我希望我的问题不是那么无聊!我从来没有真正尝试过解决这个问题,我总是通过 setters 方法而不是构造函数来使用 DI,但现在是时候寻找更好的模式了! :) 我尝试进行搜索,但没有得到任何令人满意的答案:(

基本上我有一个容器类,它应该将所有依赖项链接在一起,并且这些类中的每一个(A、B、...)也应该能够从“它们的内部”访问容器中的其他类.

<?php

class MyContainer
{
    function __construct(A $a, B $b){
        $this->a = $a;
        $this->b = $b;
    }

    function getA(){ return $this->a; }
    function getB(){ return $this->b; }
}

class A
{
    function __construct(MyContainer $myc){ $this->myc = $myc; }
    function useA(){ echo "A"; $this->myc->getB()->doSmt(); }
    function doSmt(){ echo "A smt"; }
}

class B
{
    function __construct(MyContainer $myc){ $this->myc = $myc; }
    function useB(){ echo "B"; $this->myc->getA()->doSmt(); }
    function doSmt(){ echo "B smt"; }
}

?>

现在无法实例化,因为 MYC 需要 A 和 B,而 A 和 B 需要 MYC。

我该如何解决这个问题?我的教授告诉我,当您遇到循环依赖时,很可能是设计问题。但我不知道如何正确地做到这一点:A 和 B 的存在实际上取决于 MyCollection,反之亦然。

附:我想尝试使用 DI 来解决这个问题,如果它可以以干净和明智的方式完成的话。我不是工厂的粉丝! :)

提前感谢您的帮助!

【问题讨论】:

    标签: php oop design-patterns circular-dependency circular-reference


    【解决方案1】:

    是的,这是一个设计问题。

    如果您想从已有的代码中执行此操作,您可以这样做:

    class MyContainer
    {
        function __construct(A $a, B $b){
            $a->setContainer($this);
            $b->setContainer($this);
            $this->a = $a;
            $this->b = $b;
        }
    
        function getA(){ return $this->a; }
        function getB(){ return $this->b; }
    }
    
    class A
    {
        function setContainer(MyContainer $myc){ $this->myc = $myc; }
        function useA(){ echo "A: "; $this->myc->getB()->doSmt();echo "<br />"; }
        function doSmt(){ echo "A smt<br />"; }
    }
    
    class B
    {
        function setContainer(MyContainer $myc){ $this->myc = $myc; }
        function useB(){ echo "B: "; $this->myc->getA()->doSmt();echo "<br />"; }
        function doSmt(){ echo "B smt<br />"; }
    }
    

    但我认为这不是一个好方法。

    你到底想做什么?

    也许观察者模式可以解决您的特定问题?

    <?php
    interface IObserver {
        function doSmt();
    }
    class Notifier{
        private $_observers = array();
        function register(IObserver $observer) {
            $this->_observers[] = $observer;
        }
        function notify() {
            foreach($this->_observers AS $observer) {
                $observer->doSmt();
            }
        }
    }
    
    class A implements IObserver {
        function doSmt() {
            echo "A smt<br />";
        }
    }
    class B implements IObserver {
        function doSmt() {
            echo "B smt<br />";
        }
    }
    
    
    $a = new A();
    $b = new B();
    
    $notifier = new Notifier();
    $notifier->register($a);
    $notifier->register($b);
    
    $notifier->notify();
    

    现在您还可以按照注册观察者的顺序更改调用顺序。 或者,如果您想在通知之前对其进行排序。这取决于你。

    如果您能提供更多信息或预期的输出,那就太好了。

    因为我尝试了我给你的第一种代码方法(基于你的代码):

    $a = new A();
    $b = new B();
    
    $container = new MyContainer($a, $b);
    $container->getA()->useA();
    $container->getB()->useB();
    

    $a = new A();
    $b = new B();
    
    $container = new MyContainer($a, $b);
    $container->getA()->doSmt();
    $container->getB()->doSmt();
    

    【讨论】:

    • 您好,感谢您的回答! A 类必须能够从其中调用 B 方法,反之亦然。明天我将在问题中添加更多信息!现在谢谢:)
    • 好的,但是第一个代码块是如何根据您的代码实现这一点:) 但是您应该真正抽象出两个类(classX)的共同因素并将它们放在一个新类中或者其他的东西。然后让它们都依赖于 classX。因为我不明白你想要达到什么目的。我现在真的不能帮助你更多:)
    • 但是你真的应该重构你的代码并抽象出共同因素*
    猜你喜欢
    • 1970-01-01
    • 2011-04-08
    • 2019-04-22
    • 1970-01-01
    • 2015-08-30
    • 2017-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多