• 36、面向对象设计模式之观察者模式(Observer)


    观察者模式是一种行为型模式是一种发布-订阅模型

    动机(Motivation):

      在软件构建过程中,我们需要为某些对象建立一种”通知依赖关系“--一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知。如果这样的依赖关系过于紧密,将使软件不能很好地抵御变化。

      使用面向对象技术,可以将这种依赖关系弱化,并形成一种稳定的依赖关系。从而实现软件体系结构的松耦合。

    意图(Intent)

      定义对象之间的一种一对多的依赖关系,以便当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动更新。——《设计模式》GoF

    下面的代码是强依赖的,如果观察者对象更改了被观察者对象也跟着更改,这样写不可取。

    using System;
    using System.Collections.Generic;
    using System.Text;
    
    namespace 观察者模式
    {
        class BankAccount
        {
            Email email;//强依赖关系
            Mobile mobile;//强依赖关系
            public void Withdraw(int data)
            {
                email.SendEmail("userEmail");
                mobile.SendNotification("email is to");
            }
        }
      
    public class Email
    {
        public void SendEmail(string to)
        {
    
        }
    }
     class Mobile
        {
            public void SendNotification(string to)
            {
                
            }
        }
    } 

    优化方式:利用一个共同的接口所有的观察者对象都继承这个接口。代码如下:

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Text;
    
    namespace 观察者模式
    {
        public struct UserAccountArgs
        {
            public string address;
            public string mobileNumber;
        }
        public interface IAccountObserver
        {
            public void Update(UserAccountArgs args);
        }
    
        public class Email : IAccountObserver
        {
            public void Update(UserAccountArgs args)
            {
                string toAddress = args.address;
            }
        }
    
        class Mobile : IAccountObserver
        {
            public void Update(UserAccountArgs args)
            {
                string mobileNumber = args.mobileNumber;
            }
        }
        class BankAccount
        {
            //IAccountObserver emailer;//弱的依赖关系
            List<IAccountObserver> observerList = new List<IAccountObserver>();
            public void Withdraw(int data)
            {
                UserAccountArgs args = new UserAccountArgs();
                // emailer.Update(args);
                Notify(args);
            }
            //通知的方法
            public  void Notify(UserAccountArgs args)
            {
                foreach (IAccountObserver observer in observerList)
                {
                    observer.Update(args);
                }
            }
            public void AddObserver(IAccountObserver observer)
            {
                observerList.Add(observer);
            }
            public void RemoveObserver(IAccountObserver observer)
            {
                observerList.Remove(observer);
            }
        }
    }

    继续优化将目标对象中稳定的代码继续封装到一个抽象类中

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Text;
    
    namespace 观察者模式
    {
        public struct UserAccountArgs
        {
            public string address;
            public string mobileNumber;
        }
        public interface IAccountObserver
        {
            public void Update(UserAccountArgs args);
        }
        //目标对象
        public abstract class Subject
        {
            List<IAccountObserver> observerList = new List<IAccountObserver>();
            protected virtual void Notify(UserAccountArgs args)
            {
                foreach (IAccountObserver observer in observerList)
                {
                    observer.Update(args);
                }
            }
            public void AddObserver(IAccountObserver observer)
            {
                observerList.Add(observer);
            }
            public void RemoveObserver(IAccountObserver observer)
            {
                observerList.Remove(observer);
            }
        }
        public class Email : IAccountObserver
        {
            public void Update(UserAccountArgs args)
            {
                string toAddress = args.address;
            }
        }
    
        class Mobile : IAccountObserver
        {
            public void Update(UserAccountArgs args)
            {
                string mobileNumber = args.mobileNumber;
            }
        }
        class BankAccount : Subject
        {
            //IAccountObserver emailer;//弱的依赖关系
            public void Withdraw(int data)
            {
                UserAccountArgs args = new UserAccountArgs();
                // emailer.Update(args);
                Notify(args);
            }
        }
    }

    结构图如下:

     Oberver模式的几个要点:

      使用面向对象的抽象,Observer模式使得我们可以独立地改变(扩展、子类化)目标与观察者,从而使得二者之间的依赖关系达到极致松耦合。

      目标发送通知时,无需制定观察者,通知(可以携带通知信息作为参数)会自动传播。观察者自己决定是否需要订阅通知,目标对象对此一无所知。

      在c#的event中,委托充当了抽象的Observer接口,而提供事件的对象充当了目标对象。委托是比抽象Observer接口更为松耦合的设计。

      

    C# 中的委托(delete)、事件(Event)机制也是观察者模式比上面更加松耦合:

    namespace 观察者模式
    {
        public struct AccountChangeEventArgs
        {
            public string address;
            public string mobileNumber;
        }
        //目标对象
        public class Email
        {
            public void Update(AccountChangeEventArgs args)
            {
                string toAddress = args.address;
            }
        }
        public class Mobile
        {
            public void Update(AccountChangeEventArgs args)
            {
                string mobileNumber = args.mobileNumber;
            }
        }
    
        public delegate void AccountChangeEventHandler(
            AccountChangeEventArgs args);//接口
        class BankAccount 
        {
            public event AccountChangeEventHandler AccountChange;
            public void Withdraw(int data)
            {
                AccountChangeEventArgs args = new AccountChangeEventArgs();
                OnAccountChange(args);
            }
            protected virtual void OnAccountChange(AccountChangeEventArgs args)
            {
                if(AccountChange != null)
                {
                    AccountChange(args);
                }
            }
        }
        
        public class App
        {
            public void Main(string[] args)
            {
                BankAccount bankAccount = new BankAccount();
                Email email = new Email();
                bankAccount.AccountChange += new AccountChangeEventHandler(email.Update);
                bankAccount.Withdraw(123);
            }
        }
    }

     public class Email    {        public void SendEmail(string to)        {
            }    }

    • 添加到短语集
       
      • 没有此单词集: -> ...
         
      • 创建新的单词集...
    • 拷贝
  • 相关阅读:
    ObjectARX 打印常见问题
    【动态规划】数字游戏(game)
    容斥原理在错排问题中的应用
    在某宝上用python抢茅台
    【笔记】Vue ElementPlus Rule 数字验证
    分布式中间件Nginx(一)
    20192419万腾阳 汇编程序设计 前四章学习笔记
    20192419 202120222 《网络与系统攻防技术》实验一实验报告
    reset.css 和 normalize.css
    reset.css 和 normalize.css
  • 原文地址:https://www.cnblogs.com/sy-liu/p/13224115.html
Copyright © 2020-2023  润新知