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)        {
        }    }

  • 添加到短语集
     
    • 没有此单词集: -> ...
       
    • 创建新的单词集...
  • 拷贝
原文地址:https://www.cnblogs.com/sy-liu/p/13224115.html