CSharp: Interpreter Pattern in donet core 3
/// <summary>
/// 解释器模式 Interpreter Pattern
/// geovindu, Geovin Du edit
/// </summary>
interface Employee
{
/// <summary>
/// 是否解释
/// </summary>
/// <param name="context">输入背景</param>
/// <returns></returns>
bool Interpret(Context context);
}
/// <summary>
/// IndividualEmployee class
/// 单独雇员
/// </summary>
class IndividualEmployee : Employee
{
/// <summary>
/// 年经验
/// </summary>
private int yearOfExperience;
/// <summary>
/// 当前等级
/// </summary>
private string currentGrade;
/// <summary>
///
/// </summary>
/// <param name="experience">经验年数</param>
/// <param name="grade">等级</param>
public IndividualEmployee(int experience, string grade)
{
this.yearOfExperience = experience;
this.currentGrade = grade;
}
/// <summary>
/// 是否解释
/// </summary>
/// <param name="context">输入背景</param>
/// <returns></returns>
public bool Interpret(Context context)
{
if (this.yearOfExperience >= context.GetYearofExperience()
&& context.GetPermissibleGrades().Contains(this.currentGrade))
{
return true;
}
return false;
}
}
/// <summary>
/// OrExpression class
/// 或经验
/// </summary>
class OrExpression : Employee
{
private Employee emp1;
private Employee emp2;
/// <summary>
///
/// </summary>
/// <param name="emp1">输入雇员</param>
/// <param name="emp2">输入雇员</param>
public OrExpression(Employee emp1, Employee emp2)
{
this.emp1 = emp1;
this.emp2 = emp2;
}
/// <summary>
/// 是否解释
/// </summary>
/// <param name="context">输入背景</param>
/// <returns></returns>
public bool Interpret(Context context)
{
return emp1.Interpret(context) || emp2.Interpret(context);
}
}
/// <summary>
/// AndExpression class
/// 添加经验
/// </summary>
class AndExpression : Employee
{
private Employee emp1;
private Employee emp2;
/// <summary>
/// 添加经验
/// </summary>
/// <param name="emp1">输入雇员</param>
/// <param name="emp2">输入雇员</param>
public AndExpression(Employee emp1, Employee emp2)
{
this.emp1 = emp1;
this.emp2 = emp2;
}
/// <summary>
/// 是否解释
/// </summary>
/// <param name="context">输入背景</param>
/// <returns></returns>
public bool Interpret(Context context)
{
return emp1.Interpret(context) && emp2.Interpret(context);
}
}
/// <summary>
/// NotExpression class
/// 没有经验
/// </summary>
class NotExpression : Employee
{
private Employee emp;
/// <summary>
/// 构造
/// </summary>
/// <param name="expr">输入雇员</param>
public NotExpression(Employee expr)
{
this.emp = expr;
}
/// <summary>
/// 是否解释
/// </summary>
/// <param name="context">输入背景</param>
/// <returns></returns>
public bool Interpret(Context context)
{
return !emp.Interpret(context);
}
}
/// <summary>
/// Context class
///背景
/// </summary>
class Context
{
/// <summary>
/// 晋升所需的经验
/// </summary>
private int experienceReqdForPromotion;
/// <summary>
/// 允许成绩列表
/// </summary>
private List<string> allowedGrades;
/// <summary>
///
/// </summary>
/// <param name="experience">经验年数</param>
/// <param name="allowedGrades">允许成绩列表</param>
public Context(int experience, List<string> allowedGrades)
{
this.experienceReqdForPromotion = experience;
this.allowedGrades = new List<string>();
foreach (string grade in allowedGrades)
{
this.allowedGrades.Add(grade);
}
}
/// <summary>
/// 赋值经验年数
/// </summary>
/// <returns></returns>
public int GetYearofExperience()
{
return experienceReqdForPromotion;
}
/// <summary>
/// 赋值允许的成绩
/// </summary>
/// <returns></returns>
public List<string> GetPermissibleGrades()
{
return allowedGrades;
}
}
/// <summary>
/// EmployeeBuilder class
/// </summary>
class EmployeeBuilder
{
// Building the tree
//Complex Rule-1: emp1 and (emp2 or (emp3 or emp4))
/// <summary>
/// 创建规则
/// </summary>
/// <param name="emp1"></param>
/// <param name="emp2"></param>
/// <param name="emp3"></param>
/// <param name="emp4"></param>
/// <returns></returns>
public Employee BuildTreeBasedOnRule1(Employee emp1, Employee emp2, Employee emp3, Employee emp4)
{
// emp3 or emp4
Employee firstPhase = new OrExpression(emp3, emp4);
// emp2 or (emp3 or emp4)
Employee secondPhase = new OrExpression(emp2, firstPhase);
// emp1 and (emp2 or (emp3 or emp4))
Employee finalPhase = new AndExpression(emp1, secondPhase);
return finalPhase;
}
//Complex Rule-2: emp1 or (emp2 and (not emp3 ))
/// <summary>
/// 创建规则
/// </summary>
/// <param name="emp1"></param>
/// <param name="emp2"></param>
/// <param name="emp3"></param>
/// <returns></returns>
public Employee BuildTreeBasedOnRule2(Employee emp1, Employee emp2, Employee emp3)
{
// Not emp3
Employee firstPhase = new NotExpression(emp3);
// emp2 or (not emp3)
Employee secondPhase = new AndExpression(emp2, firstPhase);
// emp1 and (emp2 or (not emp3 ))
Employee finalPhase = new OrExpression(emp1, secondPhase);
return finalPhase;
}
}
/// <summary>
/// 解释器模式 Interpreter Pattern
/// geovindu, Geovin Du edit
/// </summary>
public interface IElement
{
int Value { get; }
}
/// <summary>
///
/// </summary>
public class Integer : IElement
{
public Integer(int value)
{
Value = value;
}
public int Value { get; }
}
/// <summary>
///
/// </summary>
public class BinaryOperation : IElement
{
public enum Type
{
Addition,
Subtraction
}
public Type MyType;
public IElement Left, Right;
public int Value
{
get
{
switch (MyType)
{
case Type.Addition:
return Left.Value + Right.Value;
case Type.Subtraction:
return Left.Value - Right.Value;
default:
throw new ArgumentOutOfRangeException();
}
}
}
}
/// <summary>
///
/// </summary>
public class Token
{
public enum Type
{
Integer, Plus, Minus, Lparen, Rparen
}
public Type MyType;
public string Text;
public Token(Type type, string text)
{
MyType = type;
Text = text;
}
public override string ToString()
{
return $"`{Text}`";
}
}
/// <summary>
///
/// </summary>
public class GevovinDu
{
public static List<Token> Lex(string input)
{
var result = new List<Token>();
for (int i = 0; i < input.Length; i++)
{
switch (input[i])
{
case '+':
result.Add(new Token(Token.Type.Plus, "+"));
break;
case '-':
result.Add(new Token(Token.Type.Minus, "-"));
break;
case '(':
result.Add(new Token(Token.Type.Lparen, "("));
break;
case ')':
result.Add(new Token(Token.Type.Rparen, ")"));
break;
default:
var sb = new StringBuilder(input[i].ToString());
for (int j = i + 1; j < input.Length; ++j)
{
if (char.IsDigit(input[j]))
{
sb.Append(input[j]);
++i;
}
else
{
result.Add(new Token(Token.Type.Integer, sb.ToString()));
break;
}
}
break;
}
}
return result;
}
/// <summary>
///
/// </summary>
/// <param name="tokens"></param>
/// <returns></returns>
/// <exception cref="ArgumentOutOfRangeException"></exception>
public static IElement Parse(IReadOnlyList<Token> tokens)
{
var result = new BinaryOperation();
bool haveLHS = false;
for (int i = 0; i < tokens.Count; i++)
{
var token = tokens[i];
// look at the type of token
switch (token.MyType)
{
case Token.Type.Integer:
var integer = new Integer(int.Parse(token.Text));
if (!haveLHS)
{
result.Left = integer;
haveLHS = true;
}
else
{
result.Right = integer;
}
break;
case Token.Type.Plus:
result.MyType = BinaryOperation.Type.Addition;
break;
case Token.Type.Minus:
result.MyType = BinaryOperation.Type.Subtraction;
break;
case Token.Type.Lparen:
int j = i;
for (; j < tokens.Count; ++j)
if (tokens[j].MyType == Token.Type.Rparen)
break; // found it!
// process subexpression w/o opening
var subexpression = tokens.Skip(i + 1).Take(j - i - 1).ToList();
var element = Parse(subexpression);
if (!haveLHS)
{
result.Left = element;
haveLHS = true;
}
else result.Right = element;
i = j; // advance
break;
default:
throw new ArgumentOutOfRangeException();
}
}
return result;
}
}
调用:
//解释器模式
Console.WriteLine("*** 解释器模式 Interpreter Pattern Demonstration-2***\n");
// Minimum Criteria for promoton is:
// The year of experience is minimum 10 yrs. and
// Employee grade should be either G2 or G3
List<string> allowedGrades = new List<string> { "G2", "G3" };
Context context = new Context(10, allowedGrades);
Employee emp1 = new IndividualEmployee(5, "G1");
Employee emp2 = new IndividualEmployee(10, "G2");
Employee emp3 = new IndividualEmployee(15, "G3");
Employee emp4 = new IndividualEmployee(20, "G4");
EmployeeBuilder builder = new EmployeeBuilder();
//Validating the 1st complex rule
Console.WriteLine("----- 验证第一个复杂规则.-----");
Console.WriteLine("emp1和emp2、emp3、emp4中的任何一个是否有资格晋升?"
+ builder.BuildTreeBasedOnRule1(emp1, emp2, emp3, emp4).Interpret(context));
Console.WriteLine("emp2和emp1、emp3、emp4中的任何一个是否有资格晋升?"
+ builder.BuildTreeBasedOnRule1(emp2, emp1, emp3, emp4).Interpret(context));
Console.WriteLine("emp3和emp1、emp2、emp3中的任何一个是否有资格晋升?"
+ builder.BuildTreeBasedOnRule1(emp3, emp1, emp2, emp4).Interpret(context));
Console.WriteLine("emp4和emp1、emp2、emp3中的任何一个是否有资格晋升?"
+ builder.BuildTreeBasedOnRule1(emp4, emp1, emp2, emp3).Interpret(context));
Console.WriteLine("-----现在验证第二个复杂的规则.-----");
//Validating the 2nd complex rule
Console.WriteLine("emp1或(emp2而不是emp3)是否有资格晋升?"
+ builder.BuildTreeBasedOnRule2(emp1, emp2, emp3).Interpret(context));
Console.WriteLine("emp2或(emp3但不是emp4)是否有资格晋升?"
+ builder.BuildTreeBasedOnRule2(emp2, emp3, emp4).Interpret(context));
Console.WriteLine();
var input = "(13+4)-(12+1)";
var tokens = GevovinDu.Lex(input);
Console.WriteLine(string.Join("\t", tokens));
var parsed = GevovinDu.Parse(tokens);
Console.WriteLine($"{input} = {parsed.Value}");
输出:
***?解释器模式 Interpreter Pattern Demonstration-2*** ----- 验证第一个复杂规则.----- emp1和emp2、emp3、emp4中的任何一个是否有资格晋升?False emp2和emp1、emp3、emp4中的任何一个是否有资格晋升?True emp3和emp1、emp2、emp3中的任何一个是否有资格晋升?True emp4和emp1、emp2、emp3中的任何一个是否有资格晋升?False -----现在验证第二个复杂的规则.----- emp1或(emp2而不是emp3)是否有资格晋升?False emp2或(emp3但不是emp4)是否有资格晋升?True `(` `13` `+` `4` `)` `-` `(` `12` `+` `1` `)` (13+4)-(12+1) = 4
哲学管理(学)人生, 文学艺术生活, 自动(计算机学)物理(学)工作, 生物(学)化学逆境, 历史(学)测绘(学)时间, 经济(学)数学金钱(理财), 心理(学)医学情绪, 诗词美容情感, 美学建筑(学)家园, 解构建构(分析)整合学习, 智商情商(IQ、EQ)运筹(学)生存.---Geovin Du(涂聚文)
浙公网安备 33010602011771号