全国咨询/投诉热线:400-618-4000

java设计模式之观察者模式

更新时间:2018年12月07日11时50分 来源:传智播客 浏览次数:

---

typora-root-url: pics

---

# 设计模式之观察者模式

## 概述

​ 观察者模式,有时又被称为模型-视图(View)模式,有的叫发布-订阅模式,监听模式或从属者模式,是软件设计模式的一种。在此种模式中,一个目标物件管理所有相依于它的观察者物件,并且在它本身的状态改变时主动发出通知。一般通过呼叫各观察者所提供的方法来实现。此种模式通常被用来实现事件处理系统。

## 重要的角色

1. 观察者: 观察目标对象的状态、行为等的的主体。观察将自己存放到被观察对象中,被观察对象将观察者存放在一个容器(Vector)里。

2. 被观察的对象:被观察者所研究或关注的对象。当被观察的对象发生了某种变化时,将循环遍历容器中的所有观察者,并将发生的变化通知予观察者。

## 观察者模式结构图

![observer_structure](/observer_structure.png)

### 说明

* Observable 是一个接口,定义了被观察者主体所具备的方法,实现这个接口的主体可以拥有多个观察者,当主体对象的状态发生改变时,可以通知到所有的观察者

* addObserver: 添加新的观察者

* delObserver: 移除原有的观察者

* notifyObservers: 当主体对象发生改变时,通知所有的观察者

* Observer 也是一个接口,定义了观察者所具备的方法,当主体发生变化时,通过调用update方法通知观察者,你观察的主体发生了变化

* ConcreteSubject 是Observable的具体实现类,被观察的对象,也可称为观察的实 "物"

* ConcreteObserver 是Observer的实现类,实现这个接口的就是观察者,可以实现对实 “物” 的观察

## 举例

​ 我们都知道微信有个叫公众号的服务,只要公众号发布新的消息,关注了这个公众的微信用户就能收最新的消息,如果用户取消了该公众号的关注,就不再收到由该公众号发布出来的消息了。

## 分析

​ 这里的微信公众号可以看成是一个 被观察对象,即观察的对象,而关注了这个公众号的所有用户都是观察者

​ 下面我们可以通过代码来简单模拟一下

## 代码实现

### 1. 创建普通java工程

​ ![project](/project.png)

### 2. Observer

```java

package com.itheima.demo;

/**

* 观察者接口

*/

public interface Observer {

/**

* 被观察体发生变化时调用的方法,用来通知观察者

* @param args

*/

void update(Object args);

/**

* 获取观察者名称

* @return

*/

String getName();

}

```

### 3. Observable

```java

package com.itheima.demo;

/**

* 被观察者接口

*

*/

public interface Observable {

/**

* 添加观察者

* @param observer

*/

void addObserver(Observer observer);

/**

* 解除观察者

* @param observer

*/

void delObserver(Observer observer);

/**

* 通知所有的观察者

*/

void notifiyObservers(Object args);

}

```

### 4. WeChatOfficialAccount

```java

package com.itheima.demo;

import java.util.Vector;

/**

* 被观察者,微信公众号

*

*/

public class WeChatOfficialAccount implements Observable {

private String name;

/**

* 保存所有的观察者

*/

private Vector observers;

public WeChatOfficialAccount(String name) {

this.name = name;

observers = new Vector();

}

@Override

public synchronized void addObserver(Observer observer) {

System.out.println(observer.getName() + " 关注了公众号 " + this.name);

this.observers.add(observer);

}

@Override

public synchronized void delObserver(Observer observer) {

observers.remove(observer);

}

@Override

public void notifiyObservers(Object args) {

Observer[] arr = observers.toArray(new Observer[] {});

for(int i = arr.length - 1; i >= 0; i--) {

// 通知每个观察者

arr[i].update(args);

}

}

/**

* 发布新的消息

* @param message

*/

public void postMessage(String message) {

System.out.println(name + "微信公众号发布新的消息: " + message);

notifiyObservers(message);

}

}

```

### 5. WeChatUser

```java

package com.itheima.demo;

/**

* 微信用户

*

*/

public class WeChatUser implements Observer {

private String username;

public WeChatUser(String username) {

this.username = username;

}

@Override

public void update(Object args) {

readMessage((String)args);

}

public void readMessage(String message) {

System.out.println(String.format("%s 读取了信息-> %s", this.username,message));

}

@Override

public String getName() {

return this.username;

}

}

```

### 6. DemoMain 测试

```java

package com.itheima.demo;

public class DemoMain {

public static void main(String[] args) {

WeChatOfficialAccount wechat = new WeChatOfficialAccount("传智播客");

WeChatUser wechatUser = new WeChatUser("张三");

wechat.addObserver(wechatUser);

wechatUser = new WeChatUser("李四");

wechat.addObserver(wechatUser);

wechatUser = new WeChatUser("王五");

wechat.addObserver(wechatUser);

wechat.postMessage("改变中国IT教育,我们正在行动...");

}

}

```

### 7. 运行结果

​ ![result](/result.png)

## 总结

优点:观察者模式在被观察者和观察者之间建立一个抽象的耦合。被观察者并不认识任何一个具体观察者,当发生变化时,只需要调用它们共有的接口方法就可以了。

缺点:

* 如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间

* 如果在被观察者之间有循环依赖的话,被观察者会触发它们之间进行循环调用,导致系统崩溃。

* 如果对观察者的通知是通过另外的线程进行异步投递的话,系统必须保证投递是以自恰的方式进行的

* 虽然观察者模式可以随时使观察者知道所观察的对象发生了变化,但无法知道这个变化的过程java

javaee

python

web

ui

cloud

test

c

netmarket

pm

Linux

movies

robot

uids

北京校区

    14天免费试学

    基础班入门课程限时免费

    申请试学名额

    15天免费试学

    基础班入门课程限时免费

    申请试学名额

    15天免费试学

    基础班入门课程限时免费

    申请试学名额

    15天免费试学

    基础班入门课程限时免费

    申请试学名额

    20天免费试学

    基础班入门课程限时免费

    申请试学名额

    8天免费试学

    基础班入门课程限时免费

    申请试学名额

    20天免费试学

    基础班入门课程限时免费

    申请试学名额

    5天免费试学

    基础班入门课程限时免费

    申请试学名额

    0天免费试学

    基础班入门课程限时免费

    申请试学名额

    12天免费试学

    基础班入门课程限时免费

    申请试学名额

    5天免费试学

    基础班入门课程限时免费

    申请试学名额

    5天免费试学

    基础班入门课程限时免费

    申请试学名额

    10天免费试学

    基础班入门课程限时免费

    申请试学名额