java 23種設計模式(三)

本章是關於設計模式的最後一講,會講到第三種設計模式——行爲型模式,共11種:策略模式、模板方法模式、觀察者模式、迭代子模式、責任鏈模式、命令模式、備忘錄模式、狀態模式、訪問者模式、中介者模式、解釋器模式。這段時間一直在寫關於設計模式的東西,終於寫到一半了,寫博文是個很費時間的東西,因爲我得爲讀者負責,不論是圖還是代碼還是表述,都希望能儘量寫清楚,以便讀者理解,我想不論是我還是讀者,都希望看到高質量的博文出來,從我本人出發,我會一直堅持下去,不斷更新,源源動力來自於讀者朋友們的不斷支持,我會盡自己的努力,寫好每一篇文章!希望大家能不斷給出意見和建議,共同打造完美的博文!
學會技術,懂得分享!
有任何想法,請聯繫:egg
email:[email protected] 微博:http://weibo.com/xtfggef
如有轉載,請說明出處:http://blog.csdn.net/zhangerqing

先來張圖,看看這11中模式的關係:
第一類:通過父類與子類的關係進行實現。第二類:兩個類之間。第三類:類的狀態。第四類:通過中間類

13、策略模式(strategy)
策略模式定義了一系列算法,並將每個算法封裝起來,使他們可以相互替換,且算法的變化不會影響到使用算法的客戶。需要設計一個接口,爲一系列實現類提供統一的方法,多個實現類實現該接口,設計一個抽象類(可有可無,屬於輔助類),提供輔助函數,關係圖如下:

圖中ICalculator提供同意的方法,
AbstractCalculator是輔助類,提供輔助方法,接下來,依次實現下每個類:
首先統一接口:
public interface ICalculator {
public int calculate(String exp);
}
輔助類:
public abstract class AbstractCalculator {

public int[] split(String exp,String opt){
    String array[] = exp.split(opt);
    int arrayInt[] = new int[2];
    arrayInt[0] = Integer.parseInt(array[0]);
    arrayInt[1] = Integer.parseInt(array[1]);
    return arrayInt;
}

}
三個實現類:
public class Plus extends AbstractCalculator implements ICalculator {

@Override
public int calculate(String exp) {
    int arrayInt[] = split(exp,"\\+");
    return arrayInt[0]+arrayInt[1];
}

}
public class Minus extends AbstractCalculator implements ICalculator {

@Override
public int calculate(String exp) {
    int arrayInt[] = split(exp,"-");
    return arrayInt[0]-arrayInt[1];
}

}
public class Multiply extends AbstractCalculator implements ICalculator {

@Override
public int calculate(String exp) {
    int arrayInt[] = split(exp,"\\*");
    return arrayInt[0]*arrayInt[1];
}

}
簡單的測試類:
public class StrategyTest {

public static void main(String[] args) {
    String exp = "2+8";
    ICalculator cal = new Plus();
    int result = cal.calculate(exp);
    System.out.println(result);
}

}
輸出:10
策略模式的決定權在用戶,系統本身提供不同算法的實現,新增或者刪除算法,對各種算法做封裝。因此,策略模式多用在算法決策系統中,外部用戶只需要決定用哪個算法即可。
14、模板方法模式(Template Method)
解釋一下模板方法模式,就是指:一個抽象類中,有一個主方法,再定義1…n個方法,可以是抽象的,也可以是實際的方法,定義一個類,繼承該抽象類,重寫抽象方法,通過調用抽象類,實現對子類的調用,先看個關係圖:

就是在AbstractCalculator類中定義一個主方法calculate,calculate()調用spilt()等,Plus和Minus分別繼承AbstractCalculator類,通過對AbstractCalculator的調用實現對子類的調用,看下面的例子:
public abstract class AbstractCalculator {

/*主方法,實現對本類其它方法的調用*/
public final int calculate(String exp,String opt){
    int array[] = split(exp,opt);
    return calculate(array[0],array[1]);
}

/*被子類重寫的方法*/
abstract public int calculate(int num1,int num2);

public int[] split(String exp,String opt){
    String array[] = exp.split(opt);
    int arrayInt[] = new int[2];
    arrayInt[0] = Integer.parseInt(array[0]);
    arrayInt[1] = Integer.parseInt(array[1]);
    return arrayInt;
}

}
public class Plus extends AbstractCalculator {

@Override
public int calculate(int num1,int num2) {
    return num1 + num2;
}

}
測試類:
public class StrategyTest {

public static void main(String[] args) {
    String exp = "8+8";
    AbstractCalculator cal = new Plus();
    int result = cal.calculate(exp, "\\+");
    System.out.println(result);
}

}
我跟蹤下這個小程序的執行過程:首先將exp和”\+”做參數,調用AbstractCalculator類裏的calculate(String,String)方法,在calculate(String,String)裏調用同類的split(),之後再調用calculate(int ,int)方法,從這個方法進入到子類中,執行完return num1 + num2後,將值返回到AbstractCalculator類,賦給result,打印出來。正好驗證了我們開頭的思路。
15、觀察者模式(Observer)
包括這個模式在內的接下來的四個模式,都是類和類之間的關係,不涉及到繼承,學的時候應該 記得歸納,記得本文最開始的那個圖。觀察者模式很好理解,類似於郵件訂閱和RSS訂閱,當我們瀏覽一些博客或wiki時,經常會看到RSS圖標,就這的意思是,當你訂閱了該文章,如果後續有更新,會及時通知你。其實,簡單來講就一句話:當一個對象變化時,其它依賴該對象的對象都會收到通知,並且隨着變化!對象之間是一種一對多的關係。先來看看關係圖:

我解釋下這些類的作用:MySubject類就是我們的主對象,Observer1和Observer2是依賴於MySubject的對象,當MySubject變化時,Observer1和Observer2必然變化。AbstractSubject類中定義着需要監控的對象列表,可以對其進行修改:增加或刪除被監控對象,且當MySubject變化時,負責通知在列表內存在的對象。我們看實現代碼:
一個Observer接口:
public interface Observer {
public void update();
}
兩個實現類:
public class Observer1 implements Observer {

@Override
public void update() {
    System.out.println("observer1 has received!");
}

}
public class Observer2 implements Observer {

@Override
public void update() {
    System.out.println("observer2 has received!");
}

}
Subject接口及實現類:
public interface Subject {

/*增加觀察者*/
public void add(Observer observer);

/*刪除觀察者*/
public void del(Observer observer);

/*通知所有的觀察者*/
public void notifyObservers();

/*自身的操作*/
public void operation();

}
public abstract class AbstractSubject implements Subject {

private Vector<Observer> vector = new Vector<Observer>();
@Override
public void add(Observer observer) {
    vector.add(observer);
}

@Override
public void del(Observer observer) {
    vector.remove(observer);
}

@Override
public void notifyObservers() {
    Enumeration<Observer> enumo = vector.elements();
    while(enumo.hasMoreElements()){
        enumo.nextElement().update();
    }
}

}
public class MySubject extends AbstractSubject {

@Override
public void operation() {
    System.out.println("update self!");
    notifyObservers();
}

}

測試類:
public class ObserverTest {

public static void main(String[] args) {
    Subject sub = new MySubject();
    sub.add(new Observer1());
    sub.add(new Observer2());

    sub.operation();
}

}
輸出:
update self!
observer1 has received!
observer2 has received!
這些東西,其實不難,只是有些抽象,不太容易整體理解,建議讀者:根據關係圖,新建項目,自己寫代碼(或者參考我的代碼),按照總體思路走一遍,這樣才能體會它的思想,理解起來容易!
歡迎廣大讀者隨時指正,一起討論,一起進步!
有問題,聯繫:egg
email:[email protected] 微博:http://weibo.com/xtfggef
16、迭代子模式(Iterator)
顧名思義,迭代器模式就是順序訪問聚集中的對象,一般來說,集合中非常常見,如果對集合類比較熟悉的話,理解本模式會十分輕鬆。這句話包含兩層意思:一是需要遍歷的對象,即聚集對象,二是迭代器對象,用於對聚集對象進行遍歷訪問。我們看下關係圖:

