这个组合是否违反了面向对象编程的任何原则?

3

假设我有以下两个类:

public class MyDevice
{
    int id;
    string name;
    // other resources

    public MyChannel CreateChannel()
    {
        return new MyChannel(this);
    }
} 

public class MyChannel
{
    int id;
    MyDevice _device;
    // other resources        

    public MyChannel(MyDevice device)
    {
        _device = device;
    }
}

实际上,每个设备都可以拥有不同数量的通道。因此,每个设备都有一个通道集合。让我感到困扰的是,代码中的 MyChannel 对象拥有一个 MyDevice 对象。然而,代码中定义的关系更为方便,我也希望保持简单。
为了平息我内心的疑虑,我一直指向 SqlConnectionSqlCommand 的结构,其中每个 SqlCommand 对象都拥有一个 SqlConnection 对象,尽管每个 SQL 连接都拥有一系列 SQL 命令。
我是否违反了面向对象编程的任何原则/这段代码是否存在问题?
明确地说,将 has-a 关系颠倒过来在面向对象设计方面是否是大忌?如果是,哪个原则被忽视或忽略了?

3
我认为这个问题不适合放在SO上讨论。 - rory.ap
5
这似乎是一些示例代码,与Code Review的主题不符,因为在Code Review上合适并不代表在Stack Overflow上也合适。在Code Review上合适并不会成为一个关闭理由。如果你认为这个问题违反了Stack Overflow帮助中心中定义的规定而不适合发布在该网站上,请投票选择关闭该问题。 - Simon Forsberg
7
这不是一个编程问题吗?在我看来完全符合主题。将这些问题分配到其他堆栈交换站点只会让程序员更难找到答案 - 这是该网站的最初意图。 - BlueRebel
2
问题已定义并给出了适当的范围。成员正在寻求具体指导。它不是开放式的,也不是关于“什么构成良好组合规则”的含义,它给出了非常具体的例子。是的,我们正在进行讨论,但它是关于问题的有效性,而不是问题本身。我们已经进入了元层。 - BlueRebel
2
我理解你的观点并撤回我的论点。 - rory.ap
显示剩余5条评论
3个回答

3
我猜想这个例子中的Device应该是指MyDevice。你基本上有一个对通道父级即设备的引用。我不认为这会破坏面向对象编程,在许多情况下也很有用。纯粹主义者会说这破坏了父级的封装性,并且从通道到任何通道外部的东西以及更远处都会产生耦合。

我非常喜欢将一个引用添加到父对象的方法。我一直在思考.NET框架中使用这种方法的情况 - 到目前为止,我主要考虑了ADO.NET数据提供程序对象,但是在WinForms API中,将引用添加到所有者/父对象中被广泛使用。 - Derek W
1
如果您曾经使用过树形控件,那么从节点到其父节点的引用非常有用,可以迭代回树形结构,例如查找根节点。 - Tim Rutter

2

这并没有违反任何原则。您经常会有包含其他对象的对象。

我猜您是想让MyChannel._device字段实际上成为一个MyDevice?

此外,如果需要双向遍历,您可能希望在MyDevice对象内部拥有一个MyChannel对象列表。只需确保在两个字段之间强制执行一致性即可。


2

我认为这种模式原则上没有任何问题。有时候,存在两个紧密耦合的类是完全正常的。

但是,我认为你应该将你的通道类设为私有,并且只能使用CreateChannel方法实例化它,同时在你的设备类中添加一个私有的通道对象集合作为成员,并提供一个公共的getter但没有公共的setter。这样,你就可以确保你的设备类始终掌控着自己的通道。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接