GOF23设计模式-行为型模式9-观察者模式(Observer)

定义

观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,这个主题对象在状态发生变化时,会通知所有观察者对象,使他们能够自动更新自己。又叫做发布-订阅(Publish-Subscribe)模式。

场景

  • 聊天室程序的创建。服务器创建好后,A、B、C三个用户上来公开聊天。A向服务器发送消息,服务器端聊天数据发生改变,希望这些数据分别发给其他在线客户,也就是每个客户端都需要更新服务端的聊天数据。
  • 网站上多人订阅的“每日一笑”的新闻,当有这个主题新闻时,将消息发送给所有订阅者。
  • 大家一起玩CS游戏时,服务器需要将每个人的方位信息变化发给所有玩家。
    上面这些场景,我们都可以使用观察者模式来处理,可以将多个订阅者、客户称之为观察者;需要同步给多个观察者的数据封装到对象中,称之为目标。

核心

  • 观察者模式主要用于1:N的通知,当一个对象(目标对象Subject或Observable)的状态变化时,他需要及时告诉一系列对象(观察者对象,Observer),令他们做出响应,
  • 通知观察者的方式:

    • 每次都会把通知以广播方式发送给所有观察者,所有观察者只能被动接收。

    • 观察者只要知道有情况即可,至于什么时候获取内容,获取什么内容,都由自己决定。

结构图

在这里插入图片描述

  • Observer:抽象观察者,为所有的具体观察者定义一个接口,在得到主题的通知时,更新自己。这个接口叫做更新接口,通常包含一个update方法,这个方法叫做更新方法。
  • Subject:可叫做主题或者抽象通知者,一般由抽象类或者接口实现,它把所有对观察者对象的引用保存在一个容器中,每个主题都可以有任何数量的观察者,抽象主题可以提供增加和删除观察者的接口,还有一个广播消息的方法。
  • ConcreteObserver:具体观察者,实现Observer,有自己的状态,但是一般根据主题的状态来自动更新,与主题状态保持一致。
  • ConcreteSubject:具体主题类,有自己的状态,当状态变化时会通知所有观察者,观察者会及时更新自己的状态。

特点

  • 使用观察者模式的动机:将一个系统分割成一系列相互协作的类有一个很不好的副作用,那就是要维护相关对象之间的一致性,我们不希望为了维护一致性而使各个类之间紧密耦合,这样会给重用、维护、扩展都带来不便。而观察者模式的关键对象是主题Subject和观察者Observer,一个Subject可以有任意数量的依赖它的Observer,一旦Subject的状态发生了改变,所有Observer都可以得到通知。Subject发出通知时,并不需要知道谁是它的观察者,也就是说具体观察者是谁,它根本不需要知道,而任何一个具体观察者不知道也不需要知道其他观察者的存在。
  • 何时使用:当一个对象的改变同时需要改变其他对象时的时候,而且它不知道具体有多少对象要改变时,应该考虑使用观察者模式。
  • 观察者模式所做的事其实就是在解除耦合,让耦合的双方都依赖与抽象,而不依赖与具体,从而使得各自的变化都不会直接的影响到另一边的改动。

模拟实现

  1. 观察者接口Observer
/**
 * User:tumbler
 * Desc:观察者模式--观察者接口,包含一个update更新方法来同步主题状态
 */
public interface Observer {
    void update(Subject subject);
}
  1. 主题对象类Subject
/**
 * User:tumbler
 * Desc:观察者模式--主题类,定义所有观察者容器,注册和删除观察者方法,消息广播方法
 */
public class Subject {

    protected List<Observer> list = new ArrayList<>();

    public void registerObserver(Observer observer) {
        list.add(observer);
    }

    public void removeObserver(Observer observer) {
        list.remove(observer);
    }

    /**
     * 通知所有观察者更新状态
     */
    public void notifyAllObserver(){
        for (Observer observer : list) {
            observer.update(this);
        }
    }
}
  1. 具体主题对象ConcreteSubject
/**
 * User:tumbler
 * Desc:观察者模式--具体主题类
 */
public class ConcreteSubject extends Subject {
    private int state;

    public int getState() {
        return state;
    }

    /**
     * 主题对象状态发生变化时,通知所有观察者
     * @param state
     */
    public void setState(int state) {
        this.state = state;
        this.notifyAllObserver();
    }
}
  1. 定义具体观察者ObserverA、ObserverB
/**
 * User:tumbler
 * Desc:观察者模式--具体观察者
 */
public class ObserverA implements Observer {
    private int myState;

    public int getMyState() {
        return myState;
    }

    public void setMyState(int myState) {
        this.myState = myState;
    }

    @Override
    public void update(Subject subject) {
        myState = ((ConcreteSubject)subject).getState();
    }
}

/**
 * User:tumbler
 * Desc:观察者模式--具体观察者
 */
public class ObserverB implements Observer {
    private int myState;

    public int getMyState() {
        return myState;
    }

    public void setMyState(int myState) {
        this.myState = myState;
    }

    @Override
    public void update(Subject subject) {
        myState = ((ConcreteSubject)subject).getState();
    }
}
  1. 测试
/**
 * User:tumbler
 * Desc:观察者模式--测试
 */
public class Client {
    public static void main(String[] args) {
        //主题对象
        ConcreteSubject subject = new ConcreteSubject();
        //观察者对象
        ObserverA observerA = new ObserverA();
        ObserverB observerB = new ObserverB();
        //将观察者对象注册到主题对象中
        subject.registerObserver(observerA);
        subject.registerObserver(observerB);
        //改变主题对象subject的状态,看观察者的状态
        System.out.println("------------改变状态");
        subject.setState(888);
        System.out.println(observerA.getMyState());  //888
        System.out.println(observerB.getMyState());  //888

        System.out.println("------------改变状态");
        subject.setState(999);
        System.out.println(observerA.getMyState());  //999
        System.out.println(observerB.getMyState());  //999
    }
}
  1. UML图
    在这里插入图片描述

使用java的Observable和Observer

javaSE提供了java.util.Observable和java.util.Observer来实现观察者模式。

  1. 定义主题对象,继承Observable类
import java.util.Observable;

/**
 * User:tumbler
 * Desc:观察者模式--主题对象
 */
public class ConcreteSubject extends Observable {
    private int state;

    /**
     * 主题对象的状态发生改变,
     * 并调用父类setChanged方法表示状态已发送改变
     * 通知观察者notifyObservers
     * @param state
     */
    public void setState(int state) {
        this.state = state;
        setChanged();
        notifyObservers(state);
    }

    public int getState() {
        return state;
    }
}
  1. 定义观察者对象,实现Observer接口
import java.util.Observable;
import java.util.Observer;

/**
 * User:tumbler
 * Desc:观察者模式--具体观察者
 */
public class ObserverA implements Observer {
    private int myState;

    public int getMyState() {
        return myState;
    }

    @Override
    public void update(Observable o, Object arg) {
        myState = ((ConcreteSubject)o).getState();
    }
}
  1. 测试
/**
 * User:tumbler
 * Desc:观察者模式--测试
 */
public class Client {
    public static void main(String[] args) {
        //定义主题对象
        ConcreteSubject subject = new ConcreteSubject();
        //定义观察者对象
        ObserverA observerA = new ObserverA();
        ObserverA observerB = new ObserverA();
        //将观察者添加到主题对象中
        subject.addObserver(observerA);
        subject.addObserver(observerB);
        //改变主题的状态,看观察者状态的改变
        subject.setState(666);
        System.out.println(observerA.getMyState()); //666
        System.out.println(observerB.getMyState()); //666
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值