观察者模式

一.模式定义

  • 观察者模式定义了对象之间一对多依赖关系,当目标对象(被观察者)的状态发生改变时,它的所有依赖者(观察者)都会收到通知。一个观察目标可以对应多个观察者,而这些观察者之间没有相互联系,所以能够根据需要增加和删除观察者,使得系统更易于扩展,符合开闭原则;
  • 并且观察者模式让目标对象和观察者松耦合,虽然彼此不清楚对方的细节,但依然可以交互,目标对象只知道一个具体的观察者列表,但并不认识任何一个具体的观察者,它只知道他们都有一个共同的接口。
  • 模式理解:被观察者(目标对象)通过关联(集合方式)方式储存观察者,即一个观察者可以被多个观察者观察,观察者可以了解到目标对象的状态变化,但是这种变化不会影响目标自身的架构。

模式动机

建立一种对象与对象之间的关联关系,一个对象发生改变时将自动通知其他对象,其他对象做出相应反应。

发生改变的对象称为观察目标,而被通知的对象成为观察者,一个观察目标可以对应多个观察者。

二.模式结构

 Subject:抽象主题(被观察者/目标对象),每一个主题可以有多个观察者,并将所有观察者对象的引用保存在一个集合里,被观察者提供一个接口,可以增加和删除观察者角色

ConcreteSubject:具体主题(具体目标),将有关状态存入具体观察者对象,在主题发生改变时,给所有的观察者发出通知

Observer:抽象观察者,为所有的具体观察者定义一个接口,该接口的作用是在收到主题的通知时能够及时的更新自己

ConcreteObserver:具体观察者,实现抽象观察者角色定义的接口,以便使本身的状态与主题状态相协调。如果需要,具体观察者角色可以保存一个指向具体主题角色的引用。

模式实例

  • 假设猫是老鼠和狗的观察目标,老鼠和狗是观察者,猫叫老鼠跑,狗也跟着叫,使用观察者模式描述该过程。

抽象目标类 MySubject

MySubject是抽象目标类,在其中定义了一个ArrayList类型的集合observers,用于存储观察者对象,并定义了注册方法attach()和注销方法detach() ,同时声明了抽象的通知方法 cry()。需要注意的是attach()方法和detach()方法都必须针对抽象观察者进行编程,任何抽象观察者的子类对象都可以注册或注销。

package observer.test1;
 
import java.util.ArrayList;
 

public abstract class MySubject {
 
    protected ArrayList observers =new ArrayList();
 
    //注册方法
    public void attach(MyObserver observer){
        observers.add(observer);
    }
 
    //注销方法
    public void detach(MyObserver observer){
        observers.remove(observer);
    }
 
    public abstract void cry(); //抽象通知方法
 
}

抽象观察者类 MyObserver

抽象观察者MyObserver定义为一个接口,在其中声明了抽象响应方法response()

package observer.test1;
 

public interface MyObserver {
    void response(); //抽象响应方法
}

具体目标类 Cat(猫类)

Cat是目标类MySubject 的子类,它实现了抽象方法 cry() ,在cry()中遍历了观察者集合,调用每一个观察者对象的response()响应方法

package observer.test1;
 
 
public class Cat extends MySubject {
    @Override
    public void cry() {
        System.out.println("猫叫!");
        System.out.println("-----------------------------------------");
 
        //通过for遍历集合并且调用方法
        for (Object obs:observers){
            ((MyObserver)obs).response();
        }
    }
}

具体观察者类 Mouse(老鼠类)

Mouse是具体观察者类,它实现了在抽象观察者中定义的响应方法response()

package observer.test1;
 

public class Mouse implements MyObserver {
    @Override
    public void response() {
        System.out.println("老鼠努力逃跑!");
    }
}

具体观察者类 Dog(狗类)

Dog也是具体观察者类,它实现了在抽象观察者中定义的响应方法response()

package observer.test1;
 

public class Dog implements MyObserver {
    @Override
    public void response() {
        System.out.println("狗跟着叫!");
    }
}

三.应用场景

  • 当有一个目标对象改变的同时需要其他对象也要一起改变。
  • 类似一条触发链
  • 关联行为场景
  • 事件多级触发场景
  • 跨系统的消息变换场景,如消息队列的处理机制。

注意事项

  • 避免循环引用
  • 如果顺序执行,某一观察者错误会导致系统卡壳,一般采用异步方式。
  • 当一个对象的改变需要同时改变其它对象,并且它不知道具体有多少对象有待改变的时候,应该考虑使用观察者模式。
  • 将一个系统分割成一系列相互协作的类有一个很不好的副作用,就是需要维护相关对象间的一致性。为了维持一致性而使各类紧密耦合,这样会给维护、扩展和重用都带来不便,而观察者模式所做的工作就是在解除耦合。
     
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值