设计模式-观察者模式
概述
有时被称作发布/订阅模式,观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。
解决的问题
将一个系统分割成一个一些类相互协作的类有一个不好的副作用,那就是需要维护相关对象间的一致性。我们不希望为了维持一致性而使各类紧密耦合,这样会给维护、扩展和重用都带来不便。观察者就是解决这类的耦合关系的。
优点
观察者模式解除了主题和具体观察者的耦合,让耦合的双方都依赖于抽象,而不是依赖具体。从而使得各自的变化都不会影响另一边的变化。
缺点
依赖关系并未完全解除,抽象通知者依旧依赖抽象的观察者。
适用场景
当一个对象的改变需要给变其它对象时,而且它不知道具体有多少个对象有待改变时。
一个抽象某型有两个方面,当其中一个方面依赖于另一个方面,这时用观察者模式可以将这两者封装在独立的对象中使它们各自独立地改变和复用。
Subject.java
package com.lxf.observer;
import java.util.Observable;
/**
* @address BeiJing
* @author LiXufei
* 被观察者实体类<目标>
*/
public class Subject extends Observable {
//消息内容
private String mContent;
public String getmContent() {
return mContent;
}
public void setmContent(String mContent) {
this.mContent = mContent;
//设置更新消息内容时通知观察者接受消息
this.setChanged();
this.notifyObservers(mContent);
}
}
Observer.java
package com.lxf.observer;
import java.util.Observable;
/**
* @address BeiJing
* @author LiXufei
* 观察者实体类
*/
public class Observer implements java.util.Observer {
//观察者名称
private String mName;
public String getmName() {
return mName;
}
public void setmName(String mName) {
this.mName = mName;
}
public void update(Observable arg0, Object arg1) {
//接受消息内容
//判断观察者
if (mName.equals("观察者1")) {
System.out.println(mName+"接受了消息:[推]"+arg1);
System.out.println(mName+"接受了消息:[拉]"+((Subject)arg0).getmContent());
}else if(mName.equals("观察者2")){
System.out.println(mName+"接受了消息:[推]"+arg1);
System.out.println(mName+"接受了消息:[拉]"+((Subject)arg0).getmContent());
}
}
}
Test.java
package com.lxf.observer;
/**
* @address BeiJing
* @author LiXufei
* 测试类
*/
public class Test {
public static void main(String[] args) {
//创建被观察者
Subject subject = new Subject();
//创建观察者并设置名称
Observers observer1 = new Observers();
Observers observer2 = new Observers();
observer1.setmName("观察者1");
observer2.setmName("观察者2");
//注册观察者
subject.addObserver(observer1);
subject.addObserver(observer2);
//更新被观察者消息
subject.setmContent("这是一条消息");
}
}
运行结果:
观察者2收到一条消息:这是一条消息【拉2】
观察者2收到一条消息:这是一条消息【推2】
观察者1收到一条消息:这是一条消息【拉1】
观察者1收到一条消息:这是一条消息【推1】
拉模式和推模式:
推(push)模式是一种基于客户器/服务器机制、由服务器主动将信息送到客户器的技术。在push模式应用中,服务器把信息送给客户器之前,并没有明显的客户请求。push事务由服务器发起。push模式可以让信息主动、快速地寻找用户/客户器,信息的主动性和实时性比较好。但精确性较差,可能推送的信息并不一定满足客户的需求。推送模式不能保证能把信息送到客户器,因为推模式采用了广播机制,如果客户器正好联网并且和服务器在同一个频道上,推送模式才是有效的。push模式无法跟踪状态,采用了开环控制模式,没有用户反馈信息。在实际应用中,由客户器向服务器发送一个申请,并把自己的地址(如IP、port)告知服务器,然后服务器就源源不断地把信息推送到指定地址。在多媒体信息广播中也采用了推模式。另外,如手机***、qq广播。
拉(pull)模式与推模式相反,是由客户器主动发起的事务。服务器把自己所拥有的信息放在指定地址(如IP、port),客户器向指定地址发送请求,把自己需要的资源“拉”回来。不仅可以准确获取自己需要的资源,还可以及时把客户端的状态反馈给服务器。