C#面向对象设计模式纵横谈 学习笔记16 Interpreter 解释器模式(行为型模式)
来源:互联网 发布:linux rsync 单向同步 编辑:程序博客网 时间:2024/06/04 22:16
Interpreter模式是一种比较不常用的模式,因为这种模式存在一些弊端,他的使用有很大的条件限制。
Interpreter是一种特殊的设计模式,它建立一个解释器,对于特定的计算机程序设计语言,用来解释预先定义的文法。简单地说,Interpreter模式是一种简单的语法解释器构架。
先借用李建忠老师的代码例子
- public class Program
- {
- static void Main()
- {
- string roman = "二十四万零二";
- Context context = new Context(roman);
- ArrayList tree = new ArrayList();
- tree.Add(new GeExpression());
- tree.Add(new ShiExpression());
- tree.Add(new BaiExpression());
- tree.Add(new QianExpression());
- tree.Add(new WanExpression());
- foreach(Expression exp in tree)
- {
- exp.Interpret(context);
- }
- Console.WriteLine("{0}={1}", roman, context.Data);
- Console.Read();
- }
- }
- public class Context
- {
- private string statement;
- private int data;
- public Context(string statement)
- {
- this.statement = statement;
- }
- public string Statement
- {
- get
- {
- return statement;
- }
- set
- {
- statement = value;
- }
- }
- public int Data
- {
- get
- {
- return data;
- }
- set
- {
- data = value;
- }
- }
- }
- public abstract class Expression
- {
- protected Dictionary<string, int> table = new Dictionary<string,int>();
- public Expression()
- {
- table.Add("一", 1);
- table.Add("二", 2);
- table.Add("三", 3);
- table.Add("四", 4);
- table.Add("五", 5);
- table.Add("六", 6);
- table.Add("七", 7);
- table.Add("八", 8);
- table.Add("九", 9);
- }
- public virtual void Interpret(Context context)
- {
- if(context.Statement.Length == 0)
- {
- return;
- }
- foreach(string key in table.Keys)
- {
- int value = table[key];
- if(context.Statement.EndsWith(key + GetPostfix()))
- {
- context.Data += value * Multiplier();
- context.Statement = context.Statement.Substring(0, context.Statement.Length - GetLength());
- }
- if(context.Statement.EndsWith("零"))
- {
- context.Statement = context.Statement.Substring(0, context.Statement.Length - 1);
- }
- }
- }
- public abstract string GetPostfix();
- public abstract int Multiplier();
- public virtual int GetLength()
- {
- return this.GetPostfix().Length + 1;
- }
- }
- public class GeExpression : Expression
- {
- public override string GetPostfix()
- {
- return string.Empty;
- }
- public override int Multiplier()
- {
- return 1;
- }
- public override int GetLength()
- {
- return 1;
- }
- }
- public class ShiExpression : Expression
- {
- public override string GetPostfix()
- {
- return "十";
- }
- public override int Multiplier()
- {
- return 10;
- }
- }
- public class BaiExpression : Expression
- {
- public override string GetPostfix()
- {
- return "百";
- }
- public override int Multiplier()
- {
- return 100;
- }
- }
- public class QianExpression : Expression
- {
- public override string GetPostfix()
- {
- return "千";
- }
- public override int Multiplier()
- {
- return 1000;
- }
- }
- public class WanExpression : Expression
- {
- public override string GetPostfix()
- {
- return "万";
- }
- public override int Multiplier()
- {
- return 10000;
- }
- public override void Interpret(Context context)
- {
- if(context.Statement.Length == 0)
- {
- return;
- }
- ArrayList tree = new ArrayList();
- tree.Add(new GeExpression());
- tree.Add(new ShiExpression());
- tree.Add(new BaiExpression());
- tree.Add(new QianExpression());
- foreach(string key in table.Keys)
- {
- if(context.Statement.EndsWith(this.GetPostfix()))
- {
- int temp = context.Data;
- context.Data = 0;
- context.Statement = context.Statement.Substring(0, context.Statement.Length - 1);
- foreach(Expression exp in tree)
- {
- exp.Interpret(context);
- }
- context.Data = temp + this.Multiplier() * context.Data;
- }
- }
- }
- }
- 分析一下代码。
- 这段代码是将中文的数字转换为阿拉伯数字,如果按照面向过程的算法肯定是来截取字符串进行判断然后组合成正确的数字。在这段代码中则利用了interpreter模式将位数进行表达式的封装。
- 首先看抽象Expression类,首先他封装了一个字典类,这个字典保存了中文的1-9的字符及其对应的阿拉伯数字。Interpret方法,在便利字典中的每个中文数字,并且判断截取中文数字加其后缀是否是结尾,如果为真那么将对应的值乘以对应的位数,对应的位数是一个纯虚函数Multiplier,由派生类自己实现。在取得了对应的Expression的值后需要将中文数字语句中对应的字符串去掉,即GetLength函数,取得对应的位数符合加1。这是一个虚函数,可以由派生类重写。注意GeExpression就重写了此虚函数,因为个位数的长度是1,而不是位数符加1。
- 注意下面这段代码
- if(context.Statement.EndsWith("零"))
- {
- context.Statement = context.Statement.Substring(0, context.Statement.Length - 1);
- }
这是处理三万零五十类似中间有零来分割的情况,将零去掉。
在WanExpression中,我们重写了Interpret函数,这是由于万位数可以由千位一下的数字来描述,如三千二百万。重写Interpret函数的算法如下,先将千以下的表达式(包括千)加入一个ArrayList保存起来,然后遍历数字表,如果当前的表达式已经截取到万,那么先将已取得的数值用中间临时变量保存起来,将当前表达式的数字值置为0。然后将万以后的文字截取。在依次用ArrayList里面的千、百、十、个的Expression进行解释,最后取得的数值乘以万对应的位数加上临时变量。这里的算法不用担心亿的情况,因为没有亿的运算符表达式,算到亿的时候,解释器已经算完描述万的数值
在看Main函数的调用,在Main函数里使用ArrayList保存了个十百千万的表达式,依次用这些表达式来解析上下文。注意,解析的顺序是个十百千万的顺序。
解释器模式是用来解释语言的文法的。但是它的适用范围其实很有限:
1.简单文法:对于复杂的文法来说,解释器模式会让类的层次复杂的难以管理,如果个十百千万类似位数符很多,那么派生类的体系将相当庞大。所以此模式适用于文法比较简单的
2.效率无关:追求效率的语法解释通常使用状态机解决。
- C#面向对象设计模式纵横谈 学习笔记16 Interpreter 解释器模式(行为型模式)
- C#面向对象设计模式纵横谈 学习笔记15 Command命令模式(行为型模式)
- C#面向对象设计模式纵横谈 学习笔记18 Iterator迭代器模式(行为型模式)
- C#面向对象设计模式纵横谈 学习笔记19 Observer观察者模式(行为型模式)
- C#面向对象设计模式纵横谈 学习笔记21 Memento备忘录模式(行为型模式)
- C#面向对象设计模式纵横谈 学习笔记22 State模式(行为型模式)
- C#面向对象设计模式纵横谈 学习笔记23 Strategy策略模式(行为型模式)
- C#面向对象设计模式纵横谈 学习笔记24 Visitor访问者模式(行为型模式)
- C#面向对象设计模式纵横谈 学习笔记17 Mediator 中介者模式(行为型模式)
- C#面向对象设计模式纵横谈 学习笔记20 Chain of Responsibility职责链模式(行为型模式)
- C#面向对象设计模式纵横谈 学习笔记14 Template Method模板方法(行为型模式)
- C#面向对象设计模式纵横谈 学习笔记13 Proxy代理模式(结构型模式)
- C#面向对象设计模式纵横谈学习笔记(1)
- C#面向对象设计模式纵横谈 学习笔记4 Builder 生成器(创建型模式)
- C#面向对象设计模式纵横谈 学习笔记6 Prototype 原型(创建型模式)
- C#面向对象设计模式纵横谈 学习笔记7 Adapter适配器(结构型模式)
- C#面向对象设计模式纵横谈 学习笔记8 Bridge桥接(结构型模式)
- C#面向对象设计模式纵横谈 学习笔记9 Composite 组合(结构型模式)
- .net类库中发送电子邮件的方法总结
- 储存过程的基础的创建和简单应用[转]
- WinForm中的特殊窗体效果:渐变窗口和信息提示窗口
- 纽约随笔:走访华尔街 风暴中心最平静
- 【SQLSERVER】存储过程基础
- C#面向对象设计模式纵横谈 学习笔记16 Interpreter 解释器模式(行为型模式)
- linux系统图形界面突然打不开解决方法之一
- 读取 INI 文件的模块儿
- QTdesigner高版本设计的UI在低版本上打不开的解决方法
- 如何美化你的.net 应用程序
- 50个常用sql语句
- 美联储为何救AIG 而不救雷曼?
- 培训札记(1)
- 怎样使用Junit Framework进行单元测试的编写