23种设计模式之_解释器模式

By | 03月02日
Advertisement

定义:给定一种语言,定义他的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中句子。
类型:行为类模式
类图:

23种设计模式之_解释器模式


解释器模式的结构

抽象解释器:声明一个所有具体表达式都要实现的抽象接口(或者抽象类),接口中主要是一个interpret()方法,称为解释操作。具体解释任务由它的各个实现类来完成,具体的解释器分别由终结符解释器TerminalExpression和非终结符解释器NonterminalExpression完成。
终结符表达式:实现与文法中的元素相关联的解释操作,通常一个解释器模式中只有一个终结符表达式,但有多个实例,对应不同的终结符。终结符一半是文法中的运算单元,比如有一个简单的公式R=R1+R2,在里面R1和R2就是终结符,对应的解析R1和R2的解释器就是终结符表达式。
非终结符表达式:文法中的每条规则对应于一个非终结符表达式,非终结符表达式一般是文法中的运算符或者其他关键字,比如公式R=R1+R2中,+就是非终结符,解析+的解释器就是一个非终结符表达式。非终结符表达式根据逻辑的复杂程度而增加,原则上每个文法规则都对应一个非终结符表达式。
环境角色:这个角色的任务一般是用来存放文法中各个终结符所对应的具体值,比如R=R1+R2,我们给R1赋值100,给R2赋值200。这些信息需要存放到环境角色中,很多情况下我们使用Map来充当环境角色就足够了。

 class Context {}
    abstract class Expression {
        public abstract Object interpreter(Context ctx);
    }
  class TerminalExpression extends Expression {
        public Object interpreter(Context ctx){
            return null;
        }
    }
    class NonterminalExpression extends Expression {
        public NonterminalExpression(Expression...expressions){

        }
        public Object interpreter(Context ctx){
            return null;
        }
    }
    public class Client {
        public static void main(String[] args){
            String expression = "";
            char[] charArray = expression.toCharArray();
            Context ctx = new Context();
            Stack stack = new Stack();
            for(int i=0;i
             //进行语法判断,递归调用
        }
        Expression exp = stack.pop();
        exp.interpreter(ctx);
    }
}

文法递归的代码部分需要根据具体的情况来实现,因此在代码中没有体现。抽象表达式是生成语法集合的关键,每个非终结符表达式解释一个最小的语法单元,然后通过递归的方式将这些语法单元组合成完整的文法,这就是解释器模式。

解释器模式的优缺点

解释器是一个简单的语法分析工具,它最显著的优点就是扩展性,修改语法规则只需要修改相应的非终结符就可以了,若扩展语法,只需要增加非终结符类就可以了。
但是,解释器模式会引起类的膨胀,每个语法都需要产生一个非终结符表达式,语法规则比较复杂时,就可能产生大量的类文件,为维护带来非常多的麻烦。同时,由于采用递归调用方法,每个非终结符表达式只关心与自己相关的表达式,每个表达式需要知道最终的结果,必须通过递归方式,无论是面向对象的语言还是面向过程的语言,递归都是一个不推荐的方式。由于使用了大量的循环和递归,效率是一个不容忽视的问题。特别是用于解释一个解析复杂、冗长的语法时,效率是难以忍受的。

解释器模式的适用场景

在以下情况下可以使用解释器模式:
有一个简单的语法规则,比如一个sql语句,如果我们需要根据sql语句进行rm转换,就可以使用解释器模式来对语句进行解释。
一些重复发生的问题,比如加减乘除四则运算,但是公式每次都不同,有时是a+b-cd,有时是ab+c-d,等等等等个,公式千变万化,但是都是由加减乘除四个非终结符来连接的,这时我们就可以使用解释器模式。
注意事项
解释器模式真的是一个比较少用的模式,因为对它的维护实在是太麻烦了,想象一下,一坨一坨的非终结符解释器,假如不是事先对文法的规则了如指掌,或者是文法特别简单,则很难读懂它的逻辑。解释器模式在实际的系统开发中使用的很少,因为他会引起效率、性能以及维护等问题。

引用:
https://wiki.jikexueyuan.com/project/java-design-pattern/interpreter-pattern.html

