觀察者模式定義:
Define a one-to-many dependency between objects so that when one object changes state, all its dependency are notified and updated automatically.
翻譯過來就是,定義一種一對多的依賴關係,使得每當一個對象改變狀態,則所有依賴於它的對象都會得到通知並被自動更新。
觀察者模式也叫做發佈訂閱模式。
場景分析:
其實這種場景在我們生活中非常常見,不知你住沒注意,媽媽把飯菜做好了,然後挨個通知你爸爸和你。
我們分析一下這個場景
有三個對象: 爸爸、 媽媽和兒子。其中 媽媽做飯,做好了之後通知爸爸和兒子。
首先,創建Mum對象 他有兩個方法做飯cooking()和通知其他人notifyOthers()。
/**
* Created by dushangkui on 2017/3/22.
*/
public class Mum {
private Dad dad;
private Son son;
public Mum(Dad dad, Son son) {
this.dad = dad;
this.son = son;
}
public static void main(String[] args) {
Dad dad = new Dad();
Son son = new Son();
Mum mum = new Mum(dad,son);
mum.cooking();
mum.notifyOthers();
}
private void cooking(){
System.out.println("開始做飯");
System.out.println("做飯結束");
}
private void notifyOthers(){
System.out.println("通知其他人吃飯");
dad.onRecive();
son.onRecive();
}
}
媽媽持有爸爸和兒子的引用,好通知他們。
爸爸和兒子都要有一個方法去接收這個消息並且做出反應。
/**
* Created by dushangkui on 2017/3/22.
*/
public class Dad {
public void onRecive(){
System.out.println("爸爸聽到了,正在過去");
}
}
/**
* Created by dushangkui on 2017/3/22.
*/
public class Son {
public void onRecive(){ System.out.println("兒子聽到了,但是不想吃飯"); }}
運行場景:
開始做飯
做飯結束
通知其他人吃飯
爸爸聽到了,正在過去
兒子聽到了,但是不想吃飯
好了,我們忠實的完成了之前的定義,一對多關係,媽媽狀態改變了通知爸爸和兒子然後做出變化。但是這個代碼真的好爛。爲什麼說爛呢,不能擁抱變化。如果家庭有好多成員呢,誰中午不想吃飯,誰要吃飯,飯做多了就要剩下,少了就不夠吃。現在我們變一下:
先定義一個家庭成員的接口,可以接收消息:
public interface Member {
void onRecive(String msg);
}
然後改造爸爸和兒子的類結構,實現Member接口:
public class Dad implements Member {
@Override
public void onRecive(String msg) {
System.out.println("爸爸聽到了消息【" + msg + "】,正在過去");
}
}
public class Son implements Member {
@Override
public void onRecive(String msg) {
System.out.println("兒子聽到了消息【" + msg + "】,但是不想過去");
}
}
媽媽也要與時俱進
public class Mum implements Member {
private List<Member> familyMember = new ArrayList<Member>();
public void eating(Member member){
familyMember.add(member);
}
public static void main(String[] args) {
Dad dad = new Dad();
Son son = new Son();
Mum mum = new Mum();
//提前打報告 要不要吃飯? 爸爸要吃飯 兒子不要吃飯
mum.eating(dad);
mum.eating(mum);
mum.cooking();
mum.notifyOthers();
}
private void cooking(){
System.out.println("開始做飯");
System.out.println("做"+familyMember.size()+"個人的飯。");
System.out.println("做飯結束");
}
private void notifyOthers(){
System.out.println("通知其他人吃飯");
for(Member member : familyMember){
member.onRecive("飯做好了");
}
}
@Override
public void onRecive(String msg) {
System.out.println("媽媽也要吃飯啊^.^");
}
}
嘗試下:
開始做飯
做2個人的飯。
做飯結束
通知其他人吃飯
爸爸聽到了消息【飯做好了】,正在過去
媽媽也要吃飯啊^.^
現在如果多了其他人也能夠很好適應,如果兒子想吃飯了 直接想媽媽報告 調用eating方法就好了。提前說 好處多。
從上面我們可以總結出來 ,其實對象分兩類:消息的生產者 和消息的消費者