在软件开发中,经常需要为应用程序提供灵活的配置方式。本文将展示如何使用解释器模式(Interpreter pattern)设计一个通用的商业表达式,以满足这一需求。
表达式是根据特定上下文规则形成的符号有限组合。希望为用户提供的商业表达式具有以下语法定义:
Business Expression ::= ‘{‘ Operator ‘@’ Operand { ‘;’ … } ‘}’
Operator ::= ‘ADD’ | ‘SUB’ | ‘MUL’ | ‘DIV’
Operand ::= Business Expression | Data
Data ::= ‘1’ | ‘2’ …
以下是一些商业表达式的例子:
{ADD@1;2} // 表示 1 + 2 的结果
{SUB@3;2} // 表示 3 - 2 的结果
{MUL@2;5} // 表示 2 * 5 的结果
{DIV@4;2} // 表示 4 / 2 的结果
{MUL@2;{DIV@{ADD:5;3};{SUB@5;1}}} // 这是一个更复杂的商业表达式,等于 2 * ((5 + 3) / (5 – 1))
解释器模式的定义是:给定一种语言,定义它的语法表示以及一个解释器,该解释器使用该表示来解释语言中的句子。
从解释器模式的定义中,可以看到商业表达式非常适合应用解释器模式。可以定义商业表达式的每个部分为一个商业表达式类,这些类用来表示商业表达式语法,并构建成一个商业表达式层次结构。
在商业表达式层次结构中,有一个类似于抽象表达式的 BusinessExpression
类,一个类似于终结符表达式的 BusinessDataExpression
类,以及一个类似于非终结符表达式的 BusinessCompositeExpression
类及其所有子类。因此,客户端路由可以使用商业表达式来评估给定的商业表达式字符串。
解释器模式的图示中有一个上下文类。在商业表达式图中没有包含上下文类。解释器模式中上下文类的目的是用来包含输入字符串和结果。因此,它不是一个必须有的类。
没有上下文类,可以直接将输入字符串作为输入参数传递给商业表达式,并用返回值获取结果。
要使用商业表达式,需要遵循以下步骤:
商业表达式以字符串形式给出,例如 {ADD@1;2}。将此字符串转换为商业表达式对象树的方法是通过遍历字符串中的每个字符,并将任何识别出的术语转换为相应的商业表达式对象。
BusinessExpression
类中的 Parse
静态方法设计用于将商业表达式字符串转换为商业表达式对象树。它在内部使用一个过程栈来存储过程中的中间结果。中间结果用 ProcessAtom
类表示。
在获得商业表达式对象树之后,可以调用根商业表达式对象的 evaluate
方法来获取商业表达式字符串的结果。每个商业表达式对象都知道如何评估自己或从包含的商业表达式中获取结果。根商业表达式对象将结果汇总并返回给客户端。
商业表达式非常适合应用解释器模式,但解释器模式本身无法单独满足要求,还有其他模式被采用。
商业表达式对象树是使用组合模式构建的,因此可以在商业表达式中嵌套商业表达式。通过这样做,可以定义更复杂的商业表达式。
Parse
方法有一个固定的算法,用于将商业表达式字符串解析为商业表达式对象树,但可能有时想要添加新的商业表达式以支持新的操作。根据单一责任原则,不应该让解析器方法直接创建商业表达式对象。相反,希望商业表达式对象的创建在工厂类中完成。因此,只需要添加一个新的商业类,并更改 BusinessExpressionFactory
以将新的商业表达式对象返回给解析器。
public class BusinessExpressionFactory
{
public BusinessExpressionFactory()
{
}
public BusinessExpression CreateBusinessExpression(string type)
{
BusinessExpression businessExpression = null;
switch (type.ToLower())
{
case "add":
businessExpression = new BusinessAdditionExpression();
break;
case "sub":
businessExpression = new BusinessSubstractionExpression();
break;
case "mul":
businessExpression = new BusinessMultiplicationExpression();
break;
case "div":
businessExpression = new BusinessDivisionExpression();
break;
}
return businessExpression;
}
}