您的位置:首页 > 其它

观察者模式

2016-07-22 17:00 134 查看
观察者模式是非常实用的一种设计模式。他可以降低对象之间的耦合度,实现松耦合。

比如我们编程中,如果你的一个对象获得了一个数据,他要将这个数据通知很多别的对象,让那些对象实现数据的更新。最简单的方法如下:

T1 t1=new T1();
T2 t2=new T2();
T3 t3=new T3();
t2.update(info);
t1.update(info);
t3.update(info);


但是这样你会发现,代码明显重复。针对具体实现编程,这样会使我们日和增加或删除某个要通知的对象必须要修改程序。比如你不想通知t2了,你要对源程序进行代码的修改。

解决的办法是 我们可以把拥有公共update的被通知对象抽象出来。然后让该通知者在每次有数据更新的时候实现数据通知。这就引入了观察者模式。

所以被通知的对象都是观察者,负责通知的为主题对象(各种主题通知如邮件主题、新闻等主题都可)。

我就采用比较易懂的语言说下吧。

比如一群码农想在公司附近找房子住,但是呢码农们都比较忙,没有时间去找房子。于是他们找到了房产中介,让中介帮他们找房子,中介有房源消息的时候再通知码农们。

这个事例之中的 码农就是观察者,房产中介就是主题对象。房产中介有新的消息要对观察者(码农们)进行实时的通知。观察者们(码农们)没收到通知的时候就正常的干自己的工作,当收到消息的时候可以采取适当的行动。下面来进行代码的实现。

首先是码农们都是一类人,所以可以将码农们抽象出来,他们除了干各自的工作外,他们都有些公共的行为如查找房子看房子。

先写码农的祖先

public interface Observer {
public void update(String info);
public void seeHouse(String info);
}
下面是各个码农了,他们都实现了祖先

package ObserveMode;

public class Coder1 implements Observer {
public Coder1(Subject sub) {
// TODO Auto-generated constructor stub
sub.registerObserver(this);
}
@Override
public void update(String info) {
// TODO Auto-generated method stub
display(info);
}
@Override
public void seeHouse(String info) {
// TODO Auto-generated method stub
System.out.println("coder1 获得消息:"+info+" 内心思想:可以观望下");
}

}
class Coder2 implements Observer {
public Coder2(Subject sub) {
// TODO Auto-generated constructor stub
sub.registerObserver(this);
}
@Override
public void update(String info) {
// TODO Auto-generated method stub
display(info);
}
@Override
public void seeHouse(String info) {
// TODO Auto-generated method stub
System.out.println("coder2 获得消息:"+info+" 内心思想:这不是coder2我需要的房子");
}

}
class Coder3 implements Observer {
public Renter3(Subject sub) {
// TODO Auto-generated constructor stub
sub.registerObserver(this);
}
@Override
public void update(String info) {
// TODO Auto-generated method stub
display(info);
}
@Override
public void seeHouse(String info) {
// TODO Auto-generated method stub
System.out.println("coder3 获得消息:"+info+" 内心思想;我要抓紧必须抢占");
}

}
下面是主题类抽象,他们都有同样的一些功能。将这些功能抽象为接口

public interface Subject {
public void notifyObserver();//通知码农们
public void registerObserver(Observer obs);//注册观察者
public void removeObserver(Observer obs);//删除该观察者
}下面是房产中介了,房产中介不唯一,每个观察者可以关注多个房产中介。但是所有房产中介都有同样的一些功能,都实现Subject接口
public class Agency1 implements Subject {
private ArrayList<Observer> obsList;//用集合存储观察者集,实现一对多的关系
private String information;
public Agency1() {
// TODO Auto-generated constructor stub
obsList=new ArrayList<Observer>();
}
@Override
public void notifyObserver() {
// TODO Auto-generated method stub
for(Observer ob:obsList)
ob.update(this.information);
}

@Override
public void registerObserver(Observer obs) {
// TODO Auto-generated method stub
obsList.add(obs);
}

@Override
public void removeObserver(Observer obs) {
// TODO Auto-generated method stub
int i=obsList.indexOf(obs);
if(i>=0)
obsList.remove(i);
}
public void measurementsChanged(){
notifyObserver();
}
public void setInfor(String info){//得到新消息,设置新消息并通知所有观察者
this.information=info;
measurementsChanged();
}

}coder1 获得消息:中关村有好房子 内心思想:可以观望下

coder2 获得消息:中关村有好房子 内心思想:这不是coder2我需要的房子

coder3 获得消息:中关村有好房子 内心思想:我要抓紧必须抢占

运行结果如上。
内心思想为每个码农的思想,其实就是每个码农获得消息后该采取的后续行动,各自不同。

这样观察者模式就实现了。如果新增码农找房子,中介只需要将其注册如list中,如果某个码农不想找了那么中介直接remove删除就好,而不需要对代码就行修改。实现了松耦合。

主题和观察者之间定义了一对多的关系。观察者依赖于主题,只要主题状态一有变更,观察者便会接收到通知。

关于观察者,主题只知道观察者实现了某个接口(Observer接口)。不需要知道具体类是谁,做了什么,什么细节
任何时候可以增加新的观察者。同时也可以删除观察者。
有新类型的观察者出现,主题的代码不需要更改。改变主题或者观察者任何一方不会影响另一方,因为二者是松耦合的,只要他们之间的接口仍被遵守,就能自由改变他们。
观察者模式设计原则为:为了交互对象之间的松耦合设计而努力。对象之间的互相依赖降到了最低

其实在java源码类中有很多也是观察者模式思想。

如java swing中 JButton类。该类有添加监听器(实际就是添加观察者)。当JButton改变时,监听器获得消息进行相应行动。

同时java也有自己的Observer为java.util.Observer类。但是该类有些许问题,该类为抽象类,这样我们的观察者必须继承该类。这在只支持但继承的java语言会带来很大的劣势,让观察者无法再继承别的父类,不可取。其实我们可以写Observer不难。

观察者模式现实了主题1对观察者多的一对多的关系。主题不知道观察者的细节,只知道观察者实现了观察者接口。

总结下:观察者模式能降低对象间的关联程度,实现松耦合。符合”开闭原则”,但是呢这种广播通知必定会耗费大量时间。如果观察者与主题之间是循环依赖的话,这种广播触发会导致系统的崩溃。

以上是个人的一点浅见。不喜勿喷。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息