其實每一個設計模式都是很重要的一種思想,看上去很熟,實際上是由於咱們在學到的東西中都有涉及,儘管有時咱們並不知道,其實在Java自己的設計之中到處都有體現,像AWT、JDBC、集合類、IO管道或者是Web框架,裏面設計模式無處不在。由於咱們篇幅有限,很難講每個設計模式都講的很詳細,不過我會盡我所能,儘可能在有限的空間和篇幅內,把意思寫清楚了,更好讓你們明白。本章不出意外的話,應該是設計模式最後一講了,首先仍是上一下上篇開頭的那個圖:java
本章講講第三類和第四類。程序員
1九、備忘錄模式(Memento)web
主要目的是保存一個對象的某個狀態,以便在適當的時候恢復對象,我的以爲叫備份模式更形象些,通俗的講下:假設有原始類A,A中有各類屬性,A能夠決定須要備份的屬性,備忘錄類B是用來存儲A的一些內部狀態,類C呢,就是一個用來存儲備忘錄的,且只能存儲,不能修改等操做。作個圖來分析一下:正則表達式
Original類是原始類,裏面有須要保存的屬性value及建立一個備忘錄類,用來保存value值。Memento類是備忘錄類,Storage類是存儲備忘錄的類,持有Memento類的實例,該模式很好理解。直接看源碼:算法
public class Original { private String value; public String getValue() { return value; } public void setValue(String value) { this.value = value; } public Original(String value) { this.value = value; } public Memento createMemento(){ return new Memento(value); } public void restoreMemento(Memento memento){ this.value = memento.getValue(); } }
public class Memento { private String value; public Memento(String value) { this.value = value; } public String getValue() { return value; } public void setValue(String value) { this.value = value; } }
public class Storage { private Memento memento; public Storage(Memento memento) { this.memento = memento; } public Memento getMemento() { return memento; } public void setMemento(Memento memento) { this.memento = memento; } }
測試類:spring
public class Test { public static void main(String[] args) { // 建立原始類 Original origi = new Original("egg"); // 建立備忘錄 Storage storage = new Storage(origi.createMemento()); // 修改原始類的狀態 System.out.println("初始化狀態爲:" + origi.getValue()); origi.setValue("niu"); System.out.println("修改後的狀態爲:" + origi.getValue()); // 回覆原始類的狀態 origi.restoreMemento(storage.getMemento()); System.out.println("恢復後的狀態爲:" + origi.getValue()); } }
輸出:設計模式
初始化狀態爲:egg
修改後的狀態爲:niu
恢復後的狀態爲:egg數據結構
簡單描述下:新建原始類時,value被初始化爲egg,後通過修改,將value的值置爲niu,最後倒數第二行進行恢復狀態,結果成功恢復了。其實我以爲這個模式叫「備份-恢復」模式最形象。框架
20、狀態模式(State)數據結構和算法
核心思想就是:當對象的狀態改變時,同時改變其行爲,很好理解!就拿QQ來講,有幾種狀態,在線、隱身、忙碌等,每一個狀態對應不一樣的操做,並且你的好友也能看到你的狀態,因此,狀態模式就兩點:一、能夠經過改變狀態來得到不一樣的行爲。二、你的好友能同時看到你的變化。看圖:
State類是個狀態類,Context類能夠實現切換,咱們來看看代碼:
package com.xtfggef.dp.state; /** * 狀態類的核心類 * 2012-12-1 * @author erqing * */ public class State { private String value; public String getValue() { return value; } public void setValue(String value) { this.value = value; } public void method1(){ System.out.println("execute the first opt!"); } public void method2(){ System.out.println("execute the second opt!"); } }
package com.xtfggef.dp.state; /** * 狀態模式的切換類 2012-12-1 * @author erqing * */ public class Context { private State state; public Context(State state) { this.state = state; } public State getState() { return state; } public void setState(State state) { this.state = state; } public void method() { if (state.getValue().equals("state1")) { state.method1(); } else if (state.getValue().equals("state2")) { state.method2(); } } }
測試類:
public class Test { public static void main(String[] args) { State state = new State(); Context context = new Context(state); //設置第一種狀態 state.setValue("state1"); context.method(); //設置第二種狀態 state.setValue("state2"); context.method(); } }
輸出:
execute the first opt!
execute the second opt!
根據這個特性,狀態模式在平常開發中用的挺多的,尤爲是作網站的時候,咱們有時但願根據對象的某一屬性,區別開他們的一些功能,好比說簡單的權限控制等。
2一、訪問者模式(Visitor)
訪問者模式把數據結構和做用於結構上的操做解耦合,使得操做集合可相對自由地演化。訪問者模式適用於數據結構相對穩定算法又易變化的系統。由於訪問者模式使得算法操做增長變得容易。若系統數據結構對象易於變化,常常有新的數據對象增長進來,則不適合使用訪問者模式。訪問者模式的優勢是增長操做很容易,由於增長操做意味着增長新的訪問者。訪問者模式將有關行爲集中到一個訪問者對象中,其改變不影響系統數據結構。其缺點就是增長新的數據結構很困難。—— From 百科
簡單來講,訪問者模式就是一種分離對象數據結構與行爲的方法,經過這種分離,可達到爲一個被訪問者動態添加新的操做而無需作其它的修改的效果。簡單關係圖:
來看看原碼:一個Visitor類,存放要訪問的對象,
public interface Visitor { public void visit(Subject sub); }
public class MyVisitor implements Visitor { @Override public void visit(Subject sub) { System.out.println("visit the subject:"+sub.getSubject()); } }
Subject類,accept方法,接受將要訪問它的對象,getSubject()獲取將要被訪問的屬性,
public interface Subject { public void accept(Visitor visitor); public String getSubject(); }
public class MySubject implements Subject { @Override public void accept(Visitor visitor) { visitor.visit(this); } @Override public String getSubject() { return "love"; } }
測試:
public class Test { public static void main(String[] args) { Visitor visitor = new MyVisitor(); Subject sub = new MySubject(); sub.accept(visitor); } }
輸出:visit the subject:love
該模式適用場景:若是咱們想爲一個現有的類增長新功能,不得不考慮幾個事情:一、新功能會不會與現有功能出現兼容性問題?二、之後會不會再須要添加?三、若是類不容許修改代碼怎麼辦?面對這些問題,最好的解決方法就是使用訪問者模式,訪問者模式適用於數據結構相對穩定的系統,把數據結構和算法解耦,
2二、中介者模式(Mediator)
中介者模式也是用來下降類類之間的耦合的,由於若是類類之間有依賴關係的話,不利於功能的拓展和維護,由於只要修改一個對象,其它關聯的對象都得進行修改。若是使用中介者模式,只需關心和Mediator類的關係,具體類類之間的關係及調度交給Mediator就行,這有點像spring容器的做用。先看看圖:
User類統一接口,User1和User2分別是不一樣的對象,兩者之間有關聯,若是不採用中介者模式,則須要兩者相互持有引用,這樣兩者的耦合度很高,爲了解耦,引入了Mediator類,提供統一接口,MyMediator爲其實現類,裏面持有User1和User2的實例,用來實現對User1和User2的控制。這樣User1和User2兩個對象相互獨立,他們只須要保持好和Mediator之間的關係就行,剩下的全由MyMediator類來維護!基本實現:
public interface Mediator { public void createMediator(); public void workAll(); }
public class MyMediator implements Mediator { private User user1; private User user2; public User getUser1() { return user1; } public User getUser2() { return user2; } @Override public void createMediator() { user1 = new User1(this); user2 = new User2(this); } @Override public void workAll() { user1.work(); user2.work(); } }
public abstract class User { private Mediator mediator; public Mediator getMediator(){ return mediator; } public User(Mediator mediator) { this.mediator = mediator; } public abstract void work(); }
public class User1 extends User { public User1(Mediator mediator){ super(mediator); } @Override public void work() { System.out.println("user1 exe!"); } }
public class User2 extends User { public User2(Mediator mediator){ super(mediator); } @Override public void work() { System.out.println("user2 exe!"); } }
測試類:
public class Test { public static void main(String[] args) { Mediator mediator = new MyMediator(); mediator.createMediator(); mediator.workAll(); } }
輸出:
user1 exe!
user2 exe!
2三、解釋器模式(Interpreter)
解釋器模式是咱們暫時的最後一講,通常主要應用在OOP開發中的編譯器的開發中,因此適用面比較窄。
Context類是一個上下文環境類,Plus和Minus分別是用來計算的實現,代碼以下:
public interface Expression { public int interpret(Context context); }
public class Plus implements Expression { @Override public int interpret(Context context) { return context.getNum1()+context.getNum2(); } }
public class Minus implements Expression { @Override public int interpret(Context context) { return context.getNum1()-context.getNum2(); } }
public class Context { private int num1; private int num2; public Context(int num1, int num2) { this.num1 = num1; this.num2 = num2; } public int getNum1() { return num1; } public void setNum1(int num1) { this.num1 = num1; } public int getNum2() { return num2; } public void setNum2(int num2) { this.num2 = num2; } }
public class Test { public static void main(String[] args) { // 計算9+2-8的值 int result = new Minus().interpret((new Context(new Plus() .interpret(new Context(9, 2)), 8))); System.out.println(result); } }
最後輸出正確的結果:3。
基本就這樣,解釋器模式用來作各類各樣的解釋器,如正則表達式等的解釋器等等!
設計模式基本就這麼大概講完了,整體感受有點簡略,的確,這麼點兒篇幅,不足以對整個23種設計模式作全面的闡述,此處讀者可將它做爲一個理論基礎去學習,經過這四篇博文,先基本有個概念,雖然我講的有些簡單,但基本都能說明問題及他們的特色,若是對哪個感興趣,能夠繼續深刻研究!同時我也會不斷更新,儘可能補全遺漏、修正不足,歡迎廣大讀者及時提出好的建議,咱們一塊兒學習!項目中涉及到的代碼,已經放到了個人資源裏:http://download.csdn.net/detail/zhangerqing/4835830(由於我不喜歡坐享其成,因此沒有免積分,只設置了5個,若是有人實在沒積分又急要,那麼聯繫我吧,我給你發過去)。
在閱讀的過程當中,有任何問題,請聯繫:egg。
郵箱:xtfggef@gmail.com 微博:http://weibo.com/xtfggef