觀察者模式:顧名思義,就是衆多觀察者(observers)對被觀察者(observable)的狀態、行爲等進行監聽,
當被觀察者(observable)的狀態、行爲等發生改變後,向觀察者(observers)發出通知,告知觀察者(observers),
觀察者可以對這些通知進行處理或者不處理。
舉個例子:
比如在上課的時候,老師可以看成一個被觀察者(observable),所有學生可以看成觀察者(observers)。
老師(observable)喊上課之後,所有同學(observers)的注意力都集中在老師身上,這時候相當於給被觀察者(observable)添加了許多觀察者(observers);
被觀察者(老師)(observable)的一言一行都會通過光或者聲音反饋給到同學們(observers),當然同學們(observers)對
老師(observable)的言行可能有所反應或者不做任何響應。比如在看到老師(observable)走過來的時候,沒認真聽講的同學(observers)趕緊坐好,集中注意(響應),認真聽講的同學(observers)則可以不做反應。
當然在收到老師(observable)【放學】的通知後,同學們都背起書包回家,即都響應了。
從上面例子可以看出,觀察者(observers)一定要有接收被觀察者(observable)通知的能力;
被觀察者(observable)一定要有增加觀察者(observers)的和通知觀察者(observers)的能力;
那麼我們可以將這些能力抽象出來,讓具體的實現必須實現這些能力,然後添加觀察者(observers)的時候
只關心他有沒有接收通知的能力(即是否是抽象觀察者類observers的實現類)。至此,以及結合高內聚低耦合的思想,我們可以看到,
觀察者模式有4個必要元素:
1.觀察者抽象類
2.觀察者具體實現類
3.被觀察者抽象類
4.被觀察者具體實現類
下面來具體實現以下:
觀察者抽象類:
public abstract class Observerabstract {
/**
* 必須有接收通知的能力
* @param msg
*/
abstract void update(String msg);
}
觀察者具體實現類:
public class MyObserver extends Observerabstract {
//傳入名稱,區分不同的觀察者
private String name;
public MyObserver(String name) {
this.name = name;
}
@Override
public void update(String msg) {
System.out.print(String.format("%s 收到了新消息: %s \n",name,msg));
// System.out.print(name+ "收到特急書信: "+msg);
// Log.i("魔教求助信",name+ "收到特急書信: "+msg);
}
}
被觀察者抽象類:
public abstract class Observableabstract {
/**
* 增加觀察者
* @param observer 觀察者實例對象
*/
abstract void add(Observerabstract observer);
/**
* 移除觀察者
* @param observer 需要移除的觀察者對象
*/
abstract void move(Observerabstract observer);
/**
* 數據變更是通知觀察者
*/
abstract void notifyObserver();
}
被觀察者具體實現類:
public class MyObservable extends Observableabstract {
//保存有多少個觀察者要對此被觀察者進行觀察
private List<Observerabstract> observerList;
private String message;
public MyObservable() {
observerList = new ArrayList<>();
}
@Override
public void add(Observerabstract observer) {
observerList.add(observer);
}
@Override
public void move(Observerabstract observer) {
observerList.remove(observer);
}
@Override
public void notifyObserver() {
for (Observerabstract observer:observerList){
observer.update(message);
}
}
public void setMessage(String message) {
this.message = message;
notifyObserver();
}
}
再來看看咱們recycleview的adapter中的源碼
觀察者抽象類:
/**
* Observer base class for watching changes to an {@link Adapter}.
* See {@link Adapter#registerAdapterDataObserver(AdapterDataObserver)}.
*/
public abstract static class AdapterDataObserver {
public void onChanged() {
// Do nothing
}
public void onItemRangeChanged(int positionStart, int itemCount) {
// do nothing
}
public void onItemRangeChanged(int positionStart, int itemCount, @Nullable Object payload) {
// fallback to onItemRangeChanged(positionStart, itemCount) if app
// does not override this method.
onItemRangeChanged(positionStart, itemCount);
}
public void onItemRangeInserted(int positionStart, int itemCount) {
// do nothing
}
public void onItemRangeRemoved(int positionStart, int itemCount) {
// do nothing
}
public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) {
// do nothing
}
}
觀察者具體實現類:
private class RecyclerViewDataObserver extends AdapterDataObserver {
RecyclerViewDataObserver() {
}
@Override
public void onChanged() {
assertNotInLayoutOrScroll(null);
mState.mStructureChanged = true;
processDataSetCompletelyChanged(true);
if (!mAdapterHelper.hasPendingUpdates()) {
requestLayout();
}
}
@Override
public void onItemRangeChanged(int positionStart, int itemCount, Object payload) {
assertNotInLayoutOrScroll(null);
if (mAdapterHelper.onItemRangeChanged(positionStart, itemCount, payload)) {
triggerUpdateProcessor();
}
}
@Override
public void onItemRangeInserted(int positionStart, int itemCount) {
assertNotInLayoutOrScroll(null);
if (mAdapterHelper.onItemRangeInserted(positionStart, itemCount)) {
triggerUpdateProcessor();
}
}
@Override
public void onItemRangeRemoved(int positionStart, int itemCount) {
assertNotInLayoutOrScroll(null);
if (mAdapterHelper.onItemRangeRemoved(positionStart, itemCount)) {
triggerUpdateProcessor();
}
}
@Override
public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) {
assertNotInLayoutOrScroll(null);
if (mAdapterHelper.onItemRangeMoved(fromPosition, toPosition, itemCount)) {
triggerUpdateProcessor();
}
}
void triggerUpdateProcessor() {
if (POST_UPDATES_ON_ANIMATION && mHasFixedSize && mIsAttached) {
ViewCompat.postOnAnimation(RecyclerView.this, mUpdateChildViewsRunnable);
} else {
mAdapterUpdateDuringMeasure = true;
requestLayout();
}
}
}
被觀察者抽象類:
/**
* Provides methods for registering or unregistering arbitrary observers in an {@link ArrayList}.
*
* This abstract class is intended to be subclassed and specialized to maintain
* a registry of observers of specific types and dispatch notifications to them.
*
* @param T The observer type.
*/
public abstract class Observable<T> {
/**
* The list of observers. An observer can be in the list at most
* once and will never be null.
*/
protected final ArrayList<T> mObservers = new ArrayList<T>();
/**
* Adds an observer to the list. The observer cannot be null and it must not already
* be registered.
* @param observer the observer to register
* @throws IllegalArgumentException the observer is null
* @throws IllegalStateException the observer is already registered
*/
public void registerObserver(T observer) {
if (observer == null) {
throw new IllegalArgumentException("The observer is null.");
}
synchronized(mObservers) {
if (mObservers.contains(observer)) {
throw new IllegalStateException("Observer " + observer + " is already registered.");
}
mObservers.add(observer);
}
}
/**
* Removes a previously registered observer. The observer must not be null and it
* must already have been registered.
* @param observer the observer to unregister
* @throws IllegalArgumentException the observer is null
* @throws IllegalStateException the observer is not yet registered
*/
public void unregisterObserver(T observer) {
if (observer == null) {
throw new IllegalArgumentException("The observer is null.");
}
synchronized(mObservers) {
int index = mObservers.indexOf(observer);
if (index == -1) {
throw new IllegalStateException("Observer " + observer + " was not registered.");
}
mObservers.remove(index);
}
}
/**
* Remove all registered observers.
*/
public void unregisterAll() {
synchronized(mObservers) {
mObservers.clear();
}
}
}
被觀察者具體實現類:
static class AdapterDataObservable extends Observable<AdapterDataObserver> {
public boolean hasObservers() {
return !mObservers.isEmpty();
}
public void notifyChanged() {
// since onChanged() is implemented by the app, it could do anything, including
// removing itself from {@link mObservers} - and that could cause problems if
// an iterator is used on the ArrayList {@link mObservers}.
// to avoid such problems, just march thru the list in the reverse order.
for (int i = mObservers.size() - 1; i >= 0; i--) {
mObservers.get(i).onChanged();
}
}
public void notifyItemRangeChanged(int positionStart, int itemCount) {
notifyItemRangeChanged(positionStart, itemCount, null);
}
public void notifyItemRangeChanged(int positionStart, int itemCount,
@Nullable Object payload) {
// since onItemRangeChanged() is implemented by the app, it could do anything, including
// removing itself from {@link mObservers} - and that could cause problems if
// an iterator is used on the ArrayList {@link mObservers}.
// to avoid such problems, just march thru the list in the reverse order.
for (int i = mObservers.size() - 1; i >= 0; i--) {
mObservers.get(i).onItemRangeChanged(positionStart, itemCount, payload);
}
}
public void notifyItemRangeInserted(int positionStart, int itemCount) {
// since onItemRangeInserted() is implemented by the app, it could do anything,
// including removing itself from {@link mObservers} - and that could cause problems if
// an iterator is used on the ArrayList {@link mObservers}.
// to avoid such problems, just march thru the list in the reverse order.
for (int i = mObservers.size() - 1; i >= 0; i--) {
mObservers.get(i).onItemRangeInserted(positionStart, itemCount);
}
}
public void notifyItemRangeRemoved(int positionStart, int itemCount) {
// since onItemRangeRemoved() is implemented by the app, it could do anything, including
// removing itself from {@link mObservers} - and that could cause problems if
// an iterator is used on the ArrayList {@link mObservers}.
// to avoid such problems, just march thru the list in the reverse order.
for (int i = mObservers.size() - 1; i >= 0; i--) {
mObservers.get(i).onItemRangeRemoved(positionStart, itemCount);
}
}
public void notifyItemMoved(int fromPosition, int toPosition) {
for (int i = mObservers.size() - 1; i >= 0; i--) {
mObservers.get(i).onItemRangeMoved(fromPosition, toPosition, 1);
}
}
}
很像吧,還有很多地方都用的觀察者模式呢,比如jetpack裏面!