Error message here!

Hide Error message here!

忘记密码?

Error message here!

请输入正确邮箱

Hide Error message here!

密码丢失?请输入您的电子邮件地址。您将收到一个重设密码链接。

Error message here!

返回登录

Close

观察者模式

huansky 2019-02-16 23:13:00 阅读数:213 评论数:0 点赞数:0 收藏数:0

定义

当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知它的依赖对象。观察者模式属于行为型模式。

解释:简单来说对象 A 需要关注对象 B 的状态,根据对象 B 的不同状态来做一些调整。比如播放器的 UI 变化,会依赖当前的播放状态,一旦播放状态改变了,就需要调整 UI 的显示。

使用场景

  • 一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。
  • 一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。

  • 一个对象必须通知其他对象,而并不知道这些对象是谁。

  • 需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制。

 具体实践

根据上面说的,下面我们来实现一个简单的观察者模式。

 观察者

先定义一个观察者接口,具体的观察者都需要实现该接口。

package com.sjq.observer;
/***
* 抽象观察者
* 定义了一个update()方法,当被观察者调用notifyObservers()方法时,观察者的update()方法会被回调。*/
public interface Observer {
public void update(String message);
}

接着,就是一个具体的观察者,在 update 中添加数据改变后的操作逻辑。

package com.sjq.observer;
/**
* 观察者
* 实现了update方法
*/
public class User implements Observer {
private String name;
private String message;
public User(String name) {
this.name = name;
}
@Override
public void update(String message) {
this.message = message;
read();
}
public void read() {
System.out.println(name + " 收到推送消息: " + message);
}
}

 被观察者

同样的,需要定义一个被观察者接口,所有具体的被观察者对象都需要实现该接口。

package com.sjq.observer;
/***
* 抽象被观察者接口
* 声明了添加、删除、通知观察者方法
*/
public interface Observerable {
public void registerObserver(Observer o);
public void removeObserver(Observer o);
public void notifyObserver();
}

 定义具体的被观察者对象,实现了 Observerable 接口,对 Observerable 接口的三个方法进行了具体实现,同时有一个 List 集合,用以保存注册的观察者,等需要通知观察者时,遍历该集合即可。

package com.sjq.observer;
import java.util.ArrayList;
import java.util.List;
/**
* 被观察者,也就是微信公众号服务
* 实现了Observerable接口,对Observerable接口的三个方法进行了具体实现
*/
public class WechatServer implements Observerable {
//注意到这个List集合的泛型参数为Observer接口,设计原则:面向接口编程而不是面向实现编程
private List<Observer> list;
private String message;
public WechatServer() {
list = new ArrayList<Observer>();
}
@Override
public void registerObserver(Observer o) {
list.add(o);
}
@Override
public void removeObserver(Observer o) {
if(!list.isEmpty())
list.remove(o);
}
//遍历
 @Override
public void notifyObserver() {
for(int i = 0; i < list.size(); i++) {
Observer oserver = list.get(i);
oserver.update(message);
}
}
public void setInfomation(String s) {
this.message = s;
System.out.println("微信服务更新消息: " + s);
//消息更新,通知所有观察者
 notifyObserver();
}
} 

代码测试

完成上面的工作之后,咱们就可以测试咱们写的代码了,看看能不能跑起来。具体如下:

package com.sjq.observer;
public class Test {
public static void main(String[] args) {
WechatServer server = new WechatServer();
Observer userZhang = new User("ZhangSan");
Observer userLi = new User("LiSi");
Observer userWang = new User("WangWu");
server.registerObserver(userZhang);
server.registerObserver(userLi);
server.registerObserver(userWang);
server.setInfomation("PHP是世界上最好用的语言!");
System.out.println("----------------------------------------------");
server.removeObserver(userZhang);
server.setInfomation("JAVA是世界上最好用的语言!");
}
} 

注意事项: 

  • JAVA 中已经有了对观察者模式的支持类。

  • 避免循环引用。

  • 如果顺序执行,某一观察者错误会导致系统卡壳,一般采用异步方式。

Android 中的应用

  •  Android 中 Adapter 应用广泛,其实在 adapter 中就存在观察者模式得应用。比如 ListView, 当我们调用 setAdapter() 时候,内部是通过观察者模式来通知数据变化的,当数据发生变化,就会通知 ListView 自身去重新绘制。

  • BrocastReceive 广播。有动态注册和静态注册,其实也是观察者模式得一种应用。

  • 另外经常可见一些 addXXXListener 方法,其实这类也可以当做是观察者的一种体现。 

参考文献

1、http://www.runoob.com/design-pattern/observer-pattern.html

2、JAVA设计模式之观察者模式

 

版权声明
本文为[huansky]所创,转载请带上原文链接,感谢
https://www.cnblogs.com/huansky/p/10389751.html

编程之旅,人生之路,不止于编程,还有诗和远方。
阅代码原理,看框架知识,学企业实践;
赏诗词,读日记,踏人生之路,观世界之行;

支付宝红包,每日可领