我正在寻找解决我的问题的好模式。
我有一些布尔变量:
condition1
、condition2
、condition3
。
我还有一些操作,它们在类中的不同位置调用:
action1
、action2
、action3
当条件 1 和 2 为真时,会调用 action1
。action2
。action3
当所有条件都为真时被调用。
当然这只是问题的简化。我不想在每个地方都使用 if else 。非常不清楚。
我一直在考虑状态,但我想这不是这个问题的最佳解决方案。
一种选择是将条件逻辑包装在基类中,然后从中派生以执行实际操作。这是 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);
}
}
你的条件没有被很好地定义,但它听起来像是一张状态到动作的映射,其中一个状态是由许多简单的条件定义的,每个状态只有一个动作。那么为什么不实际这样表示呢?
这是一个简单的 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<>
的子类是因为:
它使所有内容都更具可读性,而不是到处都有通用参数。
您可以像我一样使用命名参数,使地图逻辑非常清晰。
如果您需要更复杂的逻辑,例如每个状态中有不同数量的条件,您可以将其替换为自定义类。
在这种情况下,您可能需要覆盖
Equals
和 GetHashCode
。
(您显然不需要使用匿名委托;您只需传递对您要使用的方法的直接引用即可)
您可以实现访客模式。但这取决于你的抽象水平和你的功能 访客模式实现示例
有一种方法可以在没有任何 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();
希望这有帮助。
这可能是一个扩展方法:
public static void WhenTrue(this bool condition, Action action)
{
if (action == null)
throw new ArgumentNullException("action");
if (condition)
action();
}
用途:
(condition1 && condition2).WhenTrue(() => DoSomeWork(param1));
但是,只有当您有很多条件和很多操作来保持代码整洁时,这才有意义。