【问题标题】:Implementing "Fallback" Classes实现“后备”类
【发布时间】:2011-05-10 09:46:46
【问题描述】:

我有一组类,每个类都需要在某个时候决定它们应该在内部使用两种或三种方法中的哪一种来在外部实现相同的功能。理想情况下,这应该包括回退功能,如果 ApproachA 失败,它会尝试 ApproachB(可能会接近 C、D 等)。到目前为止,我一直在使用像if (!success) { ApproachB code } 这样的编码。这样做的问题是,后面的几个方法也需要知道选择了哪种方法,并且它们都开发了自己的 if (MethodChosen) { } else { } 语句。我真的很想用不那么笨拙的东西来解决这个问题……除了我考虑过的其他选择似乎都不是那么“笨拙”。以下是我想到的三种方法:

  1. 实现一个静态 .Create 方法,该方法决定创建两个派生类中的哪一个,这两个类有一个支持它们的接口。这样做的缺点是您两次编写了大量相同的代码,并且它并没有真正创建“回退”,因为它强制所有决策制定都在 .Create 方法中预先完成。这应该可以工作 9/10 次,但还有另外 1/10 次我希望只有在主节点尝试并失败时才会启动回退。
  2. 与上述相同,但涉及基类或抽象类,或者作为两者的支持类,或者将主类作为回退的基类。这具有相同的后备缺点,但至少很少或没有重复代码。
  3. 使用可以在运行时更改的子类实现一个正常构造的抽象类:即

    public void SomeMethodOrConstructor()
    {
        if (someConditions)
            MyChild = ChildClassA;
        else
            MyChild = ChildClassB;
    }
    
    
    public void Execute()
    {
        MyChild.Execute();
    }
    

选项 3 的问题是在需要时在两者之间传递数据。由于其中一些方法是对外部对象进行建模,因此这将相当频繁。嵌套类会自动与其父类共享数据吗?还是每次通话都必须全部通过?

还有什么我应该考虑的吗?


更新:第一个类已启动并使用责任链运行。目前,我选择在方法执行期间不使用策略模式或回退,因为我相信最终可能没有必要。我认为大多数此类执行后备实际上会更好地留在他们自己的类中,因为不会完全改变游戏计划,只需处理一些小的调整。如果事实并非如此,我至少知道我现在需要调查什么。

感谢所有帮助提供最终解决方案的人!

出于好奇,我的最终解决方案大致如下:

  • 创建 Handler 抽象类,与 Wikipedia 文章中概述的非常相似,但带有 public abstract Handler GetHandler() 函数,并添加了其他抽象方法,如 Load、Save 等。
  • 为父类实现私有处理程序子类(它们也可能是子类,因为它们只会为特定类处理事情......也避免了以后的命名问题)。子类都在其构造函数中采用父对象类型的参数,因此它们可以轻松访问父对象的数据。
  • 从父类的构造函数中,设置责任链处理程序/继任者(再次,就像示例一样),然后调用 FirstHandler.GetHandler(this) 并存储结果,以便类知道将来使用哪个处理程序。
  • 大多数处理的方法然后简单地减少到Handler.MethodName()

【问题讨论】:

  • 您可以通过使用 8 个 空格缩进将代码放入编号列表中。
  • 感谢您提供的格式提示,这让我很难受!

标签: c# modeling


【解决方案1】:

使用Chain of Responsibility

责任链模式是一种 由源组成的设计模式 命令对象和一系列 处理对象。每次加工 对象包含一组逻辑 描述命令对象的类型 它可以处理,以及如何假冒 那些它无法处理的 链中的下一个处理对象。一种 还存在添加新的机制 处理对象到此结束 链。

这完全符合您需要做的事情。

【讨论】:

  • 今天下午我会玩它,但我很确定这就是我正在寻找的答案!
  • 有什么,请大声喊叫。
  • 关于如何在后期调用方面实现这一点的任何提示?为了将我的具体情况放到一个更通用的示例中,假设我有一个 Load 和 Save 方法,其中 Load 处理 XML 或 TXT 文件。 Save 不需要“重新计算”,Load 已经确定了它正在处理的内容。我在想父类只需要一个 Handler 属性来指示最终处理事件的处理程序,但我不确定如何最好地实现它。
  • 我同意,您只需要一个负责加载的责任链 - save 已经知道格式,因此策略模式可以工作。有一个工厂来发回一个 IHandler 列表,实现 IHandler 的对象,你调用 Handle 并返回结果,如果为 false,你继续更改,直到找到一个或最后一个异常。
  • 我认为你是对的......现在我只需要全神贯注。我是一名 DBA,最近一直在做大量的 VB6/VBA,所以在很多编程模式和范例方面我都落后了。感谢您的帮助!
【解决方案2】:

我认为你需要Task/Task<T>,尤其是ContinueWith(Action<Task>)方法和4个属性:IsCanceled,IsCompleted,IsFaultedResult

【讨论】:

    【解决方案3】:

    我可能会在这里使用策略模式。

    http://en.wikipedia.org/wiki/Strategy_pattern

    您只需要传递委托而不是整个类。如果所有方法都使用相同的信息进行处理,这可能会有所帮助。

    【讨论】:

    • 这也是一个很好的解决方案,但如果我理解正确,它不会有我正在寻找的失败行为。
    • 看来您的策略模式终于开始发挥作用了。 :) 谢谢!
    猜你喜欢
    • 2015-02-28
    • 2023-03-09
    • 1970-01-01
    • 2021-07-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-06
    相关资源
    最近更新 更多