[Android&Java]淺談設計模式-代碼篇:觀察者模式Observer

觀察者,就如同一個人,對很多東西都感興趣,就好像音樂、電子產品、Game、股票等,這些東西的變化都能引起愛好者們的注意並時刻關注他們。在代碼中,我們也有這樣的一種方式來設計一些好玩的思想來。今天就寫個Demo來描述一下這種思想,用java內置的Observer來實現這一思想。

好,程序員是不善言語的,看代碼先。

1.demo的結構:

2.先創建我們的主題類Subject,他就是我們本demo的明星類,繼承了Observable,顧名思義,就是被觀察的類 ,其他觀察者對他可是虎視眈眈哦(其實包括你哦)

/**
 * 定義一個主題類
 * @author jan
 */
public class Subject extends Observable implements Parcelable {
	private int id;
	private String name;
	private String message;
	
	public Subject(){}
	
	public Subject(Parcel parcel){
		this.id = parcel.readInt();
		this.name = parcel.readString();
		this.message = parcel.readString();
	}
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
		notifyChanged();
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
		notifyChanged();
	}
	public String getMessage() {
		return message;
	}
	public void setMessage(String message) {
		this.message = message;
		notifyChanged();
	}
	
	/**
	 * 數據改變後,通知我們的訂閱該主題的“觀察者”數據已經更新
	 */
	private void notifyChanged(){
		setChanged();
		notifyObservers();
	}
	
	@Override
	public String toString() {
		return "Subject [id=" + id + ", name=" + name + ", message=" + message
				+ "]";
	}

	@Override
	public int describeContents() {
		return 0;
	}
	
	@Override
	public void writeToParcel(Parcel dest, int flags) {
		dest.writeInt(this.id);
		dest.writeString(name);
		dest.writeString(message);
	}
	
	public static final Parcelable.Creator<Subject> CREATOR = new Creator<Subject>() {
		
		@Override
		public Subject[] newArray(int size) {
			return new Subject[size];
		}
		
		@Override
		public Subject createFromParcel(Parcel source) {
			return new Subject(source);
		}
	};
}
3.嗯,下面就說說我們的觀察者Bean先生吧,首先他必須要有個身份,不然怎麼叫觀察者,他要實現我們的Observer接口,和他的update方法:這是接收最新動態的入口哦!

/**
 * 這是bean先生,一位訂閱者對象 
 */
public class ObserverBean implements Observer {
	
	private Handler hanlder;
	
	private Subject subjcet;
	
	public ObserverBean(Handler handler){
		this.hanlder = handler;
	}
	
	public Subject getSubjcet() {
		return subjcet;
	}

	public void setSubjcet(Subject subjcet) {
		this.subjcet = subjcet;
	}

	@Override
	public void update(Observable observable, Object data) {
		this.subjcet = (Subject) observable;
		Log.i("ObserverBean", "主題已經更新:"+this.subjcet.toString());
		if(hanlder!=null){
			Message msg = hanlder.obtainMessage(2);
			msg.obj = subjcet;
			msg.sendToTarget();
		}
	}
}
4.我們的主界面來了,哈哈這個Activity 也是一名觀察者哦,一名觀察者怎麼夠,至少2個吧,廢話少說,看代碼。

/**
 * 觀察者模式的一種使用方式,在這裏主要的功能是顯示我們感興趣的主題如何改變並通知他們的訂閱者,即觀察者
 * 本例子的效果不是重點,主要是增加對Observer的瞭解。
 * @author jan
 * Date:2015年7月22日 20:27:01
 */
public class ObserverActivity extends Activity implements Observer {
	private static final String TAG = "ObserverActivity";
	// 顯示改變的主題內容
	private TextView mSubText1;
	private TextView mSubText2;
	// 被訂閱的主題
	private Subject mSubject;
	private UpdateRunnable runnable;
	// 觀察者實體類,我們另一個訂閱對象
	private ObserverBean bean;

	private Handler mHandler = new Handler(new Handler.Callback() {
		@Override
		public boolean handleMessage(Message msg) {
			if (msg.what == 1) { // 更新ObserverActivity的收到的主題
				Subject sj1 = (Subject) msg.obj;
				mSubText1.setText(sj1.getId() + "\n" + sj1.getName() + "\n"
						+ sj1.getMessage());
				return true;
			} else if (msg.what == 2) { // 更新bean先生收到的主題內容
				Subject sj2 = (Subject) msg.obj;
				mSubText2.setText(sj2.getId() + "\n" + sj2.getName() + "\n"
						+ sj2.getMessage());
				return true;
			}
			return false;
		}
	});

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		mSubText1 = (TextView) findViewById(R.id.subject_id_1);
		mSubText2 = (TextView) findViewById(R.id.subject_id_2);
		// 創建另一個訂閱者,bean先生
		bean = new ObserverBean(mHandler);
		// 生成主題的實例
		mSubject = new Subject();
		bean.setSubjcet(mSubject);
		// 主題對象 把 觀察者 加入進來,建立關聯,一個主題可能有幾個人感興趣,如下,添加了2個觀衆
		mSubject.addObserver(bean);
		mSubject.addObserver(this);
		runnable = new UpdateRunnable();
		mHandler.postDelayed(runnable, 1000);
	}

	// 如果主題內容變化了,會觸發該方法,我們在這裏更新顯示主題的最新內容
	@Override
	public void update(Observable observable, Object data) {
		Subject sj = null;
		if (observable instanceof Subject) {
			sj = (Subject) observable;
			Log.d(TAG, "Subject-->"+sj.toString());
			Message msg = mHandler.obtainMessage(1);
			msg.obj = sj;
			msg.sendToTarget();
		}
	}

	@Override
	protected void onDestroy() {
		super.onDestroy();
		mHandler.removeCallbacks(runnable);
		mSubject.deleteObserver(this);
		mSubject.deleteObserver(bean);
	}

	/**
	 * 定時每隔一秒改變主題的內容
	 * @author jan
	 */
	class UpdateRunnable implements Runnable {
		int i = 0;

		@Override
		public void run() {
			if (mSubject != null) {
				i++;
				mSubject.setId(i);
				mSubject.setName(i + "活動日誌");
				mSubject.setMessage("今晚打老虎--" + i);
			}
			mHandler.postDelayed(this, 1000);
		}
	}

}

5.最後的效果圖



總結:觀察者模式 就是 定義了 一系列對象之間的一對多關係。當一個對象改變狀態,其他依賴者都會收到通知。


下載demo的鏈接

在推薦相關的博客:1.設計模式之七 --- 觀察者模式(Observer)

     2.Android Observer觀察者模式

-------------------------------------------------------------------------------------更新線-----------------------------------------------------------------------------------------------------

時間:2015年7月24日

關於觀察者模式在我們代碼中,實際情況往往更加複雜,可能會有多重的組合,因爲在java中Observable是一個抽象類,是一個類而不是接口,這使我們想要靈活的使用它比較困難,因爲java類只能繼承一個類,不能像接口一樣,多重繼承,這也就是說我們最好自己能夠實現類似的接口 去替代他。我在推薦的博客中的第一篇就是這麼做的可以學習一下。



發佈了70 篇原創文章 · 獲贊 36 · 訪問量 22萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章