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

📄 interpreterpattern.htm

📁 DesignPattern基于Java方面最好的书
💻 HTM
📖 第 1 页 / 共 2 页
字号:
</ul>

<pre>public class RepeatCommandNode implements INode { <br>    private int number; <br>    private INode commandListNode; <br><br>    public void parse(Context context) { <br>        context.skipToken("REPEAT"); <br>        number = context.currentNumber(); <br>        context.nextToken(); <br>        commandListNode = new CommandListNode(); <br>        commandListNode.parse(context); <br>    }<br><br>    public String toString() {<br>        return "[REPEAT " + number + " " <br>                  + commandListNode + "]"; <br>    } <br>}<br></pre>

<br>

<ul>
  <li> PrimitiveCommandNode.java
  </li>
</ul>

<pre>// &lt;primitive command&gt; ::= PRINT &lt;string&gt; <br>//                           | SPACE | BREAK | LINEBREAK <br>public class PrimitiveCommandNode implements INode {<br>    private String name;<br>    private String text;<br><br>    public void parse(Context context) { <br>        name = context.currentToken(); <br>        context.skipToken(name); <br>        if (!name.equals("PRINT") &amp;&amp; !name.equals("BREAK") <br>             &amp;&amp; !name.equals("LINEBREAK") <br>             &amp;&amp; !name.equals("SPACE")) { <br>            System.err.println("Undefined Command"); <br>        }<br><br>        if (name.equals("PRINT")) { <br>            text = context.currentToken(); <br>            name += text; <br>            context.nextToken(); <br>        } <br>    }<br><br>    public String toString() { <br>        return name; <br>    } <br>}  <br></pre>

<br>

<ul>
  <li> Context.java
  </li>
</ul>

<pre>import java.util.*; <br><br>public class Context { <br>    private StringTokenizer tokenizer; <br>    private String currentToken; <br><br>    public Context(String text) { <br>        tokenizer = new StringTokenizer(text); <br>        nextToken(); <br>    } <br><br>    public String nextToken() { <br>        if (tokenizer.hasMoreTokens()) { <br>            currentToken = tokenizer.nextToken(); <br>        } else { <br>            currentToken = null; <br>        } <br>        return currentToken; <br>    } <br><br>    public String currentToken() { <br>        return currentToken; <br>    } <br><br>    public void skipToken(String token) { <br>        if (!token.equals(currentToken)) { <br>            System.err.println("Warning: " + token + <br>                          " is expected, but " + <br>                          currentToken + " is found."); <br>        } <br>        nextToken(); <br>    } <br><br>    public int currentNumber() { <br>        int number = 0; <br>        try { <br>            number = Integer.parseInt(currentToken); <br>        } catch (NumberFormatException e) { <br>            System.err.println("Warning: " + e); <br>        } <br>        return number; <br>    } <br>}  <br></pre>

<br>

<ul>
  <li> Main.java
  </li>
</ul>

<pre>import java.util.*; <br>import java.io.*;<br><br>public class Main { <br>    public static void main(String[] args) { <br>        try { <br>            BufferedReader reader = new <br>                  BufferedReader(new FileReader(args[0])); <br>            String text; <br>            while ((text = reader.readLine()) != null) { <br>                System.out.println("text = \"" + <br>                                       text + "\""); <br>                INode node = new ProgramNode(); <br>                node.parse(new Context(text)); <br>                System.out.println("node = " + node); <br>            } <br>        } <br>        catch (ArrayIndexOutOfBoundsException e) { <br>            System.err.println(<br>                   "Usage: java Main yourprogram.txt"); <br>        } <br>        catch (Exception e) { <br>            e.printStackTrace(); <br>        } <br>    } <br>} </pre>
<br>
假设您的程式是这样写的:<br>
<ul>
  <li>program.txt</li>
</ul>
<pre>PROGRAM PRINT xxx END<br>PROGRAM REPEAT 4 PRINT xxx END END <br>PROGRAM REPEAT 4 PRINT xxx PRINT "yyy" END END</pre>
<br>

则执行Intrepreter程式之后会是:<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>&nbsp;$ java Main program.txt <br>
&nbsp;text = "PROGRAM PRINT xxx END" <br>
&nbsp;node = [PROGRAM [PRINTxxx]] <br>
      <br>
&nbsp;text = "PROGRAM REPEAT 4 PRINT xxx END END" <br>
&nbsp;node = [PROGRAM [[REPEAT 4 [PRINTxxx]]]] <br>
      <br>
&nbsp;text = "PROGRAM REPEAT 4 PRINT xxx PRINT "yyy" END END" <br>
&nbsp;node = [PROGRAM [[REPEAT 4 [PRINTxxx, PRINT"yyy"]]]]</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>
这个范例程式基本上已经显示了直译器模式的工作原理,如何让程式直译之后能够工作,这待会再示范,先来看一下Intrepreter模式的 UML&nbsp;类别结构图: <br>
<div style="text-align: center;"><img style="width: 444px; height: 204px;" alt="Intrepreter" title="Intrepreter" src="images/interpreter-1.jpg"><br>
</div>
<br>
TerminalExpression就像我们的primitive
command,再剖析下去已经没有子节点了,而NonterminalExpression就像是repeat
command,注意到其中也使用了组合模式,就如之前所说的,组合模式让可以递回的组合句子为更复杂的语句。<br>
<br>
您已经会剖析句子了,接下来要如何让这个直译器真正工作,虽然程式中使用toString()来表示每一个节点的剖析结果,但事实上,这个程式也已经说明
了如何让剖析的结果真正运作了,既然已经记录好剖析之后的语句顺序了,只要由上而下追踪剖析结果,就一定可以执行到 primitive
command,且顺序符合自订的程式原始码的需求,这只要将toString()改为execute(),并作一些转发与重复执行的修改就可以了,直接
来看程式会比较容易理解:<br>
<ul>
  <li> <span class="createlink">INode</span>.java
  </li>
</ul>

<pre>public interface INode {<br>    public void parse(Context context);<br>    public void execute();<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><br>    public void parse(Context context) {<br>        context.skipToken("PROGRAM");<br>        commandListNode = new CommandListNode();<br>        commandListNode.parse(context);<br>    }<br><br>    public void execute() {<br>        commandListNode.execute();<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.*;    <br><br>// &lt;command list&gt; ::= &lt;command&gt;* END<br>public class CommandListNode implements INode {<br>    private Vector list = new Vector();<br>    private INode commandNode;<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(context.currentToken().equals("END")) {<br>                context.skipToken("END");<br>                break;<br>            } else {<br>                commandNode = new CommandNode();<br>                commandNode.parse(context);<br>                list.add(commandNode);<br>            }<br>        }<br>    }<br><br>    public void execute() {<br>        Iterator it = list.iterator();<br>        while (it.hasNext()) {<br>            ((CommandNode)it.next()).execute();<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 void execute() {<br>        node.execute();<br>    }<br><br>    public String toString() {<br>        return node.toString();<br>    }<br>} <br></pre>

<br>

<ul>
  <li> PrimitiveCommandNode.java
  </li>
</ul>

<pre>// &lt;primitive command&gt; ::= PRINT &lt;string&gt; <br>//                           | SPACE | BREAK | LINEBREAK<br>public class PrimitiveCommandNode implements INode {<br>    private String name;<br>    private String text;<br><br>    public void parse(Context context) {<br>        name = context.currentToken();<br>        context.skipToken(name);<br>        if (!name.equals("PRINT") &amp;&amp; !name.equals("BREAK") <br>                           &amp;&amp; !name.equals("LINEBREAK") <br>                           &amp;&amp; !name.equals("SPACE")) {<br>            System.err.println("Undefined Command");<br>        }<br><br>        if (name.equals("PRINT")) {<br>            text = context.currentToken();<br>            context.nextToken();<br>        }<br>    } <br><br>    public void execute() {<br>        if(name.equals("PRINT"))<br>            System.out.print(text);<br>        else if(name.equals("SPACE"))<br>            System.out.print(" ");<br>        else if(name.equals("BREAK"))<br>            System.out.println();<br>        else if(name.equals("LINEBREAK"))<br>            System.out.println(<br>                  "\n------------------------------");<br>    }<br><br>    public String toString() {<br>        return name;<br>    }<br>} <br></pre>

<br>

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

<pre>public class RepeatCommandNode implements INode {<br>    private int number;<br>    private INode commandListNode;<br><br>    public void parse(Context context) {<br>        context.skipToken("REPEAT");<br>        number = context.currentNumber();<br>        context.nextToken();<br>        commandListNode = new CommandListNode();<br>        commandListNode.parse(context);<br>    }<br><br>    public void execute() {<br>        for(int i = 0; i &lt; number; i++)<br>            commandListNode.execute();<br>    }<br><br>    public String toString() {<br>        return "[REPEAT " + number + " " + <br>                             commandListNode + "]";<br>    }<br>} <br></pre>

<br>

<ul>
  <li> Context.java
  </li>
</ul>

<pre>import java.util.*;<br><br>public class Context {<br>    private StringTokenizer tokenizer;<br>    private String currentToken;<br><br>    public Context(String text) {<br>        tokenizer = new StringTokenizer(text);<br>        nextToken();<br>    }<br><br>    public String nextToken() {<br>        if (tokenizer.hasMoreTokens()) {<br>            currentToken = tokenizer.nextToken();<br>        } else {<br>            currentToken = null;<br>        }<br>        return currentToken;<br>    }<br><br>    public String currentToken() {<br>        return currentToken;<br>    }<br><br>    public void skipToken(String token) {<br>        if (!token.equals(currentToken)) {<br>            System.err.println("Warning: " + token + <br>                           " is expected, but " + <br>                           currentToken + " is found.");<br>        }<br>        nextToken();<br>    }<br><br>    public int currentNumber() {<br>        int number = 0;<br>        try {<br>            number = Integer.parseInt(currentToken);<br>        } catch (NumberFormatException e) {<br>            System.err.println("Warning: " + e);<br>        }<br>        return number;<br>    }<br>} <br></pre>

<br>

<ul>
  <li> Main.java
  </li>
</ul>

<pre>import java.util.*;<br>import java.io.*;<br><br>public class Main {<br>    public static void main(String[] args) {<br>        try {<br>            BufferedReader reader = new BufferedReader(<br>                               new FileReader(args[0]));<br>            String text;<br>            while ((text = reader.readLine()) != null) {<br>                System.out.println("text = \"" + text <br>                                      + "\"");<br>                INode node = new ProgramNode();<br>                node.parse(new Context(text));<br>                node.execute();<br>            }<br>        }<br>        catch (ArrayIndexOutOfBoundsException e) {<br>            System.err.println(<br>                 "Useage: java Main yourprogram.txt");<br>        }<br>        catch (Exception e) {<br>            e.printStackTrace();<br>        }<br>    }<br>}</pre>
<br>

假设您的直译程式稿是这么撰写的: <br>
<ul>
  <li>program.txt</li>
</ul>

<pre>PROGRAM REPEAT 4 LINEBREAK PRINT justin SPACE PRINT momor LINEBREAK END END</pre>
<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>&nbsp; $ java Main program.txt <br>
&nbsp;text = "PROGRAM REPEAT 4 LINEBREAK PRINT justin SPACE <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PRINT momor LINEBREAK END END" <br>
&nbsp;------------------------------ <br>
&nbsp;justin momor <br>
&nbsp;------------------------------ <br>
      <br>
&nbsp;------------------------------ <br>
&nbsp;justin momor <br>
&nbsp;------------------------------ <br>
      <br>
&nbsp;------------------------------ <br>
&nbsp;justin momor <br>
&nbsp;------------------------------ <br>
      <br>
&nbsp;------------------------------ <br>
&nbsp;justin momor <br>
&nbsp;------------------------------&nbsp;</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>
<a href="http://www.drmaster.com.tw/info.asp?NO=PG20214">Design Patterns于Java语言之实习应用</a> 第23章的范例中,可以让您依指令稿直译,画出任何的图案,让范例结合了工厂(Factory)模式、外观(Facade)模式等等,在这边建议您看看那个范例,看看不同的设计模式之间如何组合且相互合作。<br>
<br>





</body>
</html>

⌨️ 快捷键说明

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