觀察者模式
觀察者模式是使用率非常高的一種設(shè)計(jì)模式。
什么是觀察模式俄讹?
對象間存在一對多的依賴關(guān)系疫衩,需要在某個(gè)對象改變的時(shí)候,依賴于該對象的所有其他對象都收到通知并進(jìn)行更新和相應(yīng)的業(yè)務(wù)操作剑鞍。
簡而言之,就是當(dāng)一個(gè)被觀察的對象改變了就要去通知它的觀察者爽醋,告訴觀察者我有變化了蚁署,你可以進(jìn)行你需要的處理操作。
無處不在的觀察者
情景一:小明(觀察者)給媽媽說飯熟了叫我吃飯蚂四,媽媽(被觀察者)等到飯熟了就會(huì)通知小明來吃飯了光戈。
情景二:代碼中有個(gè)需求需要監(jiān)聽用戶打開藍(lán)牙就關(guān)掉藍(lán)牙。這肯定需要使用觀察者模式遂赠,監(jiān)聽到藍(lán)牙打開了久妆,就通知相應(yīng)的觀察者,然后做關(guān)掉藍(lán)牙的操作跷睦。
觀察者模式的作用就是使對象解耦筷弦,將觀察者和被觀察者完全隔離。上述情景抑诸,小明可以在媽媽做飯的時(shí)候?qū)懽鳂I(yè)烂琴,等媽媽叫她吃飯的時(shí)候再去吃飯。這樣小明和媽媽就可以各干各的事情哼鬓,完全解耦。
最簡單的觀察者模式Demo
項(xiàng)目結(jié)構(gòu)如下边灭,只有4個(gè)類超級簡單异希。
- 被觀察接口,三個(gè)方法绒瘦,注冊監(jiān)聽者称簿,注銷監(jiān)聽者,通知所有觀察者
/**
* 被觀察者接口
*/
public interface IObservable {
void registerObserver(IObserver observer);
void unregisterObserver(IObserver observer);
void notifyAllObservers();
}
- 觀察者接口:更新數(shù)據(jù)
/**
* 觀察者接口
*/
public interface IObserver {
void update();
}
- 觀察者實(shí)現(xiàn)類
/**
* 觀察者實(shí)現(xiàn)類
*/
public class ObserverImpl implements IObserver{
private static final String TAG = "ObserverImpl";
private String observerName;
public ObserverImpl(String observerName){
this.observerName = observerName;
}
@Override
public void update() {
Log.i(TAG,observerName +"數(shù)據(jù)更新了----->");
}
}
- 被觀察者實(shí)現(xiàn)類
/**
* 被觀察者實(shí)現(xiàn)類
*/
public class ObservableImpl implements IObservable{
private List<IObserver> mObserversList = new ArrayList<>();//注冊的所有觀察者集合
@Override
public void registerObserver(IObserver observer) {
if (observer == null) {
throw new IllegalArgumentException("The observer is null.");
}
synchronized(mObserversList) {
if (mObserversList.contains(observer)) {
throw new IllegalStateException("Observer " + observer + " is already registered.");
}
mObserversList.add(observer);
}
}
@Override
public void unregisterObserver(IObserver observer) {
if (observer == null) {
throw new IllegalArgumentException("The observer is null.");
}
synchronized(observer) {
int index = mObserversList.indexOf(observer);
if (index == -1) {
throw new IllegalStateException("Observer " + observer + " was not registered.");
}
mObserversList.remove(index);
}
}
@Override
public void notifyAllObservers() {
for(int i = 0;i < mObserversList.size(); i++){
IObserver observer = mObserversList.get(i);
observer.update();
}
}
}
其實(shí)看了被觀察者的實(shí)現(xiàn)惰帽,原來所謂的注冊監(jiān)聽和取消監(jiān)聽都是靠一個(gè)list集合來維護(hù)憨降,最后的通知觀察者的本質(zhì)也就是遍歷這個(gè)list集合,然后調(diào)用觀察者的update方法该酗。
- 測試demo
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ObserverImpl observer1 = new ObserverImpl("觀察者 1 :");
ObserverImpl observer2 = new ObserverImpl("觀察者 2 :");
ObservableImpl observable = new ObservableImpl();//被觀察者
observable.registerObserver(observer1);
observable.registerObserver(observer2);
// observable.unregisterObserver(observer2);
observable.notifyAllObservers();
}
}
- 測試結(jié)果:
我們可以從結(jié)果看出注冊的2個(gè)觀察者都收到數(shù)據(jù)更新的消息了授药。這就是目前演示的最簡單的觀察者模式的寫法士嚎。
觀察者模式在Android源碼中的使用:
- 四大組件其中一個(gè):Broadcast其實(shí)就是一個(gè)訂閱發(fā)布的觀察者模式。我們注冊廣播接收者registerReceiver悔叽,當(dāng)sendBroadcast的發(fā)送廣播時(shí)莱衩,onReceive 方法就會(huì)被調(diào)用。這是一個(gè)非常典型的觀察者模式娇澎。onReceive方法就類似于上述例子中的觀察者接口中的update()方法笨蚁。細(xì)細(xì)想來,其實(shí)我們見過的很多代碼其實(shí)使用的就是觀察者模式趟庄。
-其實(shí)ListView使用Adapter模式也是觀察者模式
我們在使用ListView的時(shí)候會(huì)使用到一個(gè)方法notifyDataSetChanged();每當(dāng)有數(shù)據(jù)源更新括细,調(diào)用該方法就可以更新頁面。notifyDataSetChanged()源碼其實(shí)和上述的被觀察者實(shí)現(xiàn)類里面 notifyAllObservers()的方法類似戚啥。
Android源碼其實(shí)就是一個(gè)很好的學(xué)習(xí)的例子奋单,我們平時(shí)使用的很多模式在源碼中都有體現(xiàn)。觀察者模式是我們必現(xiàn)要掌握的設(shè)計(jì)模式之一虑鼎。