Similar Posts:

  • 23种设计模式4--行为型模式(策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式)

    总体来说设计模式分为三大类: 创建型模式,共五种:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式. 结构型模式,共七种:适配器模式.装饰器模式.代理模式.外观模式.桥接模式.组合模式.享元模式. 行为型模式,共十一种:策略模式.模板方法模式.观察者模式.迭代子模式.责任链模式.命令模式.备忘录模式.状态模式.访问者模式.中介者模式.解释器模式. 其实还有两类:并发型模式和线程池模式. 关系模式(11种) 先来张图,看看这11中模式的关系: 第一类:通过父类与子类的关系进行实现. 第二

  • 23种设计模式(8)_结构型_装饰者模式(Decorator Pattern)

    一.引言 在软件开发中,我们经常想要对一类对象添加不同的功能,例如要给手机添加贴膜,手机挂件,手机外壳等,如果此时利用继承来实现的话,就需要定义无数的类,如StickerPhone(贴膜是手机类).AccessoriesPhone(挂件手机类)等,这样就会导致 "子类爆炸"问题,为了解决这个问题,我们可以使用装饰者模式来动态地给一个对象添加额外的职责.下面让我们看看装饰者模式. 二.装饰者模式的详细介绍 2.1 定义 装饰者模式以对客户透明的方式动态地给一个对象附加上更多的责任,装饰者

  • 使用Object-C实现23种设计模式之装饰器模式

    谈到装饰器模式,首先先引入一个定义:装饰模式是在不必改变原类文件和使用继承的情况下,动态的扩展一个对象的功能.他是通过创建一个包装对象,也就是装饰来包括真实的对象. 这个定义怎么去理解?首先从定义中提取几个关键词:原类和包装对象. 装饰模式的实现可以采用继承原类,但更好的方法是原类和包装对象实现统一接口(协议),即两者在根源上属于同类. 下面,看这么一个实例,某房地产公司有这么一个制度,开发的房子在客户购买之前一律不装饰,客户交完定金之后开始按照客户意愿进行装饰. 好,接下来,具体分析一下这个例

  • 23种设计模式之工厂方法模式

    原文:http://www.codeceo.com/article/23-design-parttens-factory-partten.html 定义:定义一个用于创建对象的接口,让子类决定实例化哪一个类,工厂方法使一个类的实例化延迟到其子类. 类型:创建类模式 类图: 工厂方法模式代码 interface IProduct { public void productMethod(); } class Product implements IProduct { public void prod

  • Java编程23种设计模式之普通工厂模式

    1.工厂方法模式(Factory Method) 工厂方法模式分为三种: 1.1.普通工厂模式,就是建立一个工厂类,对实现了同一接口的一些类进行实例的创建. 举例如下:(我们举一个推送信息的例子) 创建推送接口 public interface InfoSender { //创建推送接口 public void send(); } 创建各种推送实现类: =======邮箱推送 public class MailSend implements InfoSender { // 邮箱推送 @Overr

  • java中23种设计模式之10-桥梁模式(bridge pattern)

    [GOF95]在提出桥梁模式的时候指出,桥梁模式的用意是"将抽象化(Abstraction)与实现化(Implementation)脱耦,使得二者可以独立地变化".这句话有三个关键词,也就是抽象化.实现化和脱耦. 抽象化: 存在于多个实体中的共同的概念性联系,就是抽象化.作为一个过程,抽象化就是忽略一些信息,从而把不同的实体当做同样的实体对待[LISKOV94]. 实现化: 抽象化给出的具体实现,就是实现化. 脱耦: 所谓耦合,就是两个实体的行为的某种强关联.而将它们的强关联去掉,就是

  • 23种设计模式之中介者模式1

    用来解决上述问题的一个合理的解决方案就是中介者模式.那么什么是中介者模式呢? (1)中介者模式定义 (2)应用中介者模式来解决的思路 仔细分析上面的问题,根本原因就在于多个对象需要相互交互,从而导致对象之间紧密耦合,这就不利于对象的修改和维护. 中介者模式的解决思路很简单,跟电脑的例子一样,中介者模式通过引入一个中介对象,让其它的对象都只和中介对象交互,而中介对象知道如何和其它所有的对象交互,这样对象之间的交互关系就没有了,从而实现对象之间的解耦. 对于中介对象而言,所有相互交互的对象,被视为同

  • 23种设计模式之中介者模式

    定义:用一个中介者对象封装一系列的对象交互,中介者使各对象不需要显示地相互作用,从而使耦合松散,而且可以独立地改变它们之间的交互. 类型:行为类模式 类图: 中介者模式的结构 中介者模式又称为调停者模式,从类图中看,共分为3部分: 抽象中介者:定义好同事类对象到中介者对象的接口,用于各个同事类之间的通信.一般包括一个或几个抽象的事件方法,并由子类去实现. 中介者实现类:从抽象中介者继承而来,实现抽象中介者中定义的事件方法.从一个同事类接收消息,然后通过消息影响其他同时类. 同事类:如果一个对象会

  • 23种设计模式 第二部分 结构模式(7)享元模式

    理解 享元(Flyweight)模式,顾名思义,和分享有关.享元模式可实现对象的共享,即共享池. 当对象多内存小,可以共享降低内存的开销,通常与工厂模式一起使用. 维基百科 A flyweight is an object that minimizes memory use by sharing as much data as possible with other similar objects; it is a way to use objects in large numbers when

  • 23种设计模式之--抽象工厂模式

    女娲的失误: 工厂方法模式中讲了女娲造人的故事.人是造出来了,世界也热闹了,可以低头一看,都是清一色的类型, 缺少关爱.仇恨.喜怒哀乐等情绪,人类的生命太平淡了,女娲一想,猛然一拍脑袋,忘记给人类定义性别了,那怎么办呢? 八卦炉分为两个,一个用于造女人,一个用于造男人,有了性别,就有了爱情,也就有了丰富的人生. public interface Human { void getColor(); void talk(); void getSex(); } public abstract class

Tags: