?? interpreterpattern.htm
字號:
<!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: Interpreter 模式</a></h1>
對于一個具有層次節(jié)點關(guān)系的問題來說,如果您要剖析每一個節(jié)點,您可以使用Interpreter模式,直譯器模式有些類似演算法中的個別擊破方式,對每一個父節(jié)點我們剖析出其子節(jié)點組合,然而交給子節(jié)點剖析物件繼續(xù)剖析,直到剖析至終端節(jié)點為止。<br>
<br>
舉個例子來說明好了,先說明的是,這個例子是改寫自 <a href="http://www.drmaster.com.tw/info.asp?NO=PG20214">Design Patterns于Java語言之實習(xí)應(yīng)用</a> 第23章的范例,我將之更簡化了,以讓大家將焦點能集中在如何使用Interpreter模式,以及如何實用。<br>
<br>
假設(shè)您要實作一個Interpreter,這個Interpreter可以直譯您文字檔中的程式,并依您自訂的程式文法來執(zhí)行程式,幾個簡單的程式如下:<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;"> 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;"> 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;"> 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;"> 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>
<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;"> 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;"> LINEBREAK </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;"> 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;"> BREAK </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 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>
<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;">
dog <br style="font-weight: bold;">
------------------------------ <br style="font-weight: bold;">
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;"> 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;"> BREAK </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;"> 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;"> 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;"> 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;"> 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;"> 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;"> 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;"> BREAK </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 style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;"> 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>
<br>
<br>
這個程式中的幾個關(guān)鍵字是PROGRAM、PRINT、SPACE、BREAK、LINEBREAK、REPEAT、END,
PROGRAM是表示程式開始,以END作結(jié),PRINT可以印出一個無空白的字串,SPACE印出一個空白,BREAK是換行,而LINEBREAK是
畫一個直線并換行,REPEAT是回圈指令,可以指定回圈次數(shù),以END作結(jié)。<br>
<br>
觀察程式,可以制定出以下的文法,如下:<br>
<div style="margin-left: 40px;"><span style="font-weight: bold; font-family: Courier New,Courier,monospace;"><program> ::= PROGRAM <command list> </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;"><command list> ::= <command>* END </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;"><command> ::= <repeat command> | <primitive command> </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;"><repeat command> ::= REPEAT <number> <command list> </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;"><primitive command> ::= PRINT <string> </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;">
| BREAK | SPACE | LINEBREAK</span><br>
</div>
<br>
<br>
程式文法制定需要對程式進行語句分析與定義,在這邊并不討論這個課題,在程式中,command節(jié)點由primitive或repeat兩個節(jié)點任意組
合,一個command list節(jié)點則是零個以上的command節(jié)點組合而成,其中repeat還可以組合command
list節(jié)點,這是組合模式的應(yīng)用,可以在程式中組合巢狀回圈。<br>
<br>
在直譯程式時,以讀到PROGRAM作為開始節(jié)點,接下來我們剖析程式為command list 節(jié)點,并將它們丟給專門剖析command
list的物件繼續(xù)剖析,這個物件將之分析,看是不是有repeat command或primitive
command節(jié)點,如果有就再往下交由專屬物件進行剖析,如此層層剝開,并由專屬物件負責(zé)剖析工作。<br>
<br>
Interpreter模式的基本觀念就如上所示,先來看看如何以程式實現(xiàn)剖析的過程,下面這個程式會剖析您的程式,并將程式加上對應(yīng)的括號來將同一個區(qū)塊組合起來,以表示它完成剖析之后的結(jié)果:<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>// <program> ::= PROGRAM <command list> <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>// <command list> ::= <command>* 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>// <command> ::= <repeat command> | <primitive command> <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>
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -