c# - 在 OOP 中覆盖方法与分配方法委托(delegate)/事件

标签 c# oop design-patterns abstract-class first-class-functions

这是一个有点奇怪的 oop 问题。我想创建一组对象(在设计时已知),每个对象都有与之关联的某些功能。 我可以通过为我的对象提供可以包含“代表”的属性来做到这一点:

public class StateTransition {
    Func<bool> Condition { get; set; }
    Action ActionToTake { get; set; }
    Func<bool> VerifyActionWorked { get; set; }
}

StateTransition foo = new StateTransition {
    Condition = () => {//...}
    // etc
};

或者,我可以使用一个抽象类并为我想创建的每个对象实现它:

public abstract class StateTransition {
    public abstract bool Condition();
    public abstract void ActionToTake();
    public abstract bool VerifyActionWorked();
}

class Foo : StateTransition {
    public override bool Condition() {//...}
    // etc
}

Foo f = new Foo();

我意识到这两种方法的实际结果(在设计时创建与运行时创建)完全不同。

如何选择适合我应用的方法?

最佳答案

第一种方法看起来比原始委托(delegate)更适合事件,但是......无论如何。

他们之间的关键因素是:谁控制发生的事情

如果调用者可以在那里合法地做任何事情,那么事件方法就可以了。毕竟,系统不会强制您继承 Button 只是为了添加单击它时发生的事情(尽管您可以那样做)。

如果“可能发生的事情”得到很好的控制,并且您不希望每个调用者 做不同的事情,那么子类方法更合适。这也避免了每个调用者都需要必须告诉它做什么,而“要做的事情”实际上可能只有很少的几个选项。基类型方法提供了控制子类的能力,例如,通过在基类上仅具有internal 构造函数(以便仅在同一程序集中键入,或在通过 [InternalsVisibleTo(...)] 注释的程序集中,可以将其子类化)。

您还可以通过以下方式将两者结合起来(覆盖与事件):

public class StateTransition {
    public event Func<bool> Condition;
    protected virtual bool OnCondition() {
        var handler = Condition;
        return handler == null ? false : handler();
    }
    public event Action ActionToTake;
    protected virtual void OnActionToTake() {
        var handler = ActionToTake;
        if(handler != null) handler();
    }
    public event Func<bool> VerifyActionWorked;
    protected virtual bool OnVerifyActionWorked() {
        var handler = VerifyActionWorked;
        return handler == null ? true : handler();
    }
    // TODO: think about default return values
}

委托(delegate)/事件方法要考虑的另一件事是:如果委托(delegate)为 null,您会怎么做?如果您需要全部 3 个,那么在构造函数中要求全部 3 个是个好主意。

关于c# - 在 OOP 中覆盖方法与分配方法委托(delegate)/事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14253099/

相关文章:

java - 将值从 A 类返回到 B 类,然后返回到 Main 类?

delphi - 是否可以在 delphi 类上定义虚拟静态成员?

language-agnostic - 函数式编程 : state vs. 重新赋值

关于数据封装的C#设计问题

c# - OleDbCommand 不会更新 MS Access 数据库,不会抛出任何错误

c# - .NET 字典 : Potential concurrency problems?

C# 或 F# 用于解析类似 Slim 的缩进敏感语言?

c# - 从 lambda 表达式中的函数调用获取返回值

design-patterns - 具有实体树的域聚合根

java - 在不违反 SOLID 原则的情况下使用具有不同方法名称的子类