C#,模式 - 许多条件

问题描述 投票:0回答:6

我正在寻找解决我的问题的好模式。

我有一些布尔变量:

condition1
condition2
condition3

我还有一些操作,它们在类中的不同位置调用:

action1
action2
action3

当条件 1 和 2 为真时,会调用

action1

当条件 2 和 3 为真时,会调用
action2

action3
当所有条件都为真时被调用。

当然这只是问题的简化。我不想在每个地方都使用 if else 。非常不清楚。

我一直在考虑状态,但我想这不是这个问题的最佳解决方案。

c# design-patterns pattern-matching conditional-statements
6个回答
12
投票

一种选择是将条件逻辑包装在基类中,然后从中派生以执行实际操作。这是 Command 模式和(我认为)Strategy 模式的变体:

class ActionState
{
  public bool Condition1{get;set;}
  public bool Condition2{get;set;}
  public bool Condition3{get;set;}
}

abstract class ActionDispatcher
{
  protected abstract void ExecuteAction1();
  protected abstract void ExecuteAction2();
  protected abstract void ExecuteAction2();

  public void Action1(ActionState state)
  {
    if(state.Condition1 && state.Condition2)
    {
      ExecuteAction1();
    }
  }

  public void Action2(ActionState state)
  {
    if(state.Condition2 && state.Condition3)
    {
      ExecuteAction2();
    }
  }

  public void Action3(ActionState state)
  {
    if(state.Condition1 && state.Condition2 && state.Condition3)
    {
      ExecuteAction3();
    }
  }

  public void AllActions(ActionState state)
  {
    // Execute all actions depending on the state
    Action1(state);
    Action2(state);
    Action3(state);
  }
}

3
投票

带有

enum
属性的
[Flags]
可能会对您有所帮助,而不是单独的布尔值。请参阅这个答案以获得非常好的解释+示例。


1
投票

你的条件没有被很好地定义,但它听起来像是一张状态到动作的映射,其中一个状态是由许多简单的条件定义的,每个状态只有一个动作。那么为什么不实际这样表示呢?

这是一个简单的 LinqPad 示例:

void Main()
{   
    Dictionary<Cond, Action> d = new Dictionary<Cond, Action>()  
    {
        { new Cond(waterproof:true, shockproof:true, freezeproof:false), delegate() { "Action1".Dump(); } },
        { new Cond(waterproof:false, shockproof:true, freezeproof:true), delegate() { "Action2".Dump(); } },
        { new Cond(waterproof:true, shockproof:true, freezeproof:true), delegate() { "Action3".Dump(); } }
    };

    d[new Cond(true, true, false)]();
    d[new Cond(false, true, true)]();
    d[new Cond(true, true, true)]();
}

public class Cond : Tuple<bool, bool, bool>
{
    public Cond(bool waterproof, bool shockproof, bool freezeproof) : base(waterproof, shockproof, freezeproof)
    {
    }
}

输出:

Action1
Action2
Action3

Tuple<>
的子类是因为:

  1. 它使所有内容都更具可读性,而不是到处都有通用参数。

  2. 您可以像我一样使用命名参数,使地图逻辑非常清晰。

  3. 如果您需要更复杂的逻辑,例如每个状态中有不同数量的条件,您可以将其替换为自定义类。

在这种情况下,您可能需要覆盖

Equals
GetHashCode

(您显然不需要使用匿名委托;您只需传递对您要使用的方法的直接引用即可)


0
投票

您可以实现访客模式。但这取决于你的抽象水平和你的功能 访客模式实现示例


0
投票

有一种方法可以在没有任何 if 子句的情况下实现它。

您可以将此布尔值转换为整数,这样您就可以在字典中获取该方法,例如:

cond1 = false, cond2 = true, cond3 = false

您可以将其转换为:

0 + 1 + 0
= 1

然后,您将为您拥有的每个解决方案创建一个密钥,如下所示:

public Class Action1: IAction;
public Class Action2: IAction;
public Class Action3: IAction;

Dictionary<int, IAction> dict = new Dictionary<int, IAction>()
{
    6, new Action1(); //110
    3, new Action2(); //011
    7, new Action3(); //111
};

IAction 界面:

public interface IAction
{
    void execute();
}

在具体类的每个方法

execute()
中,您将实现每个操作。

然后您只需执行您的操作:

key = //transform binary in decimal
dict[key].execute();

希望这有帮助。


-1
投票

这可能是一个扩展方法:

public static void WhenTrue(this bool condition, Action action)
{
    if (action == null)
        throw new ArgumentNullException("action");

    if (condition)
        action();
}

用途:

(condition1 && condition2).WhenTrue(() => DoSomeWork(param1));

但是,只有当您有很多条件和很多操作来保持代码整洁时,这才有意义。

© www.soinside.com 2019 - 2024. All rights reserved.