- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
当我遇到以下代码时,我正在重构一些简单脚本文件解析器的旧代码:
StringReader reader = new StringReader(scriptTextToProcess);
StringBuilder scope = new StringBuilder();
string line = reader.ReadLine();
while (line != null)
{
switch (line[0])
{
case '$':
// Process the entire "line" as a variable,
// i.e. add it to a collection of KeyValuePair.
AddToVariables(line);
break;
case '!':
// Depending of what comes after the '!' character,
// process the entire "scope" and/or the command in "line".
if (line == "!execute")
ExecuteScope(scope);
else if (line.StartsWith("!custom_command"))
RunCustomCommand(line, scope);
else if (line == "!single_line_directive")
ProcessDirective(line);
scope = new StringBuilder();
break;
default:
// No processing directive, i.e. add the "line"
// to the current scope.
scope.Append(line);
break;
}
line = reader.ReadLine();
}
在我看来,这个简单的脚本处理器很适合通过应用“开闭原则”进行重构。以 $
开头的行可能永远不会被不同地处理。但是,如果需要添加以 !
开头的新指令怎么办?还是需要新的处理标识符(例如新的 switch-cases)?
问题是,我不知道如何在不破坏 OCP 的情况下轻松、正确地添加更多指令和处理器。 !
-case 使用 scope
and/or line
让它有点棘手,默认
-case.
有什么建议吗?
最佳答案
使用 Dictionary<Char, YourDelegate>
指定应如何处理字符。调用DefaultHandler
如果字符键在字典中不存在。
添加 Add(char key, YourDelegate handler)
允许任何人处理特定字符的方法。
最好使用接口(interface):
/// <summary>
/// Let anyone implement this interface.
/// </summary>
public interface IMyHandler
{
void Process(IProcessContext context, string line);
}
/// <summary>
/// Context information
/// </summary>
public interface IProcessContext
{
}
// Actual parser
public class Parser
{
private Dictionary<char, IMyHandler> _handlers = new Dictionary<char, IMyHandler>();
private IMyHandler _defaultHandler;
public void Add(char controlCharacter, IMyHandler handler)
{
_handlers.Add(controlCharacter, handler);
}
private void Parse(TextReader reader)
{
StringBuilder scope = new StringBuilder();
IProcessContext context = null; // create your context here.
string line = reader.ReadLine();
while (line != null)
{
IMyHandler handler = null;
if (!_handlers.TryGetValue(line[0], out handler))
handler = _defaultHandler;
handler.Process(context, line);
line = reader.ReadLine();
}
}
}
请注意,我传入了一个 TextReader
反而。它提供了更大的灵 active ,因为源可以是从简单字符串到复杂流的任何内容。
我也会分解 !
以类似的方式处理。即创建一个处理 IMyHandler 的类:
public interface ICommandHandler
{
void Handle(ICommandContext context, string commandName, string[] arguments);
}
public class CommandService : IMyHandler
{
public void Add(string commandName, ICommandHandler handler)
{
}
public void Handle(IProcessContext context, string line)
{
// first word on the line is the command, all other words are arguments.
// split the string properly
// then find the corrext command handler and invoke it.
// take the result and add it to the `IProcessContext`
}
}
这为处理实际协议(protocol)和添加更多命令提供了更大的灵 active 。您无需更改任何内容即可添加更多功能。因此,关于开放/封闭和其他一些 SOLID 原则,该解决方案是可行的。
关于c# - 了解开闭原则,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5416500/
是否可以在 Delphi 中解开这些名称?如果是这样,我从哪里可以获得更多信息? 在 dbrtl100.bpl 中找不到特定条目的错误消息示例我想知道它找不到哪个确切的函数(单元、类、名称、参数等)。
我是小白,如何从列表中删除引号和逗号?或者我如何“取消字符串”? 在不显示字典 (dic) 的情况下,我使用的代码如下所示: >>>import itertools >>>list(itertools
我正在学习构建器模式,到目前为止我了解到,它是用于初始化的常用模式的一个很好的替代方案: 伸缩构造函数模式 JavaBean 模式 问题是,我真的不喜欢从我的域模型中的对象中删除 getter 和 s
我有这段文字 "Welcome to my city. Hello my good friend" 使用 jQuery(或 javascript),我想解开所有 span 标签,只保留第一级,我的意思
在为大学撰写作业的过程中,我一直享受着学习新的 Haskell monad 的乐趣。耶!!! 我有一个可以很好地进行类型检查的函数: compile :: Prog -> State VarsStat
let myLabel:UILabel = UILabel(frame:CGRectMake(0, 0, 44, 44)) myLabel.text = "Primary"
是否有一个好的 npm 包可以删除在 NodeJS 服务器上运行的 html 字符串中不必要的嵌套标签(无浏览器 DOM)?我尝试过 sanitize-html,但似乎不可能做到这一点。 我收到用户发
我目前正在编写一些日志代码,这些代码应该——除其他外——打印有关调用函数的信息。这应该比较容易,标准C++有一个type_info类(class)。这包含 typeid 的类/函数/等的名称。但它被破
我有以下组件 const ListItem = ({ children, title = '' }) => { const [isActive, setIsActive] = useSta
我正在尝试取消在 python3 中 pickle 的对象。这在 python3 中有效,但在 python2 中无效。该问题可以重现到 pickle 协议(protocol) 0。示例代码: imp
这个问题的灵感来自 How to transform a flow chart into an implementation?它询问从代码中通过算法消除 goto 语句的方法。 answer this
当我的 child 执行 unwind segue 时,我的 Controller 的 viewDidAppear 被调用。 在这个方法中(只有这个方法,我需要知道它是否来自 unwind) 注意:
我用 C 编写了一个小程序来管理 SQLite3 中的书目数据库。到目前为止,这只是一个允许导入和导出 BibTeX 数据的命令行工具。为了使导出/导入功能更加可定制(例如,在导入时始终在日期字段中组
这个问题与How to split an array according to a condition in numpy?密切相关但我正在寻找一种更通用的方法来拆分给定未知数量索引的数组: impor
我是一名优秀的程序员,十分优秀!