设计模式学习笔记十九(Observer观察者模式)

来源:互联网 发布:软件项目中标通知书 编辑:程序博客网 时间:2024/05/22 23:51

动机:在软件构建过程中,我们需要为某些对象建立一种“通知依赖关系”――一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知。如果这样的依赖关系过于紧密,将使软件不能很好地抵御变化。使用面向对象技术,可以将这种依赖关系弱化,并形成一种稳定的依赖关系。从而实现软件体结构的松耦合。

意图:定义对象间的一种一对多的依赖关系,以便当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动更新。

基本Code

/*用户在ATM上取款,系统自动给用户发邮件或手机短信*/

//用户信息

public class UserAccountArgs

{

 

    string toAddress;

    public string ToAddress

    {

        get { return toAddress; }

        set { toAddress = value; }

    }

    string mobileNumber;

    public string MobileNumber

    {

        get { return mobileNumber; }

        set { mobileNumber = value; }

    }

}

//观察者接口

public interface IAccountObserver

{

    void Update(UserAccountArgs args);

}

 

//邮件通知

public class Emailer:IAccountObserver

{

    public void Update(UserAccountArgs args)

    {

        //...

        string toAddress = args.ToAddress;

    }

}

 

//手机通知

public class Mobile:IAccountObserver

{

    public void Update(UserAccountArgs args)

    {

        //...

        string mobileNumber = args.MobileNumber;

    }

}

 

//进一步抽象

public abstract class Subject

{

    List<IAccountObserver> list = new List<IAccountObserver>();  //同时更新多个

    public virtual void Notify(UserAccountArgs args)

    {

        foreach (IAccountObserver observer in list)

        {

            observer.Update(args);

        }

    }

 

    public void AddObserver(IAccountObserver observer)

    {

        list.Add(observer);

    }

    public void RemoveObserver(IAccountObserver observer)

    {

        list.Remove(observer);

    }

}

 

//银行帐户

public class BankAccount:Subject

{  

  

    public void WithDraw(int data)

    {

        //...

        UserAccountArgs args = new UserAccountArgs();

        //...

        Notify(args);      

      

    }

  

}

 

//ATM实体

 

public class ATM

{

    public static void Main()

    {

        BankAccount bankAccount = new BankAccount();

        Emailer emailer = new Emailer();

        Mobile mobile = new Mobile();

        bankAccount.AddObserver(emailer);

        bankAccount.AddObserver(mobile);

        bankAccount.WithDraw(1234);

    }

}

Observer结构图如下:

 

Observer模式要点:

1、  使用面么对象的抽象,Observer模式使得我们可以独立地改变目标与观察者,从而使二者之间的依赖关系达致松耦合。

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

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

 

使用C#中的事件来实现的Code如下:

public delegate void AccountChangeEventHandler(object sender,AccountChangeEventArgs args);

 

//用户信息

public class AccountChangeEventArgs:EventArgs

{

    string toAddress;

    public string ToAddress

    {

        get { return toAddress; }

        set { toAddress = value; }

    }

    string mobileNumber;

    public string MobileNumber

    {

        get { return mobileNumber; }

        set { mobileNumber = value; }

    }

}

 

//邮件通知

public class Emailer

{

    public void Update(object sender, AccountChangeEventArgs args)

    {

        //...

        string toAddress = args.ToAddress;

    }

}

 

//手机通知

public class Mobile

{

    public void Update(object sender, AccountChangeEventArgs args)

    {

        //...

        string mobileNumber = args.MobileNumber;

    }

}

 

public class BankAccount

{

    public event AccountChangeEventHandler AcountChange;

    public void WithDraw(int data)

    {

        //...

        AccountChangeEventArgs args = new AccountChangeEventArgs();

        //...

        OnAccountChange(args);

 

    }

 

    protected void OnAccountChange(AccountChangeEventArgs args)

    {

        if (AcountChange != null)

        {

            AcountChange(args);

        }

    }

 

}

 

public class App

{

    public static void Main()

    {

        BankAccount bankAccount = new BankAccount();

        Emailer emailer = new Emailer();

        Mobile mobile = new Mobile();

        bankAccount.AcountChange+=new AccountChangeEventHandler(emailer.Update);

        bankAccount.AcountChange+=new AccountChangeEventHandler(mobile.Update);

        bankAccount.WithDraw(1234);

    }

}

 
原创粉丝点击