zoukankan      html  css  js  c++  java
  • Java设计模式—观察者模式(Observer pattern)

       观察者模式在软件编程中用的较多,我不善于表达我就用在网上看到的故事,和生活的例子说下基本思想 

    故事:

       小雪是一个非常漂亮的女孩,漂亮的女孩总是有很多的追求者,而且追求者的队伍在不断的变动,随时有人进入这个队伍,也有人退出。男孩们追求女孩时总是表现出120%的关心,当小雪私自游玩时总是不断收到追求者询问小雪位置变动的消息,小雪也不胜其烦,但小雪是如此的一个善良的女孩,她总是打断自己正常的生活回复男孩们的消息。而男孩们由于要不断的关心小雪的位置变化也弄的精疲力竭,而且还影响正常的工作。在这样一个简单的故事场景中我们发现了什么?来看看小雪和男孩们的烦恼:
      1.男孩们必须不断的询问小雪的位置变化,从而打断正常的工作; 
      2.小雪也要不断的接受男孩们的询问,有的时候小雪的位置并没有发生变化,还是要不断的回复男孩们的询问,也影响正常的工作。

      3.如果给各个男孩们回复问题的方式都不尽相同,小雪还要知道不同的回复方式,而且不断的有新的男孩们增加进来,还不知道未来有什么新的回复方式。

        看到这么多烦恼,我们创意无限的Nokia公司给小雪和男孩们提出了解决方案:
        Nokia公司荣誉出品了一款带有GPRS功能的手机,该手机保存着一个订阅位置变化短信通知的电话列表,当该手机检测到位置发生变化就会向这个订阅列表里的所有手机发送短信。看到Nokia这个解决方案,男孩们和小雪都应该松一口气,他们各自都可以按照自己正常的生活习惯,只有状态发生变化时候各自才会进行通信

     

       观察者模式还可以用生活中一个例子来表达,就是从邮局订杂志。假如有一个叫 妮妮 的女孩在A邮局订了《时尚女孩》的杂志,又在B邮局订了《知音》杂志,并且告诉这两家邮局,如果杂志到了就给我打电话我自己来拿,然后邮局就在系统中注册下这个女孩姓名,电话等信息。妮妮剩下的就是等邮局的电话来取杂志了。如果杂志到了,邮局打电话给妮妮说,您的杂志到了,请到某某邮局来取(这相当于程序中把对象的引用——邮局名,传给观察者),如果只说您的杂志到了,请到邮局来取,妮妮怎么知道去哪个邮局拿杂志呀。

    下面的程序模仿上面的情形,一个随机数产生对象和两个观察者,这两个观察者都在随机数产生对象那里注册了,意思说如果你产生了新的数字,就通知我一声。 

    结构图: 

    类说明
     名称  功能说明
     Observer  表示观察者的接口,要成为观察者必须实现此接口才行
     NumberGenerator  表示产生数值的抽象类
     RandomNumberGenerator  产生随机数的类,继承于NumberGenerator
     NumberObserver  数字观察者,会打印出变化的数字
     SymbolObserver  符号观察者,打印N 个符号,打印多少个符号,由接受到的数值确定

     

    1.Observer

    package com.pattern.observer;

    public interface Observer {
    public abstract void update(NumberGenerator generator);
    }

    2.NumberGenerator

    package com.pattern.observer;

    import java.util.ArrayList;
    import java.util.Iterator;

    /**
    * @project JavaPattern
    *
    @author sunnylocus
    * @verson 1.0.0
    * @date Aug 27, 2008 1:35:34 PM
    * @description 产生数值的抽象类
    */
    public abstract class NumberGenerator {
    private ArrayList observers = new ArrayList(); //存储Observer
    /** 添加观察者*/
    public void addObserver(Observer observer) {
    observers.add(observer);
    }
    /** 删除观察者*/
    public void delObserver(Observer observer) {
    observers.remove(observer);
    }
    /** 通知所有观察者*/
    public void notifyObservers() {
    Iterator it
    = observers.iterator();
    while(it.hasNext()) {
    Observer o
    =(Observer) it.next();
    o.update(
    this);//this相当于上面提到的邮局名
    }
    }
    public abstract int getNumber();//获取数字
    public abstract void generate();//产生数字
    }

    3.RandomNumberGenerator

    package com.pattern.observer;

    import java.util.Random;

    /**
    * @project JavaPattern
    *
    @author sunnylocus
    * @verson 1.0.0
    * @date Aug 27, 2008 1:48:03 PM
    * @description 用于产生随机数及通知观察者的类
    */
    public class RandomNumberGenerator extends NumberGenerator{
    private Random random = new Random();//随机数产生器
    private int number; //用于存放数字

    public void generate() {
    for(int i=0 ; i < 5; i++) {
    number
    = random.nextInt(10);//产生10以内的随机数
    notifyObservers(); //有新产生的数字,通知所有注册的观察者
    }
    }
    /** 获得数字*/
    public int getNumber() {
    return number;
    }

    }
     

    4.NumberObserver

    package com.pattern.observer;

    /** 以数字表示观察者的类*/
    public class NumberObserver implements Observer{
    public void update(NumberGenerator generator) {
    System.out.println(
    "NumberObserver:"+ generator.getNumber());
    try {
    Thread.sleep(
    1000 * 3); //为了能清楚的看到输出,休眠3秒钟。
    }catch(InterruptedException e) {
    e.printStackTrace();
    }
    }

    }

    5.SymbolObserver

    package com.pattern.observer;

    /** 以符号表示观察者的类*/
    public class SymbolObserver implements Observer{
    public void update(NumberGenerator generator) {
    System.out.print(
    "SymbolObserver:");
    int count = generator.getNumber();

    for(int i = 0 ; i < count; i ++) {
    System.out.print(
    "*^_^* ");
    }
    System.out.println(
    "");
    try {
    Thread.sleep(
    1000 * 3);
    }
    catch(InterruptedException e){
    e.printStackTrace();
    }
    }
    }
    6.Main(测试类)
    package com.pattern.observer;

    public class Main {
    public static void main(String[] args) {
    //实例化数字产生对象
    NumberGenerator generator = new RandomNumberGenerator();
    //实例化观察者
    Observer observer1 = new NumberObserver();
    Observer observer2
    = new SymbolObserver();
    //注册观察者
    generator.addObserver(observer1);
    generator.addObserver(observer2);

    generator.generate();
    //产生数字
    }
    }

    7.测试结果

    设计思想:

         观察者模式定义了对象之间的一对多的依赖关系,当一个对象的状态发生改变时,所有它的依赖对象将被自动通知并更新

    python:http://blog.csdn.net/sunyonggao/archive/2009/03/08/3970299.aspx

    from:http://sunnylocus.javaeye.com/blog/233212 

  • 相关阅读:
    深入Android 【一】 —— 序及开篇
    Android中ContentProvider和ContentResolver使用入门
    深入Android 【六】 —— 界面构造
    The service cannot be activated because it does not support ASP.NET compatibility. ASP.NET compatibility is enabled for this application. Turn off ASP.NET compatibility mode in the web.config or add the AspNetCompatibilityRequirements attribute to the ser
    Dynamic Business代码片段总结
    对文件的BuildAction以content,resource两种方式的读取
    paraview 3.12.0 windows下编译成功 小记
    百度网盘PanDownload使用Aria2满速下载
    netdata的安装与使用
    用PS给证件照排版教程
  • 原文地址:https://www.cnblogs.com/dkblog/p/1997800.html
Copyright © 2011-2022 走看看