• 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 设计模式》

      《设计模式》

     

  • 相关阅读:
    什么是ORM
    ORM优缺点
    Azure 中快速搭建 FTPS 服务
    连接到 Azure 上的 SQL Server 虚拟机(经典部署)
    在 Azure 虚拟机中配置 Always On 可用性组(经典)
    SQL Server 2014 虚拟机的自动备份 (Resource Manager)
    Azure 虚拟机上的 SQL Server 常见问题
    排查在 Azure 中新建 Windows 虚拟机时遇到的经典部署问题
    上传通用化 VHD 并使用它在 Azure 中创建新 VM
    排查在 Azure 中新建 Windows VM 时遇到的部署问题
  • 原文地址:https://www.cnblogs.com/liuxiaomian/p/DesignPattern_Observer.html
Copyright © 2020-2023  润新知