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

  1. jdk当中嵌入了观察者模式以下是简单理解的demo
  2. 读者与作者之间 读者作为观察者 作者作为被观察者
  3. public class Reader implements Observer{
  4. private String name;
  5. public String getName() {
  6. return name;
  7. }
  8. public void setName(String name) {
  9. this.name = name;
  10. }
  11. public Reader(String name) {
  12. this.name = name;
  13. }
  14. //关注
  15. public void subscribe(String writerName){
  16. WriterManager.getInstance().getWriter( writerName ).addObserver( this );
  17. }
  18. //重写通知方法 通知观察者发生的改变
  19. @Override
  20. public void update(Observable o, Object arg) {
  21. if (o instanceof Writer) {
  22. Writer writer = (Writer) o;
  23. System.out.println("优秀的偷窥了"+writer.getName());
  24. }
  25. }
  26. }
  27. //作者 被观察类 继承Observable
  28. public class Writer extends Observable {
  29. //数据名称
  30. private String name;
  31. public String getName() {
  32. return name;
  33. }
  34. public void setName(String name) {
  35. this.name = name;
  36. }
  37. public Writer(String name) {
  38. super();
  39. this.name = name;
  40. //添加作者
  41. WriterManager.getInstance().add(this);
  42. }
  43. //作者发布新小说了,要通知所有关注自己的读者
  44. public void addNovel(String novel) {
  45. System.out.println(name + "发布了新书《" + novel + "》!");
  46. setChanged();
  47. notifyObservers();
  48. }
  49. //创建一个类用于对观察者和被观察者进行管理
  50. //管理类
  51. public class WriterManager {
  52. //被观察者列表
  53. private Map <String, Writer> writerMap = new HashMap <String, Writer>();
  54. //添加作者
  55. public void add(Writer writer) {
  56. writerMap.put( writer.getName(), writer );
  57. }
  58. //根据作者姓名获取作者
  59. public Writer getWriter(String name) {
  60. return writerMap.get( name );
  61. }
  62. //单例
  63. private WriterManager() {
  64. }
  65. //作者是单例的
  66. public static WriterManager getInstance() {
  67. return WriterManagerInstance.instance;
  68. }
  69. private static class WriterManagerInstance {
  70. private static WriterManager instance = new WriterManager();
  71. }
  72. }
  73. public class ClientMain {
  74. public static void main(String[] args) {
  75. Writer w1 = new Writer("王八蛋");
  76. Reader reader=new Reader( "张三");
  77. Reader reader1=new Reader( "李四");
  78. reader.subscribe( "王八蛋" );
  79. reader1.subscribe( "王八蛋" );
  80. //七哥和刘能还关注了王小蒙
  81. w1.addNovel( "Message" );
  82. }
  83. }
  84. -------------------------------------------------
  85. 运行结果:
  86. 王八蛋发布了新书《Message》!
  87. 优秀的偷窥了王八蛋
  88. 优秀的偷窥了王八蛋

事件驱动

  1. 1,观察者模式中观察者的响应理论上讲针对特定的被观察者是唯一的(说理论上唯一的原因是,如果你愿意,你完全可以在update方法里添加一系列的elseif去产生不同的响应,但LZ早就说过,你应该忘掉elseif),而事件驱动则不是,因为我们可以定义自己感兴趣的事情,比如刚才,我们可以监听作者发布新书,我们还可以在监听器接口中定义其它的行为。再比如tomcat中,我们可以监听servletcontextinit动作,也可以监听它的destroy动作。
  2. 2,虽然事件驱动模型更加灵活,但也是付出了系统的复杂性作为代价的,因为我们要为每一个事件源定制一个监听器以及事件,这会增加系统的负担,各位看看tomcat中有多少个监听器和事件类就知道了。
  3. 3,另外观察者模式要求被观察者继承Observable类,这就意味着如果被观察者原来有父类的话,就需要自己实现被观察者的功能,当然,这一尴尬事情,我们可以使用适配器模式弥补,但也不可避免的造成了观察者模式的局限性。事件驱动中事件源则不需要,因为事件源所维护的监听器列表是给自己定制的,所以无法去制作一个通用的父类去完成这个工作。
  4. 4,被观察者传送给观察者的信息是模糊的,比如update中第二个参数,类型是Object,这需要观察者和被观察者之间有约定才可以使用这个参数。而在事件驱动模型中,这些信息是被封装在Event当中的,可以更清楚的告诉监听器,每个信息都是代表的什么。
读者
package com.md.readerAndEvent;

public class Reader implements WriterListener {

    private String name;

    public Reader(String name) {
        super();
        this.name = name;
    }

    public String getName() {
        return name;
    }

    //读者可以关注某一位作者,关注则代表把自己加到作者的监听器列表里
    public void subscribe(String writerName) {
        WriterManager.getInstance().getWriter( writerName ).registerListener( this );
    }

    //读者可以取消关注某一位作者,取消关注则代表把自己从作者的监听器列表里注销
    public void unsubscribe(String writerName) {
        WriterManager.getInstance().getWriter( writerName ).unregisterListener( this );
    }

    @Override
    public void addNodel(WritertEvent writerEvent) {
        Writers writer = writerEvent.getWriter();
        System.out.println( name + "知道" + writer.getName() + "发布了新书《" + writer.getLastNovel() + "》,非要去看!" );
    }
}

作者
package com.md.readerAndEvent;


import java.util.HashSet;
import java.util.Set;

public class Writers {
    private String name;//作者的名称

    private String lastNovel;//记录作者最新发布的小说

    private Set <WriterListener> writerListenerList = new HashSet <WriterListener>();//作者类要包含一个自己监听器的列表

    public Writers(String name) {
        super();
        this.name = name;
        WriterManager.getInstance().add( this );
    }

    //作者发布新小说了,要通知所有关注自己的读者
    public void addNovel(String novel) {
        System.out.println( name + "发布了新书《" + novel + "》!" );
        lastNovel = novel;
        fireEvent();
    }

    //触发发布新书的事件,通知所有监听这件事的监听器
    private void fireEvent() {
        WritertEvent writerEvent = new WritertEvent( this );
        for (WriterListener writerListener : writerListenerList) {
            writerListener.addNodel( writerEvent );
        }
    }

    //提供给外部注册成为自己的监听器的方法
    public void registerListener(WriterListener writerListener) {
        writerListenerList.add( writerListener );
    }

    //提供给外部注销的方法
    public void unregisterListener(WriterListener writerListener) {
        writerListenerList.remove( writerListener );
    }

    public String getLastNovel() {
        return lastNovel;
    }

    public String getName() {
        return name;
    }
}

  //自定义监听器
  package com.md.readerAndEvent;


import java.util.EventListener;

//自定义监听器
public interface WriterListener extends EventListener {

    void addNodel(WritertEvent writerEvent);
}

//作者事件
package com.md.readerAndEvent;

import java.util.EventObject;

//作者事件
public class WritertEvent extends EventObject {

    private static final long serialVersionUID = 8546459078247503692L;

    public WritertEvent(Object source) {
        super( source );
    }


    public Writers getWriter() {
        return (Writers) super.getSource();
    }
}

  //管理类
  package com.md.readerAndEvent;

import com.md.readerAndAutor.Writer;

import java.util.HashMap;
import java.util.Map;

//管理类
public class WriterManager {


    private Map <String, Writers> writerMap = new HashMap <String, Writers>();

    //添加作者
    public void add(Writers writer) {
        writerMap.put( writer.getName(), writer );
    }

    //根据作者姓名获取作者
    public Writers getWriter(String name) {
        return writerMap.get( name );
    }

    //单例
    private WriterManager() {
    }

    //作者是单例的
    public static WriterManager getInstance() {
        return WriterManagerInstance.instance;
    }

    private static class WriterManagerInstance {
        private static WriterManager instance = new WriterManager();

    }

}

:观察者模式:发布(release)—订阅(subscibe),变化(change)—更新(update)
事件驱动模型:请求(request)—响应(response),事件发生(occur)—事件处理(handle)