zoukankan      html  css  js  c++  java
  • 观察者模式


    1.观察者模式是什么

    1.百度百科

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

    2.维基百科

    The observer pattern is a software design pattern in which an object, called the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state changes, usually by calling one of their methods.

    3.自己的理解

    观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时,会通知所有观察者对象,让它们能够自动更新自己。在简单点说一个管理者类当发现变化时候通知所有依赖于管理类的观察对象。

    4.核心角色

    抽象观察者管理角色:把所有对观察者对象的引用保存在一个集合中,每个抽象主题角色都可以有任意数量的观察者。抽象主题提供一个接口,可以增加和删除观察者角色。一般用一个抽象类和接口来实现。

    抽象观察者角色:为所有具体的观察者定义一个接口,在得到主题的通知时更新自己。

    具体观察者管理角色:在具体主题内部状态改变时,给所有登记过的观察者发出通知。具体主题角色通常用一个子类实现。

    具体观察者角色:该角色实现抽象观察者角色所要求的更新接口,以便使本身的状态与观察者管理的状态相协调。通常用一个子类实现。如果需要,具体观察者角色可以保存一个指向具体观察者管理角色的引用。

    2.观察者模式解决了什么问题

    1. 解除耦合 观察者模式在被观察者和观察者之间建立一个抽象的耦合。被观察者角色所知道的只是一个具体观察者列表,每一个具体观察者都符合一个抽象观察者的接口。被观察者并不认识任何一个具体观察者,它只知道它们都有一个共同的接口。

    2. 灵活抽象 由于被观察者和观察者没有紧密地耦合在一起,因此它们可以属于不同的抽象化层次。如果被观察者和观察者都被扔到一起,那么这个对象必然跨越抽象化和具体化层次。

    3. 广播发布 观察者模式支持广播通讯。被观察者会向所有的登记过的观察者发出通知,

    3.观察者模式用法

    下面我就用代码来说明观察者模式
    抽象观察者角色

    /**
     * 抽象观察者
     * @author yanlong
     *
     */
    public interface Observer {
    	//接收被观察对象的通知方法
    	void update(String str);
    }
    

    抽象观察者管理角色

    /**
     * 被观察者
     * @author yanlong
     *
     */
    public interface Observable {
    	//添加观察者
    	void addObserver(Observer observer);
    	//移除观察者
    	void removeObserver(Observer observer);
    	//通知观察者
    	void notifybserver(String str);
    }
    

    观察者实现

    //一号
    public class FirstObserver implements Observer {
    
    	@Override
    	public void update(String str) {
    		System.out.println("一号观察则收到消息:"+str);
    	}
    
    }
    //二号
    public class SecondObserver implements Observer {
    
    	@Override
    	public void update(String str) {
    		System.out.println("二号观察者收到消息:"+str);
    	}
    
    }
    
    

    观察者管理角色实现

    public class SubjectObervable implements Observable {
    
    	private List<Observer> list = new ArrayList<Observer>();
    
    	@Override
    	public void addObserver(Observer observer) {
    		list.add(observer);
    	}
    
    	@Override
    	public void removeObserver(Observer observer) {
    		list.remove(observer);
    	}
    	//循环通知所有观察者
    	@Override
    	public void notifybserver(String str) {
    		for(Observer o:list) {
    			o.update(str);
    		}
    	}
    
    }
    
    

    调用客户端
    只需要调用观察者管理的通知方法即可通知所有观察者。观察者可以动态变化。

    public class Customer {
    
    	public static void main(String[] args) {
    		Observer firstObserver = new FirstObserver();
    		Observer secondObserver = new SecondObserver();
    		Observable SubjectObervable = new SubjectObervable();
    		SubjectObervable.addObserver(firstObserver);
    		SubjectObervable.addObserver(secondObserver);
    		SubjectObervable.notifybserver("今天下午开会");
    		System.out.println("-----------------分割线-----------------");
    		SubjectObervable.removeObserver(firstObserver);
    		SubjectObervable.notifybserver("明天早上开会");
    	}
    }
    
    

    实现结果:

    一号观察则收到消息:今天下午开会
    二号观察者收到消息:今天下午开会
    -----------------分割线-----------------
    二号观察者收到消息:明天早上开会
    

    4.观察者模式的问题

    1. 调用时间增加 如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。

    2. 循环调用,内存溢出 如果在被观察者之间有循环依赖的话,被观察者会触发它们之间进行循环调用,导致系统崩溃。在使用观察者模式是要特别注意这一点。

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

    4. 无法得知变化原因 虽然观察者模式可以随时使观察者知道所观察的对象发生了变化,但是观察者模式没有相应的机制使观察者知道所观察的对象是怎么发生变化的。

    5.观察者模式总结

    观察则模式是现在代码中和现实中都广泛应用的模式之一。比如现在比较火爆的直播,所谓的关注主播就是观察者模式,你向直播系统发送一个关注该主播的请求相当于上面代码中向该主播关注列表中插入一个观察者(addObserver),当主播开始播放时系统调用(notifybserver)通知所有用户。然而主播并不知道到底谁关注了她。
    观察流程:

    1. 实现观察者接口
    2. 将自己放入观察管理者的监视列表中
    3. 等待管理者调用通知方法。
    4. 完成通知

    学好观察者模式就能理解很多当前it架构中的很多设计方案,模式不难但是很有用。

    引用

    《观察者模式详解》
    《观察者模式及Java实现例子》
    《观察者模式的优点和缺点》

  • 相关阅读:
    大数据开发速查表
    静态图像介绍
    get请求如何传递数组参数
    Redis 6.0 新增功能
    JVM 出现 StackOverflowError和OutOfMemoryError的可能
    golang超级mapper包
    dotnet vs java vs go
    [翻译]Jupyter notebook .NET Core 内核预览1
    .NET Core到底有多强?
    .net core 运行时事件(Runtime Events)
  • 原文地址:https://www.cnblogs.com/yanlong300/p/8358646.html
Copyright © 2011-2022 走看看