Interpreter 解释器模式(行为型模式)

动机(Motivation)

在软件构建过程中,如果某一特定领域的问题比较复杂,类似的模式不断重复出现,如果使用普通的编程方式来实现将面临非常频繁的变化。

在这种情况下,将特定领域的问题表达为某种语法规则下的句子,然后构建一个解释器来解释这样的句子,从而达到解决问题的目的。

意图(Intent)

给定一个语言,定义它的文法的一种表示,并定义一种解释器,这个解释器用来解释语言中的句子。——《设计模式》GoF

中文数字转换为阿拉伯数字

    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("一", );
table.Add("二", );
table.Add("三", );
table.Add("四", );
table.Add("五", );
table.Add("六", );
table.Add("七", );
table.Add("八", );
table.Add("九", );
} public virtual void Interpret(Context context)
{
if (context.Statement.Length == )
{
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(, context.Statement.Length - GetLength() - );
} if (context.Statement.EndsWith("零"))
{
context.Statement = context.Statement.Substring(, context.Statement.Length - );
}
}
} public abstract string GetPostfix();
public abstract int Multiplier();
public virtual int GetLength()
{
return this.GetPostfix().Length;
}
} public class GeExpression : Expression
{
public override string GetPostfix()
{
return string.Empty;
}
public override int Multiplier()
{
return ;
}
public override int GetLength()
{
return ;
}
}
public class ShiExpression : Expression
{
public override string GetPostfix()
{
return "十";
} public override int Multiplier()
{
return ;
}
}
public class BaiExpression : Expression
{
public override string GetPostfix()
{
return "百";
}
public override int Multiplier()
{
return ;
}
}
public class QianExpression : Expression
{
public override string GetPostfix()
{
return "千";
}
public override int Multiplier()
{
return ;
}
}
public class WanExpression : Expression
{
public override string GetPostfix()
{
return "万";
}
public override int Multiplier()
{
return ;
}
public override void Interpret(Context context)
{
if (context.Statement.Length == )
{
return;
} List<Expression> tree = new List<Expression>();
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 = ;
context.Statement = context.Statement.Substring(, context.Statement.Length - ); foreach (Expression exp in tree)
{
exp.Interpret(context);
} context.Data = temp + this.Multiplier() * context.Data;
}
}
}
}

客户端调用代码:

        static void Main(string[] args)
{
string roman = "一千零五十万三千六百零二"; Context context = new Context(roman);
List<Expression> tree = new List<Expression>();
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.ReadKey();
}

输出:

一千零五十万三千六百零二 = 10503602

这段代码是将中文的数字转换为阿拉伯数字,如果按照面向过程的算法肯定是来截取字符串进行判断然后组合成正确的数字。在这段代码中则利用了Interpreter模式将位数进行表达式的封装。
首先看抽象Expression类,首先它封装了一个字典类,这个字典保存了中文的1-9的字符及其对应的阿拉伯数字。Interpret方法,遍历字典中的每个中文数字,并且判断截取中文数字加其后缀是否是结尾,如果是,则将对应的值乘以对应的位数,对应的位数是一个纯虚函数Multiplier,由派生类自己实现。在取得了对应的Expression的值后需要将中文数字语句中对应的字符串去掉。

在WanExpression中,我们重写了Interpret函数,这是由于万位数可以由千位以下的数字来描述,如三千二百万。重写Interpret函数的算法如下,先将千以下的表达式(包括千)加入一个List保存起来,然后遍历数字表,如果当前的表达式已经截取到万,那么先将已取得的数值用中间临时变量保存起来,将当前表达式的数字值置为0。然后将万以后的文字截取。再依次用List里面的千、百、十、个的Expression进行解释,最后取得的数值乘以万对应的位数加上临时变量。

在Main函数里使用List保存了个十百千万的表达式,依次用这些表达式来解析上下文。注意,解析的顺序是个十百千万的顺序。

结构(Structure)

Interpreter模式的几个要点

  • Interpreter模式的应用场合是Interpreter模式应用中的难点,只有满足“业务规则频繁变化,且类似的模式不断重复出现,并且容易抽象为语法规则的问题”才适合使用Interpreter模式。
  • 使用Interpreter模式来表示文法规则,从而可以使用面向对象技巧来方便“扩展”文法。
  • Interpreter模式比较适合简单的文法表示,对于复杂的文法表示,Interpreter模式会产生较大的类层次结构,需要求助于语法分析生成器这样的标准工具。

转载请注明出处:

作者:JesseLZJ
出处:http://jesselzj.cnblogs.com

