深入浅出设计模式——解释器模式(Interpreter Pattern)

模式动机

如果在系统中某一特定类型的问题发生的频率很高,此时可以考虑将这些问题的实例表述为一个语言中的句子,因此可以构建一个解释器,该解释器通过解释这些句子来解决这些问题。
解释器模式描述了如何构成一个简单的语言解释器,主要应用在使用面向对象语言开发的编译器中。

模式定义
解释器模式(Interpreter Pattern) :定义语言的文法,并且建立一个解释器来解释该语言中的句子,这里的“语言”意思是使用规定格式和语法的代码,它是一种类行为型模式。
Interpreter Pattern: Given a language, define a representation for its grammar along with an interpreter that uses the representation to interpret sentences in the language.
Frequency of use: low
UML图

模式结构
解释器模式包含如下角色:
AbstractExpression: 抽象表达式
TerminalExpression: 终结符表达式
NonterminalExpression: 非终结符表达式
Context: 环境类
Client: 客户类

模式分析
解释器模式描述了如何为简单的语言定义一个文法,如何在该语言中表示一个句子,以及如何解释这些句子。
文法规则实例:
expression ::= value | symbol
symbol ::= expression ‘+‘ expression | expression ‘-‘ expression
value ::= an integer //一个整数值
在文法规则定义中可以使用一些符号来表示不同的含义,如使用“|”表示或,使用“{”和“}”表示组合,使用“*”表示出现0次或多次等,其中使用频率最高的符号是表示或关系的“|” 。

抽象语法树:
除了使用文法规则来定义一个语言,在解释器模式中还可以通过一种称之为抽象语法树(Abstract Syntax Tree, AST)的图形方式来直观地表示语言的构成,每一棵抽象语法树对应一个语言实例。

抽象语法树描述了如何构成一个复杂的句子,通过对抽象语法树的分析,可以识别出语言中的终结符和非终结符类。
在解释器模式中,每一种终结符和非终结符都有一个具体类与之对应,正因为使用类来表示每一个语法规则,使得系统具有较好的扩展性和灵活性。

模式实例与解析
以中英文翻译系统为例来介绍解释器模式
体系结构

AbstractExpression接口 IExpression.cs

using System.Text;

namespace InterpreterPattern
{
    //定义AbstractExpression接口
    interface IExpression
    {
        void Interpret(StringBuilder sb);
    }
}

具体的Expression WordExpression.cs

using System.Text;

namespace InterpreterPattern
{
    //定义具体的Expression,这里包括对英文单词的翻译和对英文句号的翻译。
    public class WordExpression : IExpression
    {
        private string _value;
        public WordExpression(string value)
        {
            _value = value;
        }
        public void Interpret(StringBuilder sb)
        {
            sb.Append(ChineseEnglishDict.GetEnglish(_value.ToLower()));
        }
    }
}

SymbolExpression.cs

using System.Text;

namespace InterpreterPattern
{
    //对英文句号的翻译
    public class SymbolExpression : IExpression
    {
        private string _value;
        public SymbolExpression(string value)
        {
            this._value = value;
        }

        public void Interpret(StringBuilder sb)
        {
            switch (_value)
            {
                case ".":
                    sb.Append("。");
                    break;
            }
        }
    }
}

Context: 环境类 ChineseEnglishDict.cs

using System.Collections.Generic;

namespace InterpreterPattern
{
    public static class ChineseEnglishDict
    {
        private static Dictionary<string, string> _dictory = new Dictionary<string, string>();

        static ChineseEnglishDict()
        {
            _dictory.Add("this", "这");
            _dictory.Add("is", "是");
            _dictory.Add("an", "一个");
            _dictory.Add("apple", "苹果");
        }
        public static string GetEnglish(string value)
        {
            return _dictory[value];
        }
    }
}

将各部分解释器组合起来进行包装,方便用户调用 Translator.cs

using System;
using System.Collections.Generic;
using System.Text;

