设计模式在C#中基于多个输入处理动作

时间:2017-12-09 04:39:19

标签: c# design-patterns

假设商业模式中有两个属性,例如国家和类型,我们需要为每个国家和每种类型处理不同的逻辑。

if(country=="us"){
    if(type=="type1){
        usType1Handler.Execute();
    }
    else if(type=="type2"){
        usType2Handler.Execute();
    }
    .
    .
    .
    else{
        usDefaultHandler.Execute();
    }
}
else if(country=="uk"){
    if(type=="type1){
        ukType1Handler.Execute();
    }
    else if(type=="type2"){
        ukType2Handler.Execute();
    }
    .
    .
    .
    else{
        ukDefaultHandler.Execute();
    }
}
else{
    throw exception("unknown country");
}

将有很多if混合和匹配特定于每个国家/地区类型组合的每个实现。我们可以使用任何设计模式来处理这种情况吗?

5 个答案:

答案 0 :(得分:0)

我建议在这个例子中使用嵌套开关:

switch (country)
{
    case "us":
        switch (type)
        {
            case "type1":
                usType1Handler.Execute();
                break;
            case "type2":
                usType2Handler.Execute();
                break;
            default:
                break;
        }
        break;
    case "uk":
        switch (type)
        {
            case "type1":
                ukType1Handler.Execute();
                break;
            case "type2":
                ukType2Handler.Execute();
                break;
            default:
                break;
        }
        break;
}

答案 1 :(得分:0)

您可以使用两种模式的组合来改善这种情况Chain of Responsibility&& Strategy Pattern

  1. Strategy Pattern - 这种模式将帮助您解决国家的条件问题。您必须为我们系统中的每个国家/地区制作AbstractCountryStrategy +具体Strategy课程。
  2. Strategy类将包含一个非常简单的代码行(使用其他模式的行Chain of Responsibility

    class USCountryStrategy {
    
        public void execute(type) {
            new USCountryTypeAHandler()
                  .setNext(new USCountryTypeBHandler()
                  .setNext(...))
               .executeBasedOn(type)
        }
    }
    
    1. Chain of Responsibility - 这个模式将帮助你解决类型的条件(但是你仍然需要使用一个小的if / else来判断你的当前处理程序是否附加了下一个处理程序)
    2. 总体构思:对于每种类型,您都会有一个小班,检查它是否能够解决您的请求......类似于:

      if(paramType.equals(this.type)
          this.execute();
          // if I can solve your request than I'll execute it myself
      else if(this.next) 
          this.next.executeBasedOn(paramType);
          // if I can't solve your request than I'll pass it on to the next handler
      else 
          throw RuntimeException(...)
          // nobody can solve your request (because I can't && this.next is null)
      

      这是有用的还是我只是为我的代码源增加了复杂性?

      是的,当您切换代码时它很有用,请记住,您很快就必须更改此功能/类。交换机不可扩展,难以维护,速度非常快(“意大利面条代码”),您可能需要在代码库中使用它两次。

      有关更好和更好的信息,请参阅https://github.com/kamranahmedse/design-patterns-for-humans完整的例子。

答案 2 :(得分:0)

您的用例非常适合策略+工厂模式实施。您应该有工厂来移出处理程序的实例化部分。正如您所看到的,我们还没有废除if-else块,而只是将它们移动到更易于管理的类中。毫无疑问,它增加了类的数量,但是这有助于您使代码可扩展,并且从长远来看可以减少错误。您可以根据需要添加任意数量的国家/地区,而无需触及现有代码。这可确保您不会在现有功能中引入错误。此外,如果你想要你可以让工厂返回CountryFactory,这将更好。这样,无论您将来有多少国家/地区和类型,您的“YourExecutingClass”始终保持不变。

{% extends 'layout.html.twig' %}
{% block content %}         

   {% for content in contents %}     

       // here you have access to a singular content object

    {% endfor %} 

{% block content %} 

答案 3 :(得分:0)

这很简单。只需将所有处理程序添加到字典中,其中键是Country / Type组合,值是处理函数。

创建字典并添加所有处理程序:

Dictionary<string, Handler> processor = new Dictionary<string, Handler>()
{
    { "us,type1", usType1Handler },
    { "us,type2", usType2Handler },
    { "us", usDefaultType2Handler },
    { "uk,type1", ukType1Handler },
}
//...etc

然后,只需搜索字典并执行:

string key = String.Join(",", new[] { country, type })
bool success = processor.TryGetValue(key, out Handler handler);
if (success)
{
    handler.Execute();
}
else
{
    throw new Exception("unknown country");
}

答案 4 :(得分:0)

这里关键字是 execute(),它有no_countries X no_types变种数。要使用OO方法,您必须将这些组合分配到不同的类中。以大量具体课程为代价,您可以购买可扩展的解决方案。

  1. 使用策略:有人必须持有/创建这些策略并在需要时提供。如果策略不是国家/地区类型组合的唯一,那么您可以节省变化。当没有状态变化时,策略通常很有用。

  2. 责任链 - 此处的变体将由处理程序处理。处理程序必须决定它是否可以处理给定的情况(可能基于国家类型的组合),但如果变体可以处理多个组合,那么你将在处理程序中获得小的if。

  3. 两者都可以延期,但不可避免。