/// <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