中介者模式与解释器模式(2)

三、中介者模式在源码中的应用

首先来看JDK中的Timer类 ,打开Timer的结构我们发现Timer类中有很多的schedule() 重载方法,如下图:


中介者模式与解释器模式(2)


我们任意点开其中一个方法,发现所有方法最终都是调用了私有的sched()方法,我们来看 —下它的源码: ::


 public class Timer {
     public void schedule(TimerTask task, long delay, long period) {
         if (delay < 0)
             throw new IllegalArgumentException("Negative delay.");
         if (period <= 0)
             throw new IllegalArgumentException("Non-positive period.");
         sched(task, System.currentTimeMillis()+delay, -period);
     }
     
     private void sched(TimerTask task, long time, long period) {
         if (time < 0)
             throw new IllegalArgumentException("Illegal execution time.");
         // Constrain value of period sufficiently to prevent numeric
         // overflow while still being effectively infinitely large.
         if (Math.abs(period) > (Long.MAX_VALUE >> 1))
             period >>= 1;
         synchronized(queue) {
             if (!thread.newTasksMayBeScheduled)
                 throw new IllegalStateException("Timer already cancelled.");
             synchronized(task.lock) {
                 if (task.state != TimerTask.VIRGIN)
                     throw new IllegalStateException(
                         "Task already scheduled or cancelled");
                 task.nextExecutionTime = time;
                 task.period = period;
                 task.state = TimerTask.SCHEDULED;
             }
             queue.add(task);
             if (queue.getMin() == task)
                 queue.notify();
         }
     }
 }    


而且,我们发现,不管是什么样的任务都被加入到一个队列中顺序执行。我们把这个队列中 的所有对象称之为"同事”。同事之间通信都是通过Timer来协调完成的,Timer就承担了中 介者的角色。


四、解释器模式

解释器模式(Interpreter Pattern) 是指给定一门语言, 定义它的语法的一种表示, 并定义一个解释器,该解释器使用该表示来解释语言中的句子。是一种按照规定的语法进行解析的模式,属于行为型模式。


就比如编译器可以将源码编译解释为机器码, 让CPU能进行识别并运行。解释器模式的作用其实与编译器一样,都是将一些固定的语法进行解释,构建出一个解释句子的解释器。简单理解,解释器是一个简单语法分析工具,它可以识别句子语义,分离终结符号和非


终结符号,提取出需要的信息,让我们能针对不同的信息做出相应的处理。其核心思想是识别语法,构建解释。


解释器模式的应用场景:


其实我们每天都生活在解释器模式中,我们平时所听到的音乐都可以通过简谱记录下来;还有战争年代发明的摩尔斯电码(又译为摩斯密码, Morsecode) , 其实也是一种解释器。我们的程序中,如果存在一种特定类型的问题,该类型问题涉及多个不同实例,但是具备固定语法描述,那么可以使用解释器模式对该类型问题进行解释,分离出需要的信息,根据获取的信息做出相应的处理。简而言之,对于一些固定语法构建一个解释句子的解释器。解释器模式适用于以下应用场景:


一些重复出现的问题可以用一种简单的语言来进行表达;


一个简单语法需要解释的场景。


解释器模式主要包含四种角色:



1.抽象表达式(Expression) :负责定义一个解释方法interpret, 交由具体子类进行具体解释;


2.终结符表达式(Terminal Expression) :实现文法中与终结符有关的解释操作。文法中的每一个终结符都有一个具体终结表达式与之相对应,比如公式R=R1+R2,R1和R2就是终结符,对应的解析R1和R2的解释器就是终结符表达式。通常一个解释器模式中只有一个终结符表达式,但有多个实例,对应不同的终结符(R1,R2);


3.非终结符表达式(Nonterminal Expression) :实现文法中与非终结符有关的解释操作。文法中的每条规则都对应于一个非终结符表达式。非终结符表达式一般是文法中的运算符或者其他关键字,比如公式R=R1+R2中, “+”就是非终结符,解析“+”的解释器就是一个非终结符表达式。非终结符表达式根据逻辑的复杂程度而增加,原则上每个文法规则都对应一个非终结符表达式;


4.上下文环境类(Context) :包含解释器之外的全局信息。它的任务一般是用来存放文法中各个终结符所对应的具体值,比如R=R1+R2,给R1赋值100,给R2赋值200,这些信息需要存放到环境中。


五、解释器模式的实例


下面我们用解释器模式来实现一个数学表达式计算器,包含加减乘除运算。首先定义抽象表达式角色IArithmeticInterpreter接口:



public interface IArithmeticInterpreter {

    int interpret();
}


创建终结表达式角色AbstractInterpreter抽象类:


public abstract class AbstractInterpreter implements IArithmeticInterpreter {

    protected IArithmeticInterpreter left;
    protected IArithmeticInterpreter right;

    public AbstractInterpreter(IArithmeticInterpreter left, IArithmeticInterpreter right) {
        this.left = left;
        this.right = right;
    }
}


分别创建非终结表达式角色加、减、乘、除解释器:


//加
public class AddInterpreter extends AbstractInterpreter {
    public AddInterpreter(IArithmeticInterpreter left, IArithmeticInterpreter right) {
        super(left, right);
    }
    public int interpret() {
        return this.left.interpret() + this.right.interpret();
    }
}
//减
public class SubInterpreter extends AbstractInterpreter {
    public SubInterpreter(IArithmeticInterpreter left, IArithmeticInterpreter right) {
        super(left, right);
    }
    public int interpret() {
        return this.left.interpret() - this.right.interpret();
    }
}
//乘
public class MultiInterpreter extends AbstractInterpreter {
    public MultiInterpreter(IArithmeticInterpreter left, IArithmeticInterpreter right){
        super(left,right);
    }
    public int interpret() {
        return this.left.interpret() * this.right.interpret();
    }
}
//除
public class DivInterpreter extends AbstractInterpreter {
    public DivInterpreter(IArithmeticInterpreter left, IArithmeticInterpreter right){
        super(left,right);
    }
    public int interpret() {
        return this.left.interpret() / this.right.interpret();
    }
}
上一篇:冬季实战营第二期:Linux操作系统实战入门之超实用 Linux 常用命令


下一篇:Mac OS X El Capitan系统完整性保护System Integrity Protection (SIP)