zoukankan      html  css  js  c++  java
  • Java设计模式

    定义

      观察者模式属于对象行为型模式。

      在对象之间定义一对多的依赖,这样一来当一个对象改变状态,依赖它的对象都会收到通知并自动更新。

    优点

      1、  主题和观察者之间抽象耦合。无论什么对象主要实现了特定的接口(如本文中的Observable),就可以成为观察者对象。

      2、  支持广播通信。就像一个播音员不需要知道谁在收听她的播音,只负责播音,而听不听就是听众的事了。这相当于给了你在任何时候都可以增加或者删除观察者的自由。

     

    适用范围

      当对象之间是一种一对多的关系时。好比有一份文件要同时分发给多个人。

    模式结构

    各个角色的作用:

      Subject(主题):目标知道它的观察者。可以有任意多个观察者观察同一个目标;提供注册和删除观察者对象的接口。

      Observer(观察者):为那些在目标发生改变时需获得通知的对象定义一个更新接口。

      ConcreteSubject(具体的主题):当它的状态发生改变时,向它的各个观察者发出通知。

      ConcreteObserver(具体观察者):实现Oberserver的更新接口以使自身状态与目标状态一致。

    UML图

        

    两种方式:

      1、(推)主题对象主动推送;

      2、(拉)主题对象通知观察者,观察者自己去获取需要的信息;

      这两种方式会在下面介绍。

     

    例子

      写一个简单的程序来说明问题:假如现在有一个广播站在播音,有许多收音机在收听。

     

      面向接口编程能够利用多态,从而降低对象之间的耦合度。

     1 package com.tony.observer;
     2 
     3 /**
     4  * 具体的主题类必须实现这个接口
     5  *
     6  */
     7 public interface Subject {
     8     
     9     //注册观察者
    10     public void register(Observable observer);
    11     //移除观察者
    12     public void remove(Observable observer);
    13     //推送消息
    14     public void update(String message);
    15     
    16 }
     1 package com.tony.observer;
     2 
     3 import java.util.ArrayList;
     4 import java.util.List;
     5 
     6 /**
     7  * 相当于ConcreteSubject,具体的主题类
     8  *
     9  */
    10 public class Radiostation implements Subject{
    11     
    12     private List<Observable> observers;
    13     
    14     public Radiostation(){
    15         observers = new ArrayList<Observable>();
    16     }
    17     
    18     public void register(Observable observer){
    19         observers.add(observer);
    20         System.out.println("have "+observers.size()+" observer are listening...");
    21     }
    22     
    23     public void remove(Observable observer){
    24         observers.remove(observer);
    25         System.out.println("a observer has gone...left "+observers.size()+" observer");
    26     }
    27     
    28     public void update(String message){
    29         for(Observable observer:observers){
    30             observer.update(message);
    31         }
    32     }
    33 }
     1 package com.tony.observer;
     2 
     3 /**
     4  * 相当于Observer,所有的观察者必须实现这个接口 
     5  *
     6  */
     7 
     8 public interface Observable {
     9     
    10     //更新数据
    11     public void update(String message);
    12     //成为主题对象的观察者,开始监听
    13     public void register();
    14     //不再监听主题对象
    15     public void remove();
    16     
    17     
    18 }
     1 package com.tony.observer;
     2 
     3 /**
     4  * 相当于ConcreteObserver,观察者对象 
     5  *
     6  */
     7 public class Radio implements Observable {
     8 
     9     private Subject subject;
    10     
    11     public Radio(Subject subject){
    12         this.subject = subject;
    13     }
    14 
    15     @Override
    16     public void update(String message) {
    17         display(message);
    18     }
    19 
    20     @Override
    21     public void register() {
    22         subject.register(this);
    23     }
    24 
    25     @Override
    26     public void remove() {
    27         subject.remove(this);
    28     }
    29     
    30     public void display(String message){
    31         System.out.println("get message from radiostation:"+message);
    32     }
    33 
    34 
    35 }
     1 package com.tony.observer;
     2 /**
     3  * 测试观察者模式 
     4  *
     5  */
     6 public class Test {
     7     public static void main(String[] args) {
     8         
     9         Subject radiostation = new Radiostation();
    10         
    11         Radio o1 = new Radio(radiostation);
    12         Radio o2 = new Radio(radiostation);
    13         
    14         //注册
    15         o1.register();
    16         o2.register();
    17         
    18         //更新消息
    19         radiostation.update("hello world");
    20         radiostation.update("over");
    21         
    22         //退出监听
    23         o1.remove();
    24         o2.remove();
    25     }
    26 }

    运行结果:

      这种实现方法属于“推”:主题主动将数据推送给观察者。其实还有另外一种叫做“拉”的方式:主题不主动将数据推送给观察者,只是给它们一个更新提示,接收的权利在观察者手上!

      与“拉”相比较,“推”有个很大的缺点:当推送的数据量很大的时候,会对程序运行性能产生影响!就像安卓手机某些后台应用:不经过你的同意自动将服务器中的一些数据下载的你的手机上。而“拉”这种方式就没有这样的情况,就好像你关注的公众号一样:给你推送消息时并没有把所有内容都推送过来,只是把一个标题发给你,想不想看在于你。

      但是”推“这种方式比较符合设计模式的原则,所以一般使用的都是这种方式。

    总结

      观察者模式应用很广,不仅在你写代码的时候用到,你在生活当中也时常能够遇到:比如走在校园里收听到的广播:广播站是主题,你就是观察者。当你进入到能够听见广播的范围时,你就成了一个观察者:播音主持说的话就是要更新的数据,通过广播站这个主题将数据发送给你们,你们负责收听。

      必须能够熟练使用。

     

      其他模式:设计模式专栏

     

    参考文献

      《Head First 设计模式》

      《设计模式》

     

  • 相关阅读:
    C#图形编程
    深入浅出话事件(上)
    .NET名称空间对应的类集
    Equals() 和运算符 == 的重写准则(C# 编程指南)
    Implement EventArgs
    CLS(公共语言规范)的CLSCompliant(跨语言调用)
    学习MSCOREE.dll是托管程序的入口点
    设计模式之原型模式代码示例
    The disk cannot be added to Cluster Shared Volumes because it does not have any suitable partitions
    RAID小结
  • 原文地址:https://www.cnblogs.com/liuxiaomian/p/DesignPattern_Observer.html
Copyright © 2011-2022 走看看