⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 interpreterpattern.htm

📁 DesignPattern基于Java方面最好的书
💻 HTM
📖 第 1 页 / 共 2 页
字号:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>





  
  
  
  
  
  <link rel="stylesheet" href="css/stdlayout.css" type="text/css">





  
  
  
  
  
  <link rel="stylesheet" href="css/print.css" type="text/css">





  
  
  
  
  
  <meta content="text/html; charset=gb2312" http-equiv="content-type">





  
  
  
  
  
  <title>Interpreter 模式</title>
</head>


<body>





<h3><a href="http://caterpillar.onlyfun.net/GossipCN/index.html">From
Gossip@caterpillar</a></h3>





<h1><a href="CppGossip.html">Design Pattern:&nbsp;Interpreter 模式</a></h1>

对于一个具有层次节点关系的问题来说,如果您要剖析每一个节点,您可以使用Interpreter模式,直译器模式有些类似演算法中的个别击破方式,对每一个父节点我们剖析出其子节点组合,然而交给子节点剖析物件继续剖析,直到剖析至终端节点为止。<br>
<br>
举个例子来说明好了,先说明的是,这个例子是改写自 <a href="http://www.drmaster.com.tw/info.asp?NO=PG20214">Design Patterns于Java语言之实习应用</a> 第23章的范例,我将之更简化了,以让大家将焦点能集中在如何使用Interpreter模式,以及如何实用。<br>
<br>
假设您要实作一个Interpreter,这个Interpreter可以直译您文字档中的程式,并依您自订的程式文法来执行程式,几个简单的程式如下:<br>
<div style="margin-left: 40px;"><span style="font-weight: bold; font-family: Courier New,Courier,monospace;">PROGRAM </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;">&nbsp;&nbsp;&nbsp; PRINT dog SPACE </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;">&nbsp;&nbsp;&nbsp; PRINT is SPACE </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;">&nbsp;&nbsp;&nbsp; PRINT an SPACE </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;">&nbsp;&nbsp;&nbsp; PRINT animai </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;">END </span><br>
</div>
&nbsp;<br>
您的这式程个会印出"dog is an animal"的文字,再来一个例子是:<br>
<div style="margin-left: 40px;"><span style="font-weight: bold; font-family: Courier New,Courier,monospace;">PROGRAM </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;">&nbsp;&nbsp;&nbsp; REPEAT 2 </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LINEBREAK </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PRINT dog </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BREAK </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;">&nbsp;&nbsp;&nbsp; END </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;">END</span><br>
</div>
&nbsp;<br>
<br>
这个程式要印出:<br>
<table style="text-align: left; background-color: rgb(0, 0, 0); width: 963px; height: 32px; font-family: Times New Roman,Times,serif; color: rgb(255, 255, 255);" border="0" cellpadding="2" cellspacing="2">
  <tbody>
    <tr>
      <td><small>------------------------------ <br style="font-weight: bold;">
&nbsp;dog <br style="font-weight: bold;">
------------------------------ <br style="font-weight: bold;">
&nbsp;dog</small></td>
    </tr>
  </tbody>
