淺識JAVA設計模式——觀察者模式

Codeagles發表於2018-07-10

版權宣告:本文為 Codeagles 原創文章,可以隨意轉載,但必須在明確位置註明出處!!!

###觀察者模式 什麼是觀察者模式?觀察者模式(Observer Pattern)就是一種 “釋出者-訂閱者” 的模式。也被稱為 “模型-檢視”模式、“源-監聽者”模式等。工作原理:由一個目標物件來管理所有依賴與它的觀察者物件,並且當這個目標物件***自身***發生改變時,會***主動***向它的觀察者們發出通知。

關鍵字:被觀察的目標自身、主動發出通知。

想要用觀察者模式,那就要知道這麼幾個問題:

  • 為什麼要用
  • 有什麼優點
  • 有什麼缺點
  • 怎麼用

之所以叫做淺談設計模式,是因為設計模式是一種思想,一種程式碼結構,它出自於眾多人的經驗,相對來說也很靈活,只是中心思想是不變的,筆者只能儘量舉例講的通俗易懂點,當然功力有限,還需看官多理解,放在自己的專案中,或者實際體驗中。

  • 為什麼用?當然是因為一個物件改變了狀態,然後通知其他物件,之後怎麼辦那就是設計者的事情了。 應用案例其實也很多,比如按鍵新增監聽事件(Listener)。當然,對AWT、Swing比較陌生的。

舉個生活中的例子,訂飛機票,飛機什麼時候起飛,所有買票的乘客都在看著,那麼所有的乘客就是觀察者,他們需要觀察飛機的動態,而飛機就是目標物件,當飛機起飛的前一天,航空公司會給乘坐該飛機的所有乘客發一條簡訊:“飛機明天將於幾點幾分起飛,巴拉巴拉。。。”,這個時候所有的觀察者都會接到簡訊(目標物件主動傳送的通知),那麼乘客就知道飛機的動態了。

  • 有什麼優點?可能太好理解,觀察者和被觀察者是抽象耦合的關係,雖然是耦合但是是低耦合,其次它可以監聽觸發事件嘛,觀察不就是為了知道我什麼時候行動嘛。
  • 有什麼缺點?其實也很明顯。
    • 一個物件的所有的觀察者都需要被通知,時間成本很高。
    • 在這個模式中,觀察者只知道目標物件發生了變化,至於怎麼發生的它們是不知道的。
    • 還有別的缺點,理解不到,功力太淺,暫不寫出。
  • 怎麼用? ####Talk is cheap, show me the code. ####Subject類
package ObserverPattern;
 import java.util.ArrayList;
 import java.util.List; 

 public class Subject {
    //觀察者列表
     private List<Observer> observers = new ArrayList<Observer>();
    //設定狀態,就是單純了讓Subject改變一下
    private int state;	
    //setter and getter
    public int getState() {
             return state;
    }
     public void setState(int state) {
        this.state = state;
         //設定狀態,主動通知所有觀察者
         notifyAllObservers();
	}
	
	//向觀察者列表中新增觀察者
	public void addObservers(Observer ob){
            observers.add(ob);
	}

	//通知所有觀察者
	public void notifyAllObservers() {
		for(Observer ob:observers){
		//觀察者作出響應
	      ob.make_response();
	  }
	}		
  }
複製程式碼

####Obeserver抽象類

  package ObserverPattern;
  public abstract class Observer {
  //為觀察者的實體類做鋪墊,為了讓子類可以直接與Subject繫結  
       protected Subject subject;
	   public abstract void make_response();
  }
複製程式碼

####FirstObserver的觀察者實體類

package ObserverPattern;

public class FirstObserver extends Observer{
	//與Subject進行繫結
	public FirstObserver(Subject sub){
		this.subject=sub;
		//開始監聽
		this.subject.addObservers(this);
	}
	
	@Override
	public void make_response() {
		System.out.println("觀察者001,我的作用是輸出物件的改變狀態:"+subject.getState());
	}

}

複製程式碼

####SecondObserver的觀察者實體類

package ObserverPattern;

public class SecondObserver extends Observer {
	// 與Subject進行繫結
	public SecondObserver(Subject sub) {
		this.subject = sub;
		// 開始監聽
		this.subject.addObservers(this);
	}

	@Override
	public void make_response() {
		System.out.println("觀察者002,我的作用是將目標物件的狀態碼轉換成二進位制:"+Integer.toBinaryString(subject.getState()));
	}

}

複製程式碼

####ObserverPattern的Demo

package ObserverPattern;

public class ObserverPattern {
	
	public static void main(String[] args) {
		 Subject subject = new Subject();
		 FirstObserver fo= new FirstObserver(subject);
		 SecondObserver so =new SecondObserver(subject);
		 System.out.println("第一次設定狀態碼:520");
		 subject.setState(520);
		 System.out.println("第二次更改狀態碼:1314");
		 subject.setState(1314);
	}

}

複製程式碼

####輸出結果:

第一次設定狀態碼:520
觀察者001,我的作用是輸出物件的改變狀態:520
觀察者002,我的作用是將目標物件的狀態碼轉換成二進位制:1000001000
第二次更改狀態碼:1314
觀察者001,我的作用是輸出物件的改變狀態:1314
觀察者002,我的作用是將目標物件的狀態碼轉換成二進位制:10100100010

複製程式碼

###總結 到這裡就結束了,本文講的是思路以及簡單原理,如果有問題,請在下面留言。還有就是強調一句,JAVA 中已經有了對觀察者模式的支援類。使用該模式需要注意,如果程式順序執行時,有一個觀察者錯誤,程式就會掛掉了,這個也不難想象。舉得例子,也有可能不太恰當,有好的例子也歡迎在留言區貼出來,一起談論。

相關文章