设计模式15:Interpreter 解释器模式(行为型模式)的更多相关文章

  1. 设计模式(15)--Interpreter(解释器模式)--行为型

    作者QQ:1095737364    QQ群:123300273     欢迎加入! 1.模式定义: 解释器模式是类的行为模式.给定一个语言之后,解释器模式可以定义出其文法的一种表示,并同时提供一个解 ...

  2. Interpreter(解释器)-类行为型模式

    1.意图 给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子. 2.动机 如果一种特定类型的问题发生的频率足够高,那么可能就值的将该问题的各个实例表述为一个 ...

  3. php设计模式(一):简介及创建型模式

    我们分三篇文章来总结一下设计模式在PHP中的应用,这是第一篇创建型模式. 一.设计模式简介 首先我们来认识一下什么是设计模式: 设计模式是一套被反复使用.容易被他人理解的.可靠的代码设计经验的总结. ...

  4. FactoryMethod工厂方法模式(创建型模式)

    1.工厂方法模式解决的问题 现在有一个抽象的游戏设施建造系统,负责构建一个现代风格和古典风格的房屋和道路. 前提:抽象变化较慢,实现变化较快(不稳定) 整个抽象的游戏设施建造系统相对变化较慢,本例中只 ...

  5. Prototype原型模式(创建型模式)

    1.原型模式解决的问题 现在有一个抽象的游戏设施建造系统,负责构建一个现代风格和古典风格的房屋和道路. 前提:抽象变化较慢,实现变化较快(不稳定) 整个抽象的游戏设施建造系统相对变化较慢,本例中只有一 ...

  6. C#面向对象设计模式纵横谈——2.Singleton 单件(创建型模式)

    一:模式分类 从目的来看: 创建型(Creational)模式:负责对象创建. 结构型(Structural)模式:处理类与对象间的组合. 行为型(Behavioral)模式:类与对象交互中的职责分配 ...

  7. .NET设计模式(7):创建型模式专题总结(Creational Pattern)(转)

    概述 创建型模式,就是用来创建对象的模式,抽象了实例化的过程.它帮助一个系统独立于如何创建.组合和表示它的那些对象.本文对五种常用创建型模式进行了比较,通过一个游戏开发场景的例子来说该如何使用创建型模 ...

  8. .NET设计模式(7):创建型模式专题总结(Creational Pattern)

    ):创建型模式专题总结(Creational Pattern)    创建型模式专题总结(Creational Pattern) --.NET设计模式系列之七 Terrylee,2006年1月 转载: ...

  9. 设计模式(五):PROTOTYPE原型模式 -- 创建型模式

    1.定义 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象. 2.适用场景 原型模式的主要思想是基于现有的对象克隆一个新的对象出来,一般是有对象的内部提供克隆的方法,通过该方法返回一个对 ...

  10. 设计模式(二): BUILDER生成器模式 -- 创建型模式

    1.定义 将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示,这样的设计模式被称为建造者模式. 2.适用场景 1. 当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式 ...

随机推荐

  1. 华为交换机S5700设置远程ssh telnet登录

    AAA是指:authentication(认证).authorization(授权).accounting(计费)的简称,是网络安全的一种管理机制:Authentication是本地认证/授权,aut ...

  2. CentOS7.6安装JDK(Openjdk) - mvn package报错汇总

    错误一: No compiler is provided in this environment. Perhaps you are running on a JRE rather than a JDK ...

  3. Netty简单的重连机制

    其实重连机制并不是多么多高深的技术,其实就是一个在客户端做一个简单的判断,如果连接断了,那么就重新调用连接服务端的代码 当然,我们重连的动作肯定是发生在断连之后发生的,我们可以在上篇的心跳机制的基础上 ...

  4. K2 Blackpearl中从数据库直接删除流程实例之K2Server表

    转:http://www.cnblogs.com/dannyli/archive/2012/11/29/2794772.html /********************************** ...

  5. Spring定时器Quartz的使用

    在JavaEE系统中,我们会经常用到定时任务,比如每天凌晨生成前天报表,每一小时生成汇总数据等等,定时更新某某操作……. 我们可以使用java.util.Timer结合java.util.TimerT ...

  6. Thread(线程)三

    今天我们继续接着线程讲讲,上一章提到一下task概念, 首先接着task继续往下讲,在前章节提到过Thread怎么实现其他线程完成后再让主线程继续执行的功能,那么如果Task也需要线程等待事件,该怎么 ...

  7. kibana-4.6.3-linux-x86_64.tar.gz的安装(图文详解)(升级)

     前期博客 kibana-4.6.3-linux-x86_64.tar.gz的下载(图文详解) 因为,我的机器情况是如下: 1.上传 [hadoop@master app]$ rz [hadoop@m ...

  8. 安装mule-standalone说明

    1,将mule-standalone-3.4.0.zip 放到 /usr/local/ 下 2,unzip mule-standalone-3.4.0.zip 3, cd /usr/local/mul ...

  9. 操作SQL Server的帮助类

    可作为以后开发的参考代码,也可以再整理下,代码如下: using System; using System.Collections.Generic; using System.Linq; using ...

  10. SPI子系统分析之一:框架

    内核版本:3.9.5 SPI子系统概述: 一个SPI主控制器对应一条SPI总线,当然在系统中有唯一的总线编号. SPI总线上有两类设备: 其一是主控端,通常作为SOC系统的一个子模块出现,很多嵌入式M ...