觀察者模式概念與java實現

現在想想,將以前學的一些設計模式搬運到CSDN上來吧,做個備註,防止遺忘。

(1)觀察者模式的定義:

指多個對象間存在一對多的依賴關係,當一個對象的狀態發生改變時,所有依賴於它的對象都得到通知並被自動更新。

  1. 模式的優缺點:

優點:

1、降低了目標與觀察者之間的耦合關係,兩者之間是抽象耦合關係。

2、目標與觀察者之間建立了一套觸發機制。

缺點:

1、目標與觀察者之間的依賴關係並沒有完全解除,而且有可能出現循環引用。

2、當觀察者對象很多時,通知的發佈會花費很多時間,影響程序的效率。

(3)模式的結構圖如圖1所示。

 

圖1 觀察者模式結構圖

(4)模式結構

1、抽象主題(Subject)角色:也叫抽象目標類,它提供了一個用於保存觀察者對象的聚集類和增加、刪除觀察者對象的方法,以及通知所有觀察者的抽象方法。

2、具體主題(Concrete    Subject)角色:也叫具體目標類,它實現抽象目標中的通知方法,當具體主題的內部狀態發生改變時,通知所有註冊過的觀察者對象。

3、抽象觀察者(Observer)角色:它是一個抽象類或接口,它包含了一個更新自己的抽象方法,當接到具體主題的更改通知時被調用。

4、具體觀察者(Concrete Observer)角色:實現抽象觀察者中定義的抽象方法,以便在得到目標的更改通知時更新自身的狀態。

圖2 數據視圖觀察者模式實例圖

 

1、Table類是抽象主題角色:提供了一個用於保存觀察者對象的聚集類和增加、刪除觀察者對象的方法,以及通知所有觀察者的抽象方法。

2、User類是具體主題角色:實現抽象目標中的通知方法,當具體主題的內部狀態發生改變時,通知所有註冊過的觀察者對象。

3、observer類是抽象觀察者角色:是一個接口,包含了一個更新自己的抽象方法,當接到具體主題的更改通知時被調用。

4、observer1類和observer2類是具體觀察者角色:實現抽象觀察者中定義的抽象方法,以便在得到目標的更改通知時更新自身的狀態。

 

User類中包含姓名,學號,性別,年齡,成績等列。

視圖1是observer1類,包含姓名、學號、成績三列。

視圖2是observer2類,包含姓名、成績兩列。

更新User類中數據時,兩視圖也應該作出相應的更新操作。

更新學號,視圖1變化,視圖2不變化,結果如圖3所示。

 

圖3 觀察者模式結果-1

更新姓名,視圖1變化,視圖2也變化,結果如圖3所示。

 

圖4 觀察者模式結果-2

 

 

1.觀察者模式主要適用於以下情況:

①當一個抽象模型有兩個方面,其中一個方面依賴於另一方面。將這二者封裝在獨立的對象中以使它們可以各自獨立地改變和複用。

②當對一個對象的改變需要同時改變其他對象,而不知道具體有多少對象需要被改變。

③當一個對象必須通知其他對象,而它又不能假定其他對象是誰。換言之,不希望這些對象是緊密耦合的。

 

2. 觀察者模式的優缺點:

觀察者模式的主要的作用就是給對象解耦,將觀察者和被觀察者完全隔離。

①優點

觀察者模式解除了主題和具體觀察者的耦合,讓耦合的雙方都依賴於抽象,而不是依賴具體。

②缺點

在應用觀察者模式時需要考慮一下開發小路問題,程序中包括一個被觀察者和多個被觀察者,開發和調試比較複雜,而且Java中的消息的通知默認是順序執行的,一個觀察者的卡頓會影響整體的執行效率。在這種情況下,一般考慮採用異步的方式。

觀察者:Observer接口
package Observer;

public interface observer {
    void response(String str,int i,String to);
}
觀察者1:
package Observer;

public class observer1 implements observer{
    String[][] users = {
            {"姓名","學號","成績"},
            {"小A","1704010101","80"},
            {"小B","1704010102","100"},
            {"小C","1704010103","90"},
            {"小D","1704010104","99"},
            {"小E","1704010105","70"}
    };

    @Override
    public void response(String str, int i, String to) {
        int flag=0;
        for(int j=0;j<3;j++){
            if(users[0][j].equals(str)==true){
                System.out.println("觀察者1已更新!");
                users[i][j]=to;
                flag=1;
            }
        }
        if(flag==0){
            System.out.println("觀察者1視圖無需更新");
        }
        for(int k=0;k<6;k++){
            for(int j=0;j<3;j++){
                System.out.printf("%8s\t",users[k][j]);
            }
            System.out.println();
        }
    }

}

觀察者2:

package Observer;

public class observer2 implements observer {
    String[][] users = {
            {"姓名","成績"},
            {"小A","80"},
            {"小B","100"},
            {"小C","90"},
            {"小D","99"},
            {"小E","70"}
    };
    @Override
    public void response(String str, int i, String to) {
        int flag=0;
        for(int j=0;j<2;j++){
            if(users[0][j].equals(str)==true){
                System.out.println("觀察者2已更新!");
                users[i][j]=to;
                flag=1;
            }
        }
        if(flag==0){
            System.out.println("觀察者2視圖無需更新");
        }
        for(int k=0;k<6;k++){
            for(int j=0;j<2;j++){
                System.out.printf("%8s\t",users[k][j]);
            }
            System.out.println();
        }
    }
}

抽象被觀察者:

package Observer;

import java.util.ArrayList;

abstract public class table {
    protected ArrayList observers = new ArrayList();

    public void push(observer o){
        observers.add(o);
    }

    public void remove(observer o){
        observers.remove(o);
    }

    public abstract void modify(int i,int j,String to);
}

具體被觀察者:

package Observer;

public class User extends table {
    String[][] users = {
            {"姓名","學號","性別","年齡","成績"},
            {"小A","1704010101","男","22","80"},
            {"小B","1704010102","男","19","100"},
            {"小C","1704010103","男","20","90"},
            {"小D","1704010104","男","20","99"},
            {"小E","1704010105","男","20","70"}
    };
    public User(){
        for (int i=0;i<6;i++){
            for(int j=0;j<5;j++){
                System.out.printf("%8s\t",users[i][j]);
            }
            System.out.println();
        }
    }
    @Override
    public void modify(int i,int j,String to) {
        String str1 = users[0][j];
        for (Object obs:observers){
            ((observer)obs).response(users[0][j],i,to);
        }
    }
}

客戶端(測試):

package Observer;

import java.util.Scanner;

public class client {
    public static void main(String[] args) {
        table A711 = new User();
        observer obs1 = new observer1();
        observer obs2 = new observer2();

        A711.push(obs1);
        A711.push(obs2);
        Scanner cin = new Scanner(System.in);

        System.out.println("請輸入你要更改的座標i:1-5 j:0-4 以及你想修改的值:");
        while(cin.hasNext()){
            int i=cin.nextInt();
            int j=cin.nextInt();
            String str = cin.next();
            A711.modify(i,j,str);
            System.out.println("請輸入你要更改的座標i:0-4 j:1-5 以及你想修改的值:");
        }
    }
}

 

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