这是我第一次使用StackOverflow,我希望我的问题不是那个noobish!我从来没有真正试图解决这个问题,我总是通过setter方法而不是构造函数来代替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,反之亦然。
P.S。我想尝试使用DI解决这个问题,如果它可以以干净和明智的方式完成。我不是工厂的粉丝! :)
提前感谢您的帮助!
答案 0 :(得分:2)
是的,这是一个设计问题。
如果你想从你已有的代码中做到这一点,你可以这样做:
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();