一、什么是观察者模式
观察者(observer)模式是行为模式之一,它的作用是当一个被观察对象的状态发生变化时,能够自动通知相关的观察者对象,自动更新观察者对象中被观察对象的状态。它提供给关联对象一种同步通信的手段,使某个对象与依赖它的其他对象之间保持状态同步。
观察者(observer)模式多被应用于以下场景:
- 侦听事件驱动程序设计中的外部事件
- 侦听/监视某个对象的状态变化
- 发布者/订阅者(publisher/subscriber)模型中,当一个外部事件(新的产品,消息的出现等等)被触发时,通知邮件列表中的订阅者
观察者模式中的角色及其职责如下:
抽象被观察者(subject)角色 被观察对象的抽象类,为所有具体被观察者角色提供了一个统一接口,主要包括添加、删除、通知观察者对象方法,其内包含一个用以储存所有观察者对象的容器(collection),当被观察者的状态发生变化时,需要通知容器中所有观察者对象,并维护(添加,删除,通知)观察者对象列表。
具体被观察者(concretesubject)角色 被观察者的具体实现,包含一些基本的属性状态及其他操作,当具体被观察者的状态发生变化时,会给注册的所有观察者对象发送通知,以提示观察者对象们对其内被观察对象的状态进行更新。
抽象观察者(observer)角色 这是一个抽象角色,通常被定义为接口,为所有的具体观察者定义一个接口,当收到被观察对象状态发生变化的通知时更新自己。
具体观察者(concreteobserver)角色 观察者的具体实现,得到通知后将对内部被观察对象的状态进行更新,并完成一些具体的业务逻辑处理。
观察者模式结构示意源代码如下:
抽象被观察者(subject)角色
public abstract class subject {
//用来保存注册过的观察者
private list observers=new arraylist();
//注册一个观察者
public void registerobserver(observer observer){
this.observers.add(observer);
}
//删除一个观察者
public void unregisterobserver(observer observer){
this.observers.remove(observer);
}
//通知所有观察者进行状态更新
public void notifyobservers(subject subject){
for(observer o:observers){
o.update(subject);
}
}
}
具体被观察者(concretesubject)角色
public class concretesubject extends subject {
//具体被观察者类可以具有自己的属性或状态
private string state;
public string getstate() {
return state;
}
public void setstate(string newstate){
this.state = newstate;
system.out.println("被观察者自身状态更新为:" this.state);
//状态发生改变,通知所有观察者
this.notifyobservers(this);
}
}
抽象观察者(observer)角色
public interface observer{
//更新观察者的状态
public void update(subject subject);
}
具体观察者(concreteobserver)角色
public class concreteobservera implements observer {
private concretesubject subject;
public concretesubject getsubject() {
return subject;
}
public void setsubject(concretesubject subject) {
this.subject = subject;
}
@override
public void update(subject subject) {
this.subject=(concretesubject)subject;
system.out.println("观察者a中被观察对象的状态更新为:" this.subject.getstate());
}
}
public class concreteobserverb implements observer {
private concretesubject subject;
public concretesubject getsubject() {
return subject;
}
public void setsubject(concretesubject subject) {
this.subject = subject;
}
@override
public void update(subject subject) {
this.subject=(concretesubject)subject;
system.out.println("观察者b中被观察对象的状态更新为:" this.subject.getstate());
}
}
编写一个mainclass类来测试一番。
public class mainclass {
public static void main(string[] args) {
//创建被观察者对象
concretesubject subject=new concretesubject();
//创建观察者对象
concreteobservera observera=new concreteobservera();
concreteobserverb observerb=new concreteobserverb();
//为被观察者对象注册观察者
subject.registerobserver(observera);
subject.registerobserver(observerb);
subject.setstate("复活中...");
system.out.println();
system.out.println("*************一千年以后...*************");
system.out.println();
subject.setstate("疯狂杀戮中...");
}
}
运行mainclass打印结果如下:
被观察者自身状态更新为:复活中...
观察者a中被观察对象的状态更新为:复活中...
观察者b中被观察对象的状态更新为:复活中...
*************一千年以后...*************
被观察者自身状态更新为:疯狂杀戮中...
观察者a中被观察对象的状态更新为:疯狂杀戮中...
观察者b中被观察对象的状态更新为:疯狂杀戮中...
在java语言的java.util库里面有一个observable类和一个observer接口,通过两者配合使用可以实现观察者模式。
observable类:
observable中文意思“可以被观察的”,即observable类是可以被观察的,想要实现观察者模式只需将你想要被观察的类继承自observable类即可。
一个 observable对象可以有一个或多个观察者,观察者可以是实现了observer接口的任意对象。一个observable对象状态改变后,会调用notifyobservers()方法来通知观察者。
以下是observable类提供的一些常用方法:
public void addobserver(observer o) //向观察者集合中添加观察者
public void deleteobserver(observer o) //从观察者集合中删除某一个观察者
public void notifyobservers(object arg) //如果haschanged方法指示对象已改变,则通知其所有观察者,并调用 clearchanged 方法来清除对象的已改变标记。此方法可不带参数,仅将observable对象传递给update()方法,此时update方法中arg参数为null。
public void deleteobservers() //清除观察者列表,使此对象不再有任何观察者
protected void setchanged() //标记observable对象已经改变
protected void clearchanged() //清除observable对象已改变标记
public boolean haschanged() //测试对象是否改变
public int countobservers() //返回observable对象的观察者数目
observer接口:
observer接口只包含一个update()方法,该方法仅接受两个参数:继承自observable类的被观察对象和传递给notifyobservers() 方法的参数。当observable(被观察者)对象状态发生改变时将通过notifyobservers()方法向所有的observer(观察者)发送更新通知,observer(观察者)对象在收到通知后即调用此方法完成状态更新。
void update(observable o,
object arg)
接下来我们举个简单的例子来演示一下如何使用observable类和observer接口实现观察者模式,去年2015年是牛市,炒股的基本都发家了,在此我们以炒股为例。
在炒股这个例子中,不用我说,相信你也想的到:股票stock就是我们的被观察者。
import java.util.observable;
public class stock extends observable{
//为股票的状态创建一个枚举类:rise 涨,fall 跌
public enum stockstate{
rise,fall
}
//股票涨跌状态
private stockstate state;
//股票的价格
private double price;
//股票的历史最低价格
private double lowestprice;
//股票无参的构造方法
public stock(){
}
//股票的带参数构造方法
public stock(stockstate state, double price, double lowestprice) {
super();
this.state = state;
this.price = price;
lowestprice = lowestprice;
}
public stockstate getstate() {
return state;
}
private void setstate(stockstate state) {
this.state = state;
}
public double getprice() {
return price;
}
public void setprice(double price) {
if(price
我们这些只有韭菜命的股民自然就是观察者了。
import java.util.observable;
import java.util.observer;
import com.ibeifeng.news.stock.stockstate;
public class investor implements observer {
public void update(observable o, object arg) {
stock stock=(stock)o;
if(stock.getprice()==stock.getlowestprice())
{
system.out.println("股票已经跌到历史最低了,我得赶紧抄底...");
}
else{
if(stock.getstate().equals(stockstate.rise)){
system.out.println("股票在涨,目前价格:" stock.getprice());
}
else{
system.out.println("股票在跌,目前价格:" stock.getprice());
}
}
}
}
在客户端里面测试一下。
public class client{
public static void main(string[] args) {
stock stock=new stock(stockstate.fall,14.7d,13.2d);
stock.addobserver(new investor());
stock.setprice(13.7);
stock.setprice(12.6);
stock.setprice(14.0);
}
}
运行程序打印结果如下:
股票在跌,目前价格:13.7
股票已经跌到历史最低了,我得赶紧抄底...
股票在涨,目前价格:14.0
观察者observer模式解决了对象之间一对多的复杂依赖关系问题,大大地提高了程序的可维护性和可扩展性,也很好的符合了开放-封闭原则。