前言
在上一篇中我們學習了行為型模式的責任鍊模式(Chain of Responsibility Pattern)和指令模式(Command Pattern)。本篇則來學習下行為型模式的兩個模式, 解釋器模式(Interpreter Pattern)和疊代器模式(Iterator Pattern)。
解釋器模式
簡介
解釋器模式顧名思義,就是對某事物進行解釋。給定一個語言之後,解釋器模式可以定義出其文法的一種表示,并同時提供一個解釋器。用戶端可以使用這個解釋器來解釋這個語言中的句子。
解釋器模式其實就是對某事物進行解釋。比如生活中經常用到的電腦,将我們用的語言轉換成電腦預言,還有我們編寫代碼時用到的正規表達式等等。《大話設計模式》中對這個模式有個比較有意思的講解,其中示例就是把老闆對不同人說相同的話,不同的人會了解不同。這也說明的解釋器模式核心就是進行解釋。
解釋器模式主要由這四個角色組成,抽象表達式(Expression)角色、終結符表達式(Terminal Expression)角色、非終結符表達式(Nonterminal Expression)角色和環境(Context)角色。
- 抽象解釋器:聲明一個所有具體表達式都要實作的抽象接口(或者抽象類),接口中主要是一個interpret()方法,稱為解釋操作。具體解釋任務由它的各個實作類來完成,具體的解釋器分别由終結符解釋器TerminalExpression和非終結符解釋器NonterminalExpression完成。
- 終結符表達式:實作與文法中的元素相關聯的解釋操作,通常一個解釋器模式中隻有一個終結符表達式,但有多個執行個體,對應不同的終結符。終結符一半是文法中的運算單元,比如有一個簡單的公式R=R1+R2,在裡面R1和R2就是終結符,對應的解析R1和R2的解釋器就是終結符表達式。
- 非終結符表達式:文法中的每條規則對應于一個非終結符表達式,非終結符表達式一般是文法中的運算符或者其他關鍵字,比如公式R=R1+R2中,+就是非終結符,解析+的解釋器就是一個非終結符表達式。非終結符表達式根據邏輯的複雜程度而增加,原則上每個文法規則都對應一個非終結符表達式。
- 環境角色:這個角色的任務一般是用來存放文法中各個終結符所對應的具體值,比如R=R1+R2,我們給R1指派100,給R2指派200。這些資訊需要存放到環境角色中,很多情況下我們使用Map來充當環境角色就足夠了。
這裡為了友善了解,我們使用一個簡單的示例來加以說明。
平常我們在進行英語學習的時候,會自行翻譯或者用到翻譯工具。但是不同的翻譯工具翻譯的結果也可能不一樣,這時我們隻需要拿到自己想要的結果就行了。比如,使用百度和有道翻譯“好好學習,天天向上!”,它們翻譯的結果分别為“Study hard and keep up!”和“study hard and make progress every day!”,而xuwujing翻譯的結果是“ Good good study, day day up!”。
那麼我們便可以用解釋器模式來實作這種場景。
首先定義一個抽象的解釋器接口,有解釋的這個方法,然後再定義不同的解釋器實作該接口和方法,最後再來進行測試。那麼代碼如下:
interface Expreeion{
void interpert(String word);
}
class BaiduExpreeion implements Expreeion{
String str ="好好學習,天天向上!";
@Override
public void interpert(String word) {
if(str.equals(word)) {
System.out.println("百度翻譯:"+word+" 的英文是 Study hard and keep up!");
}
}
}
class YouDaoExpreeion implements Expreeion{
String str ="好好學習,天天向上!";
@Override
public void interpert(String word) {
if(str.equals(word)) {
System.out.println("有道翻譯:"+word+" 的英文是 study hard and make progress every day!");
}
}
}
class XuWuJingExpreeion implements Expreeion{
String str ="好好學習,天天向上!";
@Override
public void interpert(String word) {
if(str.equals(word)) {
System.out.println("xuwujing翻譯:"+word+" 的英文是 Good good study, day day up!");
}
}
}
public class InterpreterTest {
public static void main(String[] args) {
String word = "好好學習,天天向上!";
Expreeion expreeion =new BaiduExpreeion();
Expreeion expreeion2 =new YouDaoExpreeion();
Expreeion expreeion3 =new XuWuJingExpreeion();
expreeion.interpert(word);
expreeion2.interpert(word);
expreeion3.interpert(word);
}
}
輸出結果:
百度翻譯:好好學習,天天向上! 的英文是 Study hard and keep up!
有道翻譯:好好學習,天天向上! 的英文是 study hard and make progress every day!
xuwujing翻譯:好好學習,天天向上! 的英文是 Good good study, day day up!
解釋器模式優點:
擴充性好,子類擴充非常友善。
實作簡單。
解釋器模式缺點:
可使用的場景比較少;
類過多的話,會使代碼臃腫,難以維護;
使用場景:
一個簡單的文法規則需要解釋的場景,比如sql。
有重複的問題的時候。
疊代器模式
疊代器模式用于順序通路集合對象的元素,不需要知道集合對象的底層表示,屬于行為型模式。 它提供一種方法順序通路一個聚合對象中各個元素, 而又無須暴露該對象的内部表示。
我們對疊代器(Iterator)肯定不陌生,因為我們在Java開發中會經常用到,比如對List、Set和Map集合進行周遊或對數組進行周遊的時候。但是疊代器模式的話,可能就不太了解了,這裡我們就簡單講講疊代器模式。
疊代器模式主要由這四個角色組成,疊代器角色(Iterator)、具體疊代器角色(Concrete Iterator)、容器角色(Container)和具體容器角色(Concrete Container)。
- 疊代器角色(Iterator):通過接口或抽象類聲明實作的方法。
- 具體疊代器角色(Concrete Iterator):具體疊代器角色要實作疊代器接口,并要記錄周遊中的目前位置。
- 容器角色(Container):容器角色負責提供建立具體疊代器角色的接口。
- 具體容器角色(Concrete Container):具體容器角色實作建立具體疊代器角色的接口——這個具體疊代器角色于該容器的結構相關。
因為疊代器我們平時用的比較多,這裡也不在過多描述了,這裡就簡單的介紹下疊代器模式的運作。
首先,定義一個疊代器角色(MyIterator )和容器角色(MyIterable)的接口。
代碼如下:
interface MyIterator {
boolean hasNext();
String next();
}
interface MyIterable{
MyIterator getIterator();
void add(String str);
String get(int index);
}
然後定義一個 具體容器角色(ListContainer )實作容器角色的接口,這裡的實作方法通過List自帶的進行實作;然後再定義一個具體疊代器角色(ListIterator )實作疊代器角色的接口,這裡的實作的方法由自己實作。
那麼代碼如下:
class ListContainer implements MyIterable {
private List<String> list =new ArrayList<>();
@Override
public MyIterator getIterator() {
return new ListIterator();
}
@Override
public void add(String str) {
list.add(str);
}
@Override
public String get(int index) {
return list.get(index);
}
class ListIterator implements MyIterator{
int index;
@Override
public boolean hasNext() {
return index < list.size();
}
@Override
public String next() {
if (this.hasNext()) {
return list.get(index++);
}
return null;
}
}
}
最後再來進行代碼的測試。
測試代碼如下:
public static void main(String[] args) {
MyIterable myIterable = new ListContainer();
myIterable.add("1");
myIterable.add("zhangsan");
myIterable.add("2");
myIterable.add("lisi");
myIterable.add("3");
myIterable.add("xuwujing");
MyIterator myIterator = myIterable.getIterator();
while (myIterator.hasNext()){
String str = myIterator.next();
System.out.println(str);
}
}
1
zhangsan
2
lisi
3
xuwujing
疊代器模式優點:
靈活度高,可以通過不同的方式周遊對象;
擴充性好,可以很友善的增加新的聚合類和疊代器類而不用修改之前的代碼。
疊代器模式缺點:
由于疊代器模式将存儲資料和周遊資料的職責分離,增加新的聚合類需要對應增加新的疊代器類,類的個數成對增加,這在一定程度上增加了系統的複雜性。
需要為聚合對象提供周遊的功能的時候。
其它
音樂推薦
分享一首很好聽的日語歌曲!
項目的代碼
java-study 是本人在學習Java過程中記錄的一些代碼,也包括之前博文中使用的代碼。如果感覺不錯,希望順手給個start,當然如果有不足,也希望提出。
github位址: https://github.com/xuwujing/java-study
原創不易,如果感覺不錯,希望給個推薦!您的支援是我寫作的最大動力!
版權聲明:
作者:虛無境
部落格園出處:http://www.cnblogs.com/xuwujing
CSDN出處:http://blog.csdn.net/qazwsxpcm
個人部落格出處:http://www.panchengming.com
如果你對生活感覺到了絕望,請不要氣餒。因為這樣隻會讓你更加絕望!
所謂的希望往往都是在絕望中萌發的,是以,請不要放棄希望!