观察者模式定义:
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方法就好了。提前说 好处多。
从上面我们可以总结出来 ,其实对象分两类:消息的生产者 和消息的消费者