【问题标题】:Is it ok to put methods/fields to base class that will only be used by some of the derived classes是否可以将方法/字段放入仅由某些派生类使用的基类
【发布时间】:2015-04-01 04:20:13
【问题描述】:

这是一个通用的软件设计问题。假设您有一个基类和许多从它派生的类(大约 10 个)。

一些类之间共享一些通用功能(3-4 个派生类需要它)。基本上是一个 UI 控件的字段,一个创建 UI 控件的抽象方法和使用抽象方法回收 UI 块的通用代码(8-9 行代码)使用抽象方法。像这样的:

class BaseClass {
    ...

    protected UIControl control;

    protected abstract UIControl CreateUI();

    protected void RecycleUI() {
        if (/* some condition is met */) {
            if (this.control != null) {
                control.Dispose();
            }
            this.control = this.CreateUI();
            this.AddToUITree(control);
        }
    }

    ...
}

你认为把它放到基类中而不是在派生类中复制代码可以吗?

缺点是这段代码只用于一些基类,与其他类完全无关。

另一种方法是创建一个派生自 BaseClass 的中间类,并将其用作需要该功能的类的基础。我觉得为特定目的的几行代码创建派生类感觉很沉重。感觉不值得为此中断继承树。我们尝试使层次结构尽可能简单,以便易于遵循和理解继承树。也许如果这是 C++ 中可以选择多重继承,这不会是一个大问题,但多重继承不可用。

另一种选择是创建一个实用方法和一个接口来创建/更新 UI 控件:

interface UIContainer {
    UIControl CreateUIControl();

    UIControl GetUIControl();

    void SetUIControl(UIControl control);
}

class UIControlUtil {
    public void RecycleUI(UIContainer container) {
        if (/* some condition is met */) {
            if (container.GetUIControl() != null) {
                container.GetUIControl().Dispose();
            }
            UIControl control = container.CreateUI();
            container.SetUIControl(control);
            container.AddToUITree(control);
        }
    }
}

我不喜欢这个选项,因为它会从外部泄露 UI 逻辑,这不太安全,因为它的 UI 状态可以在外部进行操作。派生类现在也必须实现 getter/setter。一个优点是在上述继承树之外还有另一个类,它需要这个功能,它也可以使用这个实用函数。

您还有其他建议吗?我是不是应该抑制我内心酝酿的不重复公共代码的冲动?

【问题讨论】:

    标签: class inheritance architecture software-design


    【解决方案1】:

    另一种方法是创建一个派生自的中间类 BaseClass 并将其用作需要 功能。

    嗯,这是我认为最合适的。但这取决于。这里的主要问题如下:对象是否需要 UI 回收并且与那些不需要回收的对象真的不同?如果它们真的不同,你必须为它们创建一个新的基类。如果差异真的可以忽略不计,我认为将东西留在基类中是可以的。

    不要忘记LSP

    我们尝试使层次结构尽可能简单,以便于使用 遵循和理解继承树

    我认为这里更重要的是让事情不仅简单,而且要接近现实世界的事物,这样新实体的建模就会很容易。现在看起来轻松,将来可能会引起真正的麻烦。

    【讨论】:

    • > 是对象,需要 UI 回收,并且与那些真正不同,不需要?除了这种 UI 回收之外,它们并没有太大的不同。他们没有这样的功能。我最终暂时保留了复制代码,主要是因为逻辑本身非常简单,而且很可能不需要维护。不过,关于 LSP 的观点很好。
    • @nrydn 很高兴你解决了这个问题;)谢谢你的好问题。
    猜你喜欢
    • 2020-10-21
    • 2014-04-30
    • 1970-01-01
    • 2020-03-24
    • 2013-08-16
    • 1970-01-01
    • 2011-09-11
    • 2021-08-14
    • 1970-01-01
    相关资源
    最近更新 更多