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

    概述

    在设计一款软件时,我们经常需要这样的功能,当某个状态发生变化,其它控件也相应的更具这个状态调整自己的属性,我们需要为这些对象建立一种“通知依赖关系”。如果依赖关系过于的紧密,那么当代码修改时,不能抵御变化,会牵涉到大量的修改。使用面向对象技术,可以使依赖关系弱化,形成稳定的依赖关系。从而实现软件体系结构的松耦合。

    定义

    GOF 给观察者模式是这么定义的:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

    结构图

    生活中的例子

    观察者定义了对象间一对多的关系,当一个对象的状态变化时,所有依赖它的对象都得到通知并且自动地更新。现在又拿经典案例热水器烧水作为例子。现在假设热水器由三部分组成:热水器、警报器、显示器。报警器和显示器告诉热水器,对温度感兴趣。然后热水器烧水时,当温度达到一定值后,就通知报警器和显示器,报警器鸣叫,显示器显示警告信息。 类似这样的例子是很多的,GOF对它进行了抽象,称为Observer设计模式。

    Observer模式分析

    下面通过一个例子来说明Obversor模式。监控家里的花园,如果有贼进来,就将拍照,并发送短信到主人手机。

    实现方法(本人对C#熟悉,故这里只用C#来实现Observer模式):

    Cam.cs

      oberservers用来存放所有的观察者,通过方法Add和Remove来添加和删除观察者。

      warning和picture用来模拟警告信息和贼的照片。

      update方法将会依次调用观察者自己的SendData方法,并将本实例的warning和picture的值传递过去。

    1 using System;
    2  using System.Collections.Generic;
    3  using System.Linq;
    4  using System.Text;
    5
    6  namespace uml
    7 {
    8 public abstract class Cam
    9 {
    10 private List<IObserver> observers = new List<IObserver>();
    11      
    12 private String warning;
    13
    14 private String picture;
    15
    16 public Cam(String warning, String picture)
    17 {
    18 this.warning = warning;
    19
    20 this.picture = picture;
    21 }
    22
    23 public void Update()
    24 {
    25 foreach (IObserver o in observers)
    26 {
    27 o.SendData(this);
    28 }
    29 }
    30
    31 public void AddObserver(IObserver observer)
    32 {
    33 observers.Add(observer);
    34 }
    35
    36 public void RemoveObserver(IObserver observer)
    37 {
    38 observers.Remove(observer);
    39 }
    40
    41 public String Warning
    42 {
    43 get { return warning; }
    44 set { warning = value; }
    45 }
    46
    47 public String Picture
    48 {
    49 get { return picture; }
    50 set { picture = value; }
    51 }
    52 }
    53 }

    MyCam.cs

    1 using System;
    2  using System.Collections.Generic;
    3  using System.Linq;
    4  using System.Text;
    5
    6  namespace uml
    7 {
    8 public class MyCam : Cam
    9 {
    10 public MyCam(String warning, String picture)
    11 : base(warning, picture)
    12 { }
    13 }
    14 }

    IObserver.cs

      将Observer抽象出来,可以避免Cam对具体哪个观察者的依赖。Cam类中只对Iobserver依赖。

    1 using System;
    2  using System.Collections.Generic;
    3  using System.Linq;
    4  using System.Text;
    5
    6  namespace uml
    7 {
    8 public interface IObserver
    9 {
    10 void SendData(Cam cam);
    11 }
    12 }

    Host.cs

      观察者具体实例。其中有两个字段。_name是主人的名字。SendData方法用来显示具体的警告信息和贼的照片。

    1 using System;
    2  using System.Collections.Generic;
    3 using System.Linq;
    4 using System.Text;
    5
    6 namespace uml
    7 {
    8 public class Host : IObserver
    9 {
    10 private string _name;
    11
    12 public Host(string name)
    13 {
    14 this._name = name;
    15 }
    16
    17 public void SendData(Cam cam)
    18 {
    19 Console.WriteLine("Host:{0},Notified{1},Picture: {2}",
    20 _name, cam.Warning,cam.Picture);
    21 }
    22 }
    23 }

    HostMobile.cs

      观察者实例。实现IOberver接口。这样,可以让Cam类不直接和观察者具体实例发生联系。避免依赖紧密。

    1 using System;
    2 using System.Collections.Generic;
    3 using System.Linq;
    4 using System.Text;
    5
    6 namespace uml
    7 {
    8 public class HostMobile : IObserver
    9 {
    10 private string _name;
    11
    12 public HostMobile(string name)
    13 {
    14 this._name = name;
    15 }
    16
    17 public void SendData(Cam cam)
    18 {
    19 Console.WriteLine("MSG:Host:{0},Notified{1},Picture:{2}",
    20 _name,cam.Warning,cam.Picture);
    21 }
    22 }
    23 }

    客户端程序代码如下:

    1 class Program
    2 {
    3 static void Main(string[] args)
    4 {
    5 Cam mc = new MyCam("Thief!!Be Careful!!","He is so ugly!!");
    6
    7 mc.AddObserver(new Host("Husband"));
    8
    9 mc.AddObserver(new HostMobile("Husband"));
    10
    11 mc.Update();
    12
    13 Console.ReadLine();
    14 }
    15 }

    运行结果如下:

    Host:Husband,Notified Thief!!Be Careful!!,Picture: He is so ugly!!

    MSG:Host:Husband,Notified Thief!!Be Careful!!,Picture: He is so ugly!!

    分析:

    静态uml图:

    在Cam类中,observers用来存放所有的观察者,IOberser充当了观察者的角色,而Cam则扮演了主题对象角色,在任何时候,只要调用了CamUpdate()方法,它就会通知它的所有观察者对象。同时可以看到,通过Observer模式,取消了直接依赖,变为间接依赖,这样大大提供了系统的可维护性和可扩展性。

    在生活中,我们的摄像头不可能只有一个,所以在这里对Cam进行了抽象,这样,Host和HostMobile都不依赖于具体的某个Camera,然后也可以看到,MyCam也不依赖于具体的具体的Host,而是依赖于IOberser。

    总结

    观察者模式所做的工作其实就是解除耦合,让耦合的双方都依赖于抽象,从而使得各自的变化不会影响到另一边。

    附:对UML与设计模式课程的意见和建议

    1)部分学生不热爱学习,对课程不感兴趣,或者不知到怎么学习这么课程。老师可以在这么课还没开始上的时候,给我们一个详细的学习规划,如何学习好这么课程。

    2)课堂气氛还不够活跃,希望老师可以采取各种方法活跃课堂气氛。

    参考文献

    .net设计模式19 观察者模式(Observer Pattern)http://www.cnblogs.com/terrylee/archive/2006/10/23/observer_pattern.html

    大话设计模式  清华大学出版社 程杰

    徐佳良

    2011.6.7

  • 相关阅读:
    Kafka Tuning Recommendations
    ​Installing the Ranger Kafka Plug-in
    Problem of Creating Topics in Kafka with Kerberos
    Step by Step Recipe for Securing Kafka with Kerberos
    ERROR:"org.apache.zookeeper.KeeperException$NoAuthException: KeeperErrorCode = NoAuth for /config/topics/test" when creating or deleting Kafka operations authorized through the Ranger policies
    Scala操作Hbase空指针异常java.lang.NullPointerException处理
    使用ranger对kafka进行鉴权
    IBM developer:Setting up the Kafka plugin for Ranger
    IBM developer:Kafka ACLs
    Exception in thread "main" org.I0Itec.zkclient.exception.ZkAuthFailedException: Authentication failure is thrown while creating kafka topic
  • 原文地址:https://www.cnblogs.com/danye/p/2074629.html
Copyright © 2011-2022 走看看