</table>
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;"></span><span style="font-weight: bold; font-family: Courier New,Courier,monospace;"></span><br>
您也可以任意的组合程式,例如:<br>
<div style="margin-left: 40px;"><span style="font-weight: bold; font-family: Courier New,Courier,monospace;">PROGRAM </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;">&nbsp;&nbsp;&nbsp; PRINT begin </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;">&nbsp;&nbsp;&nbsp; BREAK </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;">&nbsp;&nbsp;&nbsp; REPEAT 3 </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; REPEAT 2 </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PRINT dog SPACE </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PRINT is SPACE </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PRINT a SPACE </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PRINT animal </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BREAK </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; END </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;">&nbsp;&nbsp;&nbsp; END </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;">END</span><br>
</div>
&nbsp;<br>
<br>
这个程式中的几个关键字是PROGRAM、PRINT、SPACE、BREAK、LINEBREAK、REPEAT、END,
PROGRAM是表示程式开始,以END作结,PRINT可以印出一个无空白的字串,SPACE印出一个空白,BREAK是换行,而LINEBREAK是
画一个直线并换行,REPEAT是回圈指令,可以指定回圈次数,以END作结。<br>
<br>
观察程式,可以制定出以下的文法,如下:<br>
<div style="margin-left: 40px;"><span style="font-weight: bold; font-family: Courier New,Courier,monospace;">&lt;program&gt; ::= PROGRAM &lt;command list&gt; </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;">&lt;command list&gt; ::= &lt;command&gt;* END </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;">&lt;command&gt; ::= &lt;repeat command&gt; | &lt;primitive command&gt; </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;">&lt;repeat command&gt; ::= REPEAT &lt;number&gt; &lt;command list&gt; </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;">&lt;primitive command&gt; ::= PRINT &lt;string&gt; </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
| BREAK | SPACE | LINEBREAK</span><br>
</div>
&nbsp;<br>
<br>
程式文法制定需要对程式进行语句分析与定义,在这边并不讨论这个课题,在程式中,command节点由primitive或repeat两个节点任意组
合,一个command list节点则是零个以上的command节点组合而成,其中repeat还可以组合command
list节点,这是组合模式的应用,可以在程式中组合巢状回圈。<br>
<br>
在直译程式时,以读到PROGRAM作为开始节点,接下来我们剖析程式为command list 节点,并将它们丢给专门剖析command
list的物件继续剖析,这个物件将之分析,看是不是有repeat command或primitive
command节点,如果有就再往下交由专属物件进行剖析,如此层层剥开,并由专属物件负责剖析工作。<br>
<br>
Interpreter模式的基本观念就如上所示,先来看看如何以程式实现剖析的过程,下面这个程式会剖析您的程式,并将程式加上对应的括号来将同一个区块组合起来,以表示它完成剖析之后的结果:<br>
<ul>
  <li> INode.java
  </li>
</ul>

<pre>public interface INode { <br>    public void parse(Context context); <br>} <br></pre>

<br>

<ul>
  <li> ProgramNode.java
  </li>
</ul>

<pre>// &lt;program&gt; ::= PROGRAM &lt;command list&gt; <br>public class ProgramNode implements INode { <br>    private INode commandListNode; <br>    public void parse(Context context) { <br>        context.skipToken("PROGRAM"); <br>        commandListNode = new CommandListNode(); <br>        commandListNode.parse(context); <br>    } <br><br>    public String toString() { <br>        return "[PROGRAM " + commandListNode + "]"; <br>    } <br>}  <br></pre>

<br>

<ul>
  <li> CommandListNode.java
  </li>
</ul>

<pre>import java.util.Vector; <br><br>// &lt;command list&gt; ::= &lt;command&gt;* END <br>public class CommandListNode implements INode { <br>    private Vector list = new Vector();<br><br>    public void parse(Context context) { <br>        while (true) { <br>            if (context.currentToken() == null) { <br>                System.err.println("Missing 'END'"); <br>                 break; <br>            } else if (<br>                    context.currentToken().equals("END")) { <br>                context.skipToken("END"); <br>                break; <br>            } else { <br>                INode commandNode = new CommandNode(); <br>                commandNode.parse(context); <br>                list.add(commandNode); <br>            } <br>        } <br>    }<br><br>    public String toString() { <br>        return "" + list; <br>    } <br>}  <br></pre>

<br>

<ul>
  <li> CommandNode.java
  </li>
</ul>

<pre>// &lt;command&gt; ::= &lt;repeat command&gt; | &lt;primitive command&gt; <br>public class CommandNode implements INode { <br>    private INode node;<br><br>    public void parse(Context context) { <br>        if (context.currentToken().equals("REPEAT")) { <br>            node = new RepeatCommandNode(); <br>            node.parse(context); <br>        } else { <br>            node = new PrimitiveCommandNode(); <br>            node.parse(context); <br>        } <br>    }<br><br>    public String toString() { <br>        return node.toString(); <br>    } <br>}  <br></pre>

<br>

<ul>
  <li> RepeatCommandNode.java
  </li>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -