• 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
    

      

  • 相关阅读:
    (转)simple-framework(MaliSDK框架分析)
    (转)libhybris及EGL Platform-在Glibc生态中重用Android的驱动
    (原)在firefly_rk3288开发板上解决openGL在设置32位色深以后出现花屏的问题
    参考论坛:Mali kernel driver TX011-SW-99002-r5p1-00rel0 for firefly
    (转)android媒体--stagefright概述【一】
    (转)android系统架构及源码目录结构
    (原)linux下利用cmake来编译jthread开源库
    (原)U盘可见容量不能被识别的处理方法
    学会阅读Java字节码
    JVM
  • 原文地址:https://www.cnblogs.com/geovindu/p/16786478.html
Copyright © 2020-2023  润新知