【问题标题】:How to dynamically call a function for the strategy pattern?如何动态调用策略模式的函数?
【发布时间】:2018-05-30 15:33:23
【问题描述】:

我正在使用 Razor Pages (MVVM) 在 .NET Core 中开发一个 Web 应用程序,用户可以在其中给我 4 个选项。

这些选项中的每一个都执行相同的操作,但在执行方面略有不同 - 这就是我想要实施策略模式的原因。

有没有办法以某种方式动态生成函数名?这可能是一个愚蠢的问题,但我只了解基础知识。

// option = A
// option = B
// option = C
// option = D

public async Task<IActionResult> OnPostAsync()
{

    ...

    var option = Input.Option // from model
    if(option == "A") {
        A.DoAlgorithm(input)
    } else if(option = "B") {
        B.DoAlgorithm(ïnput)
    } else if(option = "c") {
        C.DoAlgorithm(input) 
    } else {
        D.DoAlgorithm(input) 
    }

    ...
}

如果我这样做的话,感觉就像我错过了这个模式的要点,所以我的问题是:有没有办法根据输入选项动态调用函数?如果我为此使用了错误的模式,请纠正我。

【问题讨论】:

    标签: c# asp.net design-patterns


    【解决方案1】:

    尽管您可以遵循四人组策略模式的死记硬背,但现在有其他工具可以在不创建工厂的情况下做很多相同的事情,并且依赖于继承子类或实现接口的类的扩散,例如由于现在可以将函数用作变量,我们可以提供Actions 的映射以获取您的输入类型:

    public static readonly IDictionary<string, Action<InputType>> HandlerMap = 
        new Dictionary<string, Action<InputType>>
     {
        ["A"] = DoAlgorithmA,
        ["B"] = DoAlgorithmB,
        ["C"] = DoAlgorithmC,
        ["D"] = (input) => Console.WriteLine("Too simple to need a method")
        ...
     };
    

    其中InputType 是您的input 变量的类型,DoAlgorithmA 等只是接受InputType 的方法(如果方法真的很简洁,您甚至可以在这里使用 lambda),例如

    public static void DoAlgorithmA(InputType input)
    {
        ...
    }
    

    调用将如下所示:

    public async Task<IActionResult> OnPostAsync()
    {
        if (HandlerMap.TryGetValue(option, out var algorithm))
        {
             algorithm(input);
        }
        // .. else this isn't a valid option.
    }
    

    【讨论】:

    • 感谢您的回答。这似乎解决了我的问题,尽管下面的答案也是一个不错的选择。只是出于好奇,在推理和使用方面 - 为什么这个实现(没有设计模式)会比实际的更好?
    • 代码更少——GoF 策略是在 1990 年代制定的,当时函数式编程还没有真正流行。 Louis 有下面的香草模式,你可以看到你需要一个接口(或基/抽象类),每个算法的多个子类(通常只有一个方法),一个工厂(新建正确的实例)。通常你也会想抽象工厂,否则你只会用原始的东西结束,只是用工厂。从本质上讲,任何只有一个方法的interface 抽象都可以用委托/Func/Action 代替。保持简单:)
    • 因此,即结果保持不变,但您避免编写超出需要/必要的行数。谢谢你的解释。点赞! :)
    • 您显然可以增强/重构相当生硬的算法查找步骤,即将if (HandlerMap.TryGetValue(option, out var algorithm)) 移动到像FindMeTheAlgoForThisInput 这样的方法调用中,但您明白了。
    【解决方案2】:

    您可以使用基于所选选项创建策略的工厂,然后使用 A、B、C 和 D 扩展的基本策略类来执行算法的特定实例。

    伪代码:

    interface Strategy
    {
        void DoAlgorithm()
    }
    
    class A : Strategy
    {   
    }
    
    class B : Strategy
    {
    }
    
    abstract class Creator
    {
     public abstract Strategy FactoryMethod(string option);
    }
    
    class ConcreteCreator : Creator
    {
     public override Strategy FactoryMethod(string option)
     {
     switch (option)
     {
     case "A": return new A();
     case "B": return new B();
     default: throw new ArgumentException("Invalid type", "option");
     }
     }
    }
    

    【讨论】:

      猜你喜欢
      • 2011-06-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-09
      • 1970-01-01
      • 2013-05-23
      • 1970-01-01
      相关资源
      最近更新 更多