namespace InterpreterPattern
{
    //将各部分解释器组合起来进行包装,方便用户调用。
    public static class Translator
    {
        public static string Translate(string sentense)
        {
            StringBuilder sb = new StringBuilder();
            List<IExpression> expressions = new List<IExpression>();
            string[] elements = sentense.Split(new char[] { ‘.‘ }, StringSplitOptions.RemoveEmptyEntries);
            foreach (string element in elements)
            {
                string[] words = element.Split(new char[] { ‘ ‘ }, StringSplitOptions.RemoveEmptyEntries);
                foreach (string word in words)
                {
                    expressions.Add(new WordExpression(word));
                }
                expressions.Add(new SymbolExpression("."));
            }
            foreach (IExpression expression in expressions)
            {
                expression.Interpret(sb);
            }
            return sb.ToString();
        }
    }
}

Client:客户类

using System;

namespace InterpreterPattern
{
    class Program
    {
        static void Main(string[] args)
        {
            string englist = "This is an apple.";
            string chinese = Translator.Translate(englist);
            Console.WriteLine(chinese);
            Console.Read();
        }
    }
}

模式优缺点
解释器模式的优点
易于改变和扩展文法。
易于实现文法。
增加了新的解释表达式的方式。
解释器模式的缺点
对于复杂文法难以维护。
执行效率较低。
应用场景很有限。

模式适用环境
在以下情况下可以使用解释器模式:
可以将一个需要解释执行的语言中的句子表示为一个抽象语法树。
一些重复出现的问题可以用一种简单的语言来进行表达。
文法较为简单。
效率不是关键问题。

【声明与感谢】
本文,站在许多巨人的肩膀上,借鉴和引用了许多他人拥有版权的作品或著述,在此,对前人们的贡献致谢。并同时公布引用的内容、原作者或来源(一些来源于互联网的内容本人无法追述本源,深表遗憾)。

【参考文献】
《设计模式—可复用面向对象软件的基础》作者: [美] Erich Gamma / Richard Helm / Ralph Johnson / John Vlissides 译者: 李英军 / 马晓星 / 蔡敏 / 刘建中 等 机械工业出版社
《重构—改善既有代码的设计》作者: Martin Fowler译者:候捷 中国电力出版社
《敏捷软件开发—原则、模式与实践》作者: Robert C. Martin 清华大学出版社
《程序员修炼之道—从小工到专家》作者: Andrew Hunt / David Thomas 电子工业出版社
《Head First 设计模式》作者: 弗里曼 译者: O‘Reilly Taiwan公司 中国电力出版社
《设计模式之禅》 作者: 秦小波 机械工业出版社
MSDN WebCast 《C#面向对象设计模式纵横谈》 讲师:李建忠
刘伟. 设计模式. 北京:清华大学出版社, 2011.
刘伟. 设计模式实训教程. 北京:清华大学出版社, 2012.
《大话设计模式》 作者: 程杰 清华大学出版社
《C#图解教程》作者: 索利斯 译者: 苏林 / 朱晔 人民邮电出版社
《你必须知道的.NET》作者: 王涛
《项目中的.NET》作者: 李天平 电子工业出版社
《Microsoft .NET企业级应用架构设计》作者: (美)埃斯波西托等编著 译者: 陈黎夫
http://www.dofactory.com/Patterns/Patterns.aspx .NET Design Patterns
http://www.cnblogs.com/zhenyulu 博客作者:吕震宇
http://www.cnblogs.com/terrylee 博客作者:李会军
http://www.cnblogs.com/anlyren/ 博客作者:anlyren
http://www.cnblogs.com/idior 博客作者:idior
http://www.cnblogs.com/allenlooplee 博客作者:Allen lee
http://blog.csdn.net/ai92 博客作者:ai92
http://www.cnblogs.com/umlonline/ 博客作者:张传波
http://www.cnblogs.com/lovecherry/ 博客作者:LoveCherry

时间: 2024-10-04 13:11:37

深入浅出设计模式——解释器模式(Interpreter Pattern)的相关文章

C#设计模式:解释器模式(Interpreter Pattern)

一,C#设计模式:解释器模式(Interpreter Pattern) 1,解释器模式的应用场合是Interpreter模式应用中的难点,只有满足“业务规则频繁变化,且类似的模式不断重复出现,并且容易抽象为语法规则的问题”才适合使用解释器模式2,解释器设计模式每个解释的类有自己的规则,并且与其他业务规则不冲突 二,如下代码 using System; using System.Collections.Generic; using System.Linq; using System.Text; u

二十四种设计模式:解释器模式(Interpreter Pattern)

解释器模式(Interpreter Pattern) 介绍给定一个语言, 定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子. 示例有一个Message实体类,某个类对它的操作有Get()方法.现在要求用具有某一规则的中文语法来执行这个操作. MessageModel using System; using System.Collections.Generic; using System.Text; namespace Pattern.Interpreter { //

设计模式(行为型)之解释器模式(Interpreter Pattern)

PS一句:最终还是选择CSDN来整理发表这几年的知识点,该文章平行迁移到CSDN.因为CSDN也支持MarkDown语法了,牛逼啊! [工匠若水 http://blog.csdn.net/yanbober] 阅读前一篇<设计模式(行为型)之访问者模式(Visitor Pattern)>http://blog.csdn.net/yanbober/article/details/45536787 概述 解释器模式是类的行为模式.给定一个语言之后,解释器模式可以定义出其文法的一种表示,并同时提供一个

[设计模式] 解释器模式 Interpreter

在GOF的<设计模式:可复用面向对象软件的基础>一书中对解释器模式是这样说的:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子.如果一种特定类型的问题发生的频率足够高,那么可能就值得将该问题的各个实例表述为一个简单语言中的句子.这样就可以构建一个解释器,该解释器通过解释这些句子来解决该问题. 就如上面说的那个游戏,我输入up walk 5,我必须按照:移动方向+移动方式+移动距离这种格式输入我的指令,而这种格式的指令就是一种文法,只有按照了我定义的

原始的解释器模式(Interpreter Pattern)

解释器模式的定义(现实项目中很少遇到,因此直接理论先...) 解释器模式是一种按照规定语法进行解析的方案,在现在项目中使用较少,其定义为:给定一门语言,定义它的方法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子.其构成如下: 1.AbstractExpression--抽象解释器 具体的解释任务由各个实现类完成,具体的解释器分别由TerminalExpression和NonterminalExpression完成 2.TerminalExpression--终结符表达式 实现

设计模式之解释器模式(Interpreter)摘录

23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式抽象了实例化过程,它们帮助一个系统独立于如何创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而一个对象创建型模式将实例化委托给另一个对象.创建型模式有两个不断出现的主旋律.第一,它们都将关于该系统使用哪些具体的类的信息封装起来.第二,它们隐藏了这些类的实例是如何被创建和放在一起的.整个系统关于这些对象所知道的是由抽象类所定义的接口.因此,创建型模式在什么被创建,谁创建它,它是怎样被创建的,以

解释器模式 Interpreter 行为型 设计模式(十九)

解释器模式(Interpreter) 考虑上图中计算器的例子 设计可以用于计算加减运算(简单起见,省略乘除),你会怎么做? 你可能会定义一个工具类,工具类中有N多静态方法 比如定义了两个方法用于计算a+b 和 a+b-c public static int add(int a,int b){ return a+b; } public static int add(int a,int b,int c){ return a+b-c; } 但是很明显,如果形式有限,那么可以针对对应的形式进行编程 如果

设计模式 - 代理模式(proxy pattern) 未使用代理模式 详解

代理模式(proxy pattern) 未使用代理模式 详解 本文地址: http://blog.csdn.net/caroline_wendy 部分代码参考: http://blog.csdn.net/caroline_wendy/article/details/37698747 如果需要监控(monitor)类的某些状态, 则需要编写一个监控类, 并同过监控类进行监控. 但仅仅局限于本地, 如果需要远程监控, 则需要使用代理模式(proxy pattern). 具体方法: 1. 类中需要提供

设计模式 - 迭代器模式(iterator pattern) Java 迭代器(Iterator) 详解

迭代器模式(iterator pattern) Java 迭代器(Iterator) 详解 本文地址: http://blog.csdn.net/caroline_wendy 参考迭代器模式(iterator pattern): http://blog.csdn.net/caroline_wendy/article/details/35254643 Java的标准库(util)中包含迭代器接口(iterator interface), import java.util.Iterator; 继承(