現在想想,將以前學的一些設計模式搬運到CSDN上來吧,做個備註,防止遺忘。
(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 以及你想修改的值:");
}
}
}