我在某人的代码中看到了这一点并想到了哇,这是解决这一特定问题的一种优雅方式,但它可能以史诗般的方式违反了良好的OO原则。
在一组全部派生自公共基类的类的构造函数中,他需要引用要传递的实例化类。例如,
Foo Foo_i = new(this);
然后在Foo上调用实例化类中的方法来获取有关自身和实例化类所包含的其他对象的信息。
一方面,这简化了在硬件中模拟5层树结构的代码的TON(代理插入多个交换机上的端口等)。另一方面,这些物体彼此紧密耦合的方式似乎非常错误,但我不太了解OOA& D将我的手指放在它上面。
那么,这没关系吗?或者这是否等同于goto语句?
答案 0 :(得分:5)
你应该尽量避免相互引用(特别是在实施遏制时),但往往无法避免。即父子关系 - 孩子经常需要知道父母并在发生某些事件时通知父母。如果你真的需要那样做 - 选择接口(或者在C ++的情况下抽象类)。 所以你的实例化类应该实现一些接口,并且instanciated类应该只知道它作为接口 - 这将显着减少耦合。在某些方面,这种方法类似于嵌套的侦听器类,因为它只暴露了类的一部分,但它更容易维护。这是一个小C#示例:
interface IParent
{
//some methods here
}
class Child
{
// child will know parent (instancing class) as interface only
private readonly IParent parent_;
public Child(IParent parent)
{
parent_ = parent;
}
}
class Parent : IParent
{
// IParent implementation and other methods here
}
答案 1 :(得分:3)
这听起来可能违反了Law of Demeter,这取决于Foo需要知道在实例课程中钓鱼的程度。物体应该优选地松散地耦合。你宁愿没有一个班级需要知道很多关于另一个班级的结构。我听过几次的一个例子就是你不会把你的钱包递给店员,让他在里面钓鱼。你的钱包是你的生意,你会找到你需要的东西给职员并交给你自己。你可以重组你的钱包,没有人会更聪明。松耦合使测试更容易。理想情况下,Foo应该是可测试的,而不需要维护复杂的上下文。
答案 2 :(得分:2)
如果我可以从信息隐藏的角度来看,我会尽量避免这种情况。一个类拥有或需要的信息越少,测试和验证就越容易。话虽这么说,它确实在某些情况下会导致更优雅的解决方案,所以如果不这样做是非常令人费解的涉及大量的参数传递然后通过各种手段去做。
例如,Java在内部类中使用了很多:public class Outer {
private class Inner {
public Inner() {
// has access to the members of Outer for the instance that instantiated it
}
}
}
答案 3 :(得分:1)
在Java中,我记得通过在我的控制器中继承某些监听器和适配器并将这些监听器和适配器添加到我的子类来避免这种情况。
换句话说,我的控制器是
class p {
private member x
private methods
private class q {
// methods referencing p's private members and methods
}
x.setListener(new q());
}
我认为这是松散耦合的,但我还想要一些确认。
答案 4 :(得分:1)
在某些情况下,这种设计模式很有意义。例如,迭代器总是与特定集合相关联,因此迭代器的构造函数需要集合才有意义。
你没有提供具体的例子,但如果班级提醒你goto
,那可能是个坏主意。
您说新对象必须询问实例化对象以获取信息。也许班级对其环境做了太多假设?如果这些假设使单元测试,调试或(非假设的)代码重用变得复杂,那么您应该考虑重构。
但如果设计可以节省整个开发人员的时间,并且你不会期望在两年内有一个难以维护的野兽,那么从实际的角度来看,这种做法是完全可以接受的。