Oop 拥有一个需要引用实例化对象的类是一种不好的做法吗?

Oop 拥有一个需要引用实例化对象的类是一种不好的做法吗?,oop,Oop,我在某人的代码中看到了这一点,并认为哇,这是解决这个特殊问题的一种优雅方式,但它可能以史诗般的方式违反了良好的OO原则 在所有派生自公共基类的一组类的构造函数中,他需要传递对实例类的引用。例如, Foo Foo_i=新(本) 随后,Foo将调用实例化类中的方法,以获取有关自身和实例化类包含的其他对象的信息 一方面,这简化了大量在硬件中建模5层树结构的代码(代理插入多个交换机上的端口等)。另一方面,这些对象以一种似乎非常错误的方式彼此紧密耦合,但我对OOA&D的了解还不够,无法对其进行深入研究 那

我在某人的代码中看到了这一点,并认为哇,这是解决这个特殊问题的一种优雅方式,但它可能以史诗般的方式违反了良好的OO原则

在所有派生自公共基类的一组类的构造函数中,他需要传递对实例类的引用。例如,
Foo Foo_i=新(本)

随后,Foo将调用实例化类中的方法,以获取有关自身和实例化类包含的其他对象的信息

一方面,这简化了大量在硬件中建模5层树结构的代码(代理插入多个交换机上的端口等)。另一方面,这些对象以一种似乎非常错误的方式彼此紧密耦合,但我对OOA&D的了解还不够,无法对其进行深入研究


那么,这样可以吗?或者这是等同于goto语句的OO吗?

如果从信息隐藏的角度看,我会尽量避免这种情况。类拥有或需要的信息越少,测试和验证就越容易。这就是说,在某些情况下,它确实会导致更优雅的解决方案,因此,如果不这样做,涉及到大量的参数传递,那么就要千方百计地去做

例如,Java在内部类中经常使用这一点:

public class Outer {
  private class Inner {
    public Inner() {
      // has access to the members of Outer for the instance that instantiated it
    }
  }
}

在Java中,我记得曾经通过在我的控制器中对某些侦听器和适配器进行子类化并将这些侦听器和适配器添加到我的子类中来避免这种情况

换句话说,我的控制器是

class p {

  private member x

  private methods

  private class q {
    // methods referencing p's private members and methods
  }

  x.setListener(new q());

}

我认为这是一种松散耦合,但我也希望得到一些确认。

这种设计模式在某些情况下很有意义。例如,迭代器总是与特定集合相关联,因此迭代器的构造函数需要集合是有意义的

您没有提供具体的示例,但是如果该类提醒您“转到”,那么这可能是个坏主意

您说过新对象必须询问实例化对象以获取信息。也许这个类对它的环境做了太多的假设?如果这些假设使单元测试、调试或(非假设的)代码重用复杂化,那么就应该考虑重构。
但是,如果该设计总体上节省了开发人员的时间,并且您不希望在两年内出现无法维护的beast,那么从实践的角度来看,这种做法是完全可以接受的。

这听起来可能违反了规范,这取决于Foo需要知道多少才能在实例化类中进行搜索。对象最好是松散耦合的。你不希望有一个类,你需要知道很多关于另一个类的结构。我听过好几次的一个例子是,你不会把钱包交给店员,让他在里面钓鱼。你的钱包是你的事,你会找到你需要给店员的东西,然后自己交给他。你可以重新整理你的钱包,没有人会更聪明。更松的耦合使测试更容易。理想情况下,Foo应该是可测试的,而不需要维护复杂的上下文。

您应该尽量避免相互引用(特别是在实现包含时),但通常它们是无法避免的。即亲子关系-孩子通常需要了解父母,并在发生某些事件时通知父母。如果您真的需要这样做,请选择接口(或者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
}

我从来没有听说过这是一种不好的做法,在某些情况下,这很方便。