这是我第一次在StackOverflow上,我希望我的问题不是那么无聊!我从来没有真正尝试解决这个问题,我总是使用DI通过setter方法而不是构造函数,但现在是时候寻找一个更好的模式了!:)我试着执行一个搜索,但我不能得到任何满意的答案:(
基本上我有一个容器类,应该链接所有的依赖在一起,每一个类(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,如果它可以在一个干净和明智的方式。我不喜欢工厂!:)
提前感谢您的帮助!
是的,这是一个设计问题。
如果你想从你已有的代码中执行,你可以这样做:
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();