這個思路和我們常用的一模一樣,MyCollection中定義了集合的一些操作,MyIterator中定義了一系列迭代操作,且持有Collection實例,我們來看看實現代碼:
兩個接口:
public interface Collection {

public Iterator iterator();

/*取得集合元素*/
public Object get(int i);

/*取得集合大小*/
public int size();

}
public interface Iterator {
//前移
public Object previous();

//後移
public Object next();
public boolean hasNext();

//取得第一個元素
public Object first();

}
兩個實現:
public class MyCollection implements Collection {

public String string[] = {"A","B","C","D","E"};
@Override
public Iterator iterator() {
    return new MyIterator(this);
}

@Override
public Object get(int i) {
    return string[i];
}

@Override
public int size() {
    return string.length;
}

}
public class MyIterator implements Iterator {

private Collection collection;
private int pos = -1;

public MyIterator(Collection collection){
    this.collection = collection;
}

@Override
public Object previous() {
    if(pos > 0){
        pos--;
    }
    return collection.get(pos);
}

@Override
public Object next() {
    if(pos<collection.size()-1){
        pos++;
    }
    return collection.get(pos);
}

@Override
public boolean hasNext() {
    if(pos<collection.size()-1){
        return true;
    }else{
        return false;
    }
}

@Override
public Object first() {
    pos = 0;
    return collection.get(pos);
}

}
測試類:
public class Test {

public static void main(String[] args) {
    Collection collection = new MyCollection();
    Iterator it = collection.iterator();

    while(it.hasNext()){
        System.out.println(it.next());
    }
}

}
輸出:A B C D E
此處我們貌似模擬了一個集合類的過程,感覺是不是很爽?其實JDK中各個類也都是這些基本的東西,加一些設計模式,再加一些優化放到一起的,只要我們把這些東西學會了,掌握好了,我們也可以寫出自己的集合類,甚至框架!
17、責任鏈模式(Chain of Responsibility)
接下來我們將要談談責任鏈模式,有多個對象,每個對象持有對下一個對象的引用,這樣就會形成一條鏈,請求在這條鏈上傳遞,直到某一對象決定處理該請求。但是發出者並不清楚到底最終那個對象會處理該請求,所以,責任鏈模式可以實現,在隱瞞客戶端的情況下,對系統進行動態的調整。先看看關係圖:

Abstracthandler類提供了get和set方法,方便MyHandle類設置和修改引用對象,MyHandle類是核心,實例化後生成一系列相互持有的對象,構成一條鏈。
public interface Handler {
public void operator();
}
public abstract class AbstractHandler {

private Handler handler;

public Handler getHandler() {
    return handler;
}

public void setHandler(Handler handler) {
    this.handler = handler;
}

}
public class MyHandler extends AbstractHandler implements Handler {

private String name;

public MyHandler(String name) {
    this.name = name;
}

@Override
public void operator() {
    System.out.println(name+"deal!");
    if(getHandler()!=null){
        getHandler().operator();
    }
}

}
public class Test {

public static void main(String[] args) {
    MyHandler h1 = new MyHandler("h1");
    MyHandler h2 = new MyHandler("h2");
    MyHandler h3 = new MyHandler("h3");

    h1.setHandler(h2);
    h2.setHandler(h3);

    h1.operator();
}

}
輸出:
h1deal!
h2deal!
h3deal!
此處強調一點就是,鏈接上的請求可以是一條鏈,可以是一個樹,還可以是一個環,模式本身不約束這個,需要我們自己去實現,同時,在一個時刻,命令只允許由一個對象傳給另一個對象,而不允許傳給多個對象。
18、命令模式(Command)
命令模式很好理解,舉個例子,司令員下令讓士兵去幹件事情,從整個事情的角度來考慮,司令員的作用是,發出口令,口令經過傳遞,傳到了士兵耳朵裏,士兵去執行。這個過程好在,三者相互解耦,任何一方都不用去依賴其他人,只需要做好自己的事兒就行,司令員要的是結果,不會去關注到底士兵是怎麼實現的。我們看看關係圖:

Invoker是調用者(司令員),Receiver是被調用者(士兵),MyCommand是命令,實現了Command接口,持有接收對象,看實現代碼:
public interface Command {
public void exe();
}
public class MyCommand implements Command {

private Receiver receiver;

public MyCommand(Receiver receiver) {
    this.receiver = receiver;
}

@Override
public void exe() {
    receiver.action();
}

}
public class Receiver {
public void action(){
System.out.println(“command received!”);
}
}
public class Invoker {

private Command command;

public Invoker(Command command) {
    this.command = command;
}

public void action(){
    command.exe();
}

}
public class Test {

public static void main(String[] args) {
    Receiver receiver = new Receiver();
    Command cmd = new MyCommand(receiver);
    Invoker invoker = new Invoker(cmd);
    invoker.action();
}

}
輸出:command received!
這個很哈理解,命令模式的目的就是達到命令的發出者和執行者之間解耦,實現請求和執行分開,熟悉Struts的同學應該知道,Struts其實就是一種將請求和呈現分離的技術,其中必然涉及命令模式的思想!
本篇暫時就到這裏,因爲考慮到將來博文會不斷的更新,不斷的增加新內容,所以當前篇幅不易過長,以便大家閱讀,所以接下來的放到另一篇裏。敬請關注!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章