我更喜欢扩展 switch case 语句的策略模式。首先,我创建一个接口来定义每个规则的外观:
public interface IWindowRule
{
string Command { get; }
void Invoke();
}
然后为每个可能的情况创建一个实现接口的类:
public class ShowAllWindowRule : IWindowRule
{
public string Command => "Show commands";
private ProgramCommands _progCommands;
public ShowAllWindowRule(ProgramCommands programCommands) =>
_progCommands = programCommands;
public void Invoke() => _progCommands.ShowAllCommands();
}
public class CloseWindowRule : IWindowRule
{
private ControlCommands _ctrlCommands;
public string Command => "Close window";
public CloseWindowRule(ControlCommands ctrlCommands) =>
_ctrlCommands = ctrlCommands;
public void Invoke() =>
_ctrlCommands.CloseWindow();
}
public class SwitchWindowRule : IWindowRule
{
private ControlCommands _ctrlCommands;
public string Command => "Switch window";
public SwitchWindowRule(ControlCommands ctrlCommands) =>
_ctrlCommands = ctrlCommands;
public void Invoke() =>
_ctrlCommands.SwitchWindow();
}
那么你的 switch 语句就变成了这样:
public void RunWindowRule(IList<IWindowRule> rules, string command)
{
foreach (IWindowRule rule in rules)
{
if (rule.Command == command) rule.Invoke();
}
}
现在您可以向函数传递您希望的任何规则集并运行它们,从而使函数遵守开放/封闭原则。
我意识到这可能看起来有点过度设计,而且我确实认为有更多功能解决方案需要更少的工作,但是这有一个额外的好处是允许您通过创建注入的类来扩展此功能各种情况下的规则列表,甚至创建一个为您提供流畅 API 的构建器类。
public class WindowRuleBuilder
{
private IList<IWindowRule> rules;
public WindowRuleBuilder(IList<IWindowRule> rules = null) =>
rules = rules ?? new List<IWindowRule>();
public WindowRuleBuilder AddRule(IWindowRule newRule)
{
rules.Add(newRule);
return this;
}
public void Run(string command)
{
foreach (IWindowRule rule in rules)
{
if (rule.Command == command) rule.Invoke();
}
}
}
现在你有这样的东西:
public static void Main(string[] args)
{
WindowRuleBuilder ruleBuilder = new WindowRuleBuilder()
.AddRule(new CloseWindowRule(conrolCommands))
.AddRule(new ShowAllWindowRule(programCommands))
.AddRule(new SwitchWindowRule(controlCommands));
ruleBuilder.Run(args[0]);
}
这是高度可扩展的,因为您只需创建类并使用 AddRule() 方法将其添加到规则构建器中即可。也不需要太多的阅读来理解这里发生了什么。这是一种更具组合性的方法。虽然我再次承认,实现起来确实需要一些工作,但代码遵循 SOLID 并且很好地解耦。