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

    1 定义

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

    2 解决问题

      一系统中有一些相互协作的类。副作用是,需要维护相关对象间的一致性。我们不希望为了维持一致性而使各类紧密耦合,这样会给维护、扩展和重用都带来不便。观察者就是用来解决这类的耦合关系的。

    3 模式类图

     

    4 观察者模式代码

    /// <summary>
        /// 抽象主题类
        /// </summary>
        public abstract class Subject
        {
            private IList<Observer> observers = new List<Observer>();
    
            /// <summary>
            /// 增加观察者
            /// </summary>
            /// <param name="observer"></param>
            public void Attach(Observer observer)
            {
                observers.Add(observer);
            }
    
            /// <summary>
            /// 移除观察者
            /// </summary>
            /// <param name="observer"></param>
            public void Detach(Observer observer)
            {
                observers.Remove(observer);
            }
    
            /// <summary>
            /// 向观察者(们)发出通知
            /// </summary>
            public void Notify()
            {
                foreach (Observer o in observers)
                {
                    o.Update();
                }
            }
        }
    
        /// <summary>
        /// 抽象观察者类,为所有具体观察者定义一个接口,在得到通知时更新自己
        /// </summary>
        public abstract class Observer
        {
            public abstract void Update();
        }
    
        /// <summary>
        /// 具体观察者或具体通知者,将有关状态存入具体观察者对象;在具体主题的内部状态改变时,给所有登记过的观察者发出通知。具体主题角色通常用一个具体子类实现。
        /// </summary>
        public class ConcreteSubject : Subject
        {
            private string subjectState;
    
            /// <summary>
            /// 具体观察者的状态
            /// </summary>
            public string SubjectState
            {
                get { return subjectState; }
                set { subjectState = value; }
            }
        }
    
        /// <summary>
        /// 具体观察者,实现抽象观察者角色所要求的更新接口,已是本身状态与主题状态相协调
        /// </summary>
        public class ConcreteObserver : Observer
        {
            private string observerState;
            private string name;
            private ConcreteSubject subject;
    
            /// <summary>
            /// 具体观察者用一个具体主题来实现
            /// </summary>
            public ConcreteSubject Subject
            {
                get { return subject; }
                set { subject = value; }
            }
    
            public ConcreteObserver(ConcreteSubject subject, string name)
            {
                this.subject = subject;
                this.name = name;
            }
    
            /// <summary>
            /// 实现抽象观察者中的更新操作
            /// </summary>
            public override void Update()
            {
                observerState = subject.SubjectState;
                Console.WriteLine("The observer's state of {0} is {1}", name, observerState);
            }
        }
    
    class Program
        {
            static void Main(string[] args)
            {
                // 具体主题角色通常用具体自来来实现
                ConcreteSubject subject = new ConcreteSubject();
    
                subject.Attach(new ConcreteObserver(subject, "Observer A"));
                subject.Attach(new ConcreteObserver(subject, "Observer B"));
                subject.Attach(new ConcreteObserver(subject, "Observer C"));
    
                subject.SubjectState = "Ready";
                subject.Notify();
    
                Console.Read();
            }
        }

    5. 模式总结

      5.1 优点

        5.1.1 观察者模式解除了主题和具体观察者的耦合,让耦合的双方都依赖于抽象,而不是依赖具体。从而使得各自的变化都不会影响另一边的变化。

      5.2 缺点

        5.2.1 依赖关系并未完全解除,抽象通知者依旧依赖抽象的观察者。

      5.3 适用场景

        5.3.1 当一个对象的改变需要给变其它对象时,而且它不知道具体有多少个对象有待改变时。

        5.3.2 一个抽象某型有两个方面,当其中一个方面依赖于另一个方面,这时用观察者模式可以将这两者封装在独立的对象中使它们各自独立地改变和复用。

        

  • 相关阅读:
    取代iframe,实现页面中引入别的页面
    axios请求
    接口跨域
    es7,es8
    promise
    移动端开发调试工具神器--Weinre使用方法
    资本论第一卷笔记
    2018春季实习生校招面经(一)阿里篇
    linux小实验-考勤模拟程序
    在基于debian的deepin或者Ubuntu上双等号“==”和双中括号“[[]]”不能使用的真相
  • 原文地址:https://www.cnblogs.com/liufei1983/p/7106621.html
Copyright © 2011-2022 走看看