17【观察者设计模式】

在这里插入图片描述

17.2 观察者设计模式的UML类图

观察者模式主要包含如下4个角色:

  • 1)抽象主题(ISubject):被观察的对象,该角色是一个接口,规范主题的方法,如订阅、退订、广播消息等;
  • 2)具体主题(ConcreteSubject):具体的被观察对象,对抽象主题中的方法进行实现
  • 3)抽象观察者(IObserver):抽象的观察者对象,用于观察主题,定义了响应通知的更新方法
  • 4)具体观察者(ConcreteObserver):对抽象观察者进行实现

在这里插入图片描述

17.3 观察者设计模式的实现

17.3.1 手动实现观察者

【案例】

定义一个消息处理模型,小灰、小蓝订阅自己喜欢观看的频道,当这些频道退出新的节目时需通知已经订阅过该频道的用户

  • 1)定义抽象主题:
package com.pattern.demo01\_手动实现观察者设计模式;

/\*\*
 \* @author lscl
 \* @version 1.0
 \* @intro: 抽象主题
 \*/
public interface ISubject {

    // 主题名称
    public String getName();

    // 增加订阅者
    public void attach(IObserver observer);

    // 删除订阅者
    public void detach(IObserver observer);

    // 广播消息
    public void notify(String message);

}

  • 定义具体主题:
package com.pattern.demo01\_手动实现观察者设计模式;

import java.util.ArrayList;
import java.util.List;

/\*\*
 \* @author lscl
 \* @version 1.0
 \* @intro: 具体主题(具体被观察者)
 \*/
public class TVSubject implements ISubject {

    // 频道的名称
    private String name;

    // 储存订阅频道的用户
    private List<IObserver> userList = new ArrayList();

    public TVSubject(String name) {
        this.name = name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public void attach(IObserver observer) {
        userList.add(observer);
    }

    @Override
    public void detach(IObserver observer) {
        userList.remove(observer);
    }

    @Override
    public void notify(String message) {
        for (IObserver observer : userList) {
            observer.update(this, message);
        }
    }
}

  • 3)定义抽象观察者:
package com.pattern.demo01\_手动实现观察者设计模式;

/\*\*
 \* @author lscl
 \* @version 1.0
 \* @intro: 抽象观察者类
 \*/
public interface IObserver {

    // 更新信息方法
    void update(ISubject subject, String message);
}

  • 4)定义具体观察者:
package com.pattern.demo01\_手动实现观察者设计模式;

/\*\*
 \* @author lscl
 \* @version 1.0
 \* @intro: 具体观察者(接收来自观察者的消息)
 \*/
public class UserObserver implements IObserver {
    // 用户名
    private String name;

    public UserObserver(String name) {
        this.name = name;
    }

    @Override
    public void update(ISubject subject, String message) {
        System.out.println("【" + name + "】接到来自【" + subject.getName() + "】的消息【" + message + "】");
    }
}

  • 5)测试类:
package com.pattern.demo01\_手动实现观察者设计模式;

/\*\*
 \* @author lscl
 \* @version 1.0
 \* @intro:
 \*/
public class Demo01 {

    public static void main(String[] args) {

        // 创建主题(频道、被观察者)
        ISubject subject = new TVSubject("CCTV");

        // 创建用户(观察者)
        UserObserver user1 = new UserObserver("小灰");
        UserObserver user2 = new UserObserver("小蓝");

        // 订阅CCTV频道
        subject.attach(user1);
        subject.attach(user2);

        // 发送给那些订阅过CCTV频道的用户
        subject.notify("今晚19.00播出新闻联播,敬请收看~");
    }
}

运行效果:

在这里插入图片描述

17.3.2 采用JDK提供的API实现

在 Java 中,提供有java.util.Observable类来表示主题,java.util.Observer来表示观察者,借助这两个类我们可以很轻松的实现观察者模式;

1)Observable类

Observable 类是一个抽象主题角色,它有一个 Vector 集合成员变量,用于保存所有要通知的观察者对象,常用方法如下:

  • void addObserver(Observer o):将新的观察者对象添加到集合中。
  • void notifyObservers(Object arg):调用集合中的所有观察者对象的update方法,通知它们数据发生改变。通常越晚加入集合的观察者越先得到通知。
  • void setChange():Observable类内部有个变量changed,默认为false;调用该方法将其设置为true,表示目标对象发生了变化。然后调用notifyObservers()方法才会通知观察者。
2)Observer 接口

Observer接口是抽象观察者角色,它监视目标对象的变化,当目标对象发生变化时,主题将会发送消息到观察者,并调用 update 方法,进行相应的工作。

3)实现观察者模式
  • 1)定义主题:
package com.pattern.demo02\_采用JDK的API实现;

import java.util.Date;
import java.util.Observable;

/\*\*
 \* @author lscl
 \* @version 1.0
 \* @intro: 被观察者
 \*/
public class TVSubject extends Observable {

    private String name;

    public TVSubject(String name) {
        this.name = name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void publish(String message) {
        super.setChanged();                 // 将changed设置为true(只有changed为true才能进行下面的广播消息)
        super.notifyObservers(message);     // 广播消息,观察者将会接收到消息
    }
}

  • 2)定义观察者:
package com.pattern.demo02\_采用JDK的API实现;

import java.util.Observable;
import java.util.Observer;

/\*\*
 \* @author lscl
 \* @version 1.0
 \* @intro: 具体观察者
 \*/
public class UserObserver implements Observer {

    private String name;

    public UserObserver(String name) {
        this.name = name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    /\*\*
 \*
 \* @param subject: 订阅的主题
 \* @param message: 主题发送过来的消息
 \*/
    @Override
    public void update(Observable subject, Object message) {
        TVSubject tvSubject = (TVSubject) subject;

        System.out.println("【" + getName() + "】接收到来自【" + tvSubject.getName() + "】的一条消息【" + message + "】");
    }
}

  • 3)测试类:
package com.pattern.demo02\_采用JDK的API实现;

/\*\*
 \* @author lscl
 \* @version 1.0
 \* @intro:
 \*/
public class Demo01 {
    public static void main(String[] args) {
        TVSubject subject = new TVSubject("马桶台");

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值