zoukankan      html  css  js  c++  java
  • 设计模式之观察者模式(Observer)(4)

    简介

            观察者模式(Observer)完美的将观察者和被观察的对象分离开。举个例子,用户界面可以作为一个观察者,业务数据是被观察者,用户界面观察业务数据的变化,发现数据变化后,就显示在界面上。面向对象设计的一个原则是:系统中的每个类将重点放在某一个功能上,而不是其他方面。一个对象只做一件事情,并且将他做好。观察者模式在模块之间划定了清晰的界限,提高了应用程序的可维护性和重用性。

    定义

            观察者模式(又被称为发布-订阅(Publish/Subscribe)模式)定义一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态变化时,会通知所有的观察者对象,使他们能够自动更新自己。

    类型

    行为型模式

    类图

    图1 类图

    结构

    最基础的观察者模式包括以下四个角色:

    • Subject:抽象主题(抽象被观察者),抽象主题角色把所有观察者对象保存在一个集合里,每个主题都可以有任意数量的观察者,抽象主题提供一个接口,可以增加和删除观察者对象。
    • ConcreteSubject:具体主题(具体被观察者),该角色将有关状态存入具体观察者对象,在具体主题的内部状态发生改变时,给所有注册过的观察者发送通知。
    • Observer:抽象观察者,是观察者者的抽象类,它定义了一个更新接口,使得在得到主题更改通知时更新自己。
    • ConcrereObserver:具体观察者,是实现抽象观察者定义的更新接口,以便在得到主题更改通知时更新自身的状态。

    使用场景

    • 关联行为场景,需要注意的是,关联行为是可拆分的,而不是“组合”关系。
    • 事件多级触发场景。
    • 跨系统的消息交换场景,如消息队列、事件总线的处理机制。

    优点

    • 观察者与被观察者之间是属于轻度的关联关系,并且是抽象耦合的,这样,对于两者来说都比较容易进行扩展。
    • 观察者模式是一种常用的触发机制,它形成一条触发链,依次对各个观察者的方法进行处理。但同时,这也算是观察者模式一个缺点,由于是链式触发,当观察者比较多的时候,性能问题是比较令人担忧的。并且,在链式结构中,比较容易出现循环引用的错误,造成系统假死。

    缺点

            在应用观察者模式时需要考虑一下开发效率和运行效率的问题,程序中包括一个被观察者、多个观察者,开发、调试等内容会比较复杂 而且在Java中消息的通知一般是顺序执行,那么一个观察者卡顿,会影响整体的执行效率,在这种情况下,一般会采用异步实现。

    模拟场景

            假设有一个软件公司,每当有新产品推出,就把信息通知到一些客户。

    实现

    C#版

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace Observer
    {
        class Program
        {
            static void Main(string[] args)
            {
                MyCompany company = new MyCompany();
                IService customerA = new Customer("Alice");
                IService customerB = new Customer("Bob");
                company.Subscribe(customerA);
                company.Subscribe(customerB);
                company.SendMsg();
                Console.ReadLine();
            }
        }
        /// <summary>
        /// 抽象观察者
        /// </summary>
        public interface IService
        {
            void Update();
        }
        /// <summary>
        /// 具体观察者
        /// </summary>
        public class Customer : IService
        {
            private string name;
            public Customer(string name)
            {
                this.name = name;
            }
            public void Update()
            {
                Console.WriteLine("客户{0}收到通知了", this.name);
            }
        }
        /// <summary>
        /// 抽象被观察者
        /// </summary>
        public interface IMyCompany
        {
            //合作
            void Subscribe(IService subscriber);
            //取消合作
            void CancelSubscribe(IService subscriber);
            //向客户发送更新消息
            void SendMsg();
        }
    
        /// <summary>
        /// 被观察者
        /// </summary>
        public class MyCompany : IMyCompany
        {
            private IList<IService> subscribers = new List<IService>();
    
            public void Subscribe(IService subscriber)
            {
                subscribers.Add(subscriber);
            }
            public void CancelSubscribe(IService subscriber)
            {
                subscribers.Remove(subscriber);
            }
            public void SendMsg()
            {
                foreach (IService service in subscribers)
                {
                    service.Update();
                }
            }
        }
    }
    View Code

    Java版

    package Observer;
    import java.util.ArrayList;
    import java.util.List;
    
    public class Program {
        /**
         * @param args
         */
        public static void main(String[] args) {
            // TODO Auto-generated method stub
             MyCompany company = new MyCompany();
          IService customerA = new Customer("Alice");
          IService customerB = new Customer("Bob");
          company.Subscribe(customerA);
          company.Subscribe(customerB);
          company.SendMsg();
        }
    }
    interface IService {
            void Update();
    }
        class Customer implements IService
        {
            private String name;
            public Customer(String name)
            {
                this.name = name;
            }
            public void Update()
            {
                System.out.println("客户"+this.name+"收到通知了");
            }
        }
        /// <summary>
        /// 抽象被观察者
        /// </summary>
         interface IMyCompany
        {
            //合作
            void Subscribe(IService subscriber);
            //取消合作
            void CancelSubscribe(IService subscriber);
            //向客户发送更新消息
            void SendMsg();
        }
    
        /// <summary>
        /// 被观察者
        /// </summary>
         class MyCompany implements IMyCompany
        {
            private List<IService> subscribers = new ArrayList<IService>();
            public void Subscribe(IService subscriber)
            {
                subscribers.add(subscriber);
            }
            public void CancelSubscribe(IService subscriber)
            {
                subscribers.remove(subscriber);
            }
            public void SendMsg()
            {
                for (IService service : subscribers)
                {
                    service.Update();
                }
            }
        }
    View Code
  • 相关阅读:
    js 面试的坑:变量提升
    meta 标签大全
    一个极为简单的requirejs实现
    AMD 的 CommonJS wrapping
    浅解析js中的对象
    javascript运动系列第二篇——变速运动
    开发汉澳即时通信网,2006年上线,QQ死期到了
    SpringMVC中的异步提交表单
    HDU 3698 DP+线段树
    黑马程序猿_反射、内省、泛型
  • 原文地址:https://www.cnblogs.com/CIreland/p/9385987.html
Copyright © 2011-2022 走看看