use*_*672 8 .net c# refactoring switch-statement
我在c#中编程,你通过口述命令控制,所以现在我有一个很长的switch语句.就像是
switch (command)
{
case "Show commands":
ProgramCommans.ShowAllCommands();
break;
case "Close window":
ControlCommands.CloseWindow();
break;
case "Switch window":
ControlCommands.SwitchWindow();
break;
}
Run Code Online (Sandbox Code Playgroud)
等等
几乎所有情况都只调用一个方法,方法不在一个类中,它们分布在许多类中.所以问题是,我如何能够将这种转换重构为更优雅的方式?
您可以这样做来重构您的switch语句:
var commands = new Dictionary<string, Action>()
{
{ "Show commands", () => ProgramCommans.ShowAllCommands() },
{ "Close window", () => ControlCommands.CloseWindow() },
{ "Switch window", () => ControlCommands.SwitchWindow() },
};
if (commands.ContainsKey(command))
{
commands[command].Invoke();
}
Run Code Online (Sandbox Code Playgroud)
这种方法的主要优点是您可以在运行时更改"切换".
我更喜欢使用策略模式来扩展 switch case 语句。首先,我创建一个接口来定义每个规则的外观:
public interface IWindowRule
{
string Command { get; }
void Invoke();
}
Run Code Online (Sandbox Code Playgroud)
然后创建一个类来实现每种可能情况的接口:
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();
}
Run Code Online (Sandbox Code Playgroud)
然后你的 switch 语句变成这样:
public void RunWindowRule(IList<IWindowRule> rules, string command)
{
foreach (IWindowRule rule in rules)
{
if (rule.Command == command) rule.Invoke();
}
}
Run Code Online (Sandbox Code Playgroud)
现在,您可以向函数传递任何您希望的规则集并运行它们,使函数遵循开放/关闭原则。
我意识到这可能看起来有点过度工程,而且我确实认为有更多功能解决方案需要更少的工作,但是这还有一个额外的好处,即允许您通过创建注入列表的类来扩展此功能为各种情况制定规则,甚至创建一个为您提供流畅 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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
现在你有这样的东西:
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]);
}
Run Code Online (Sandbox Code Playgroud)
这是高度可扩展的,因为对于新规则,您只需创建该类并使用 AddRule() 方法将其添加到规则构建器中。也不需要读太多书就能理解这里发生的事情。这是一种更具组合性的方法。尽管我再次承认,实现它确实需要一些工作,但代码遵循 SOLID 并进行了很好的解耦。
| 归档时间: |
|
| 查看次数: |
2770 次 |
| 最近记录: |