Motivation:
在软件构建过程中,我们需要为某些对象建立一种“通知依赖关系”————一个对象(目标对象)的状态发生改变,所有的依赖对象(观察这对象)都将得到通知。如果这样的依赖关系过于紧密,将是软件不能很好的抵御变化。
使用面向对象技术,可以将这种依赖关系弱化,并形成一种稳定的依赖关系。从而实现软件体系结构的松耦合。
Intent:
定义对象间的一种一对多的依赖关系,以便当一个对象的状态发生变化,所有依赖于它的对象都得到通知并自动更新。
Code:
1.不使用设计模式编程。
//不使用设计模式编程 //AMT取钱并且通过终端通知用户账户信息。 //每出现一个新的终端就需要在BankAccount类中添加一个新的终端类型字段并调用其方法。 public class ATM { BankAccount bankAccount; void Process(int data) { bankAccount.Withdraw(data); } } public class BankAccount { Email emailer;//Strong Dependence Mobile mobile;//Strong Dependence string userEmail; string userPhoneNumber; public void Withdraw(int data) { emailer.SendEmail(userEmail); mobile.SendNotification(userPhoneNumber); } } public class Email { public void SendEmail(string userEmail) { //...Todo } } public class Mobile { public void SendNotification(string userPhoneNumber) { //...Todo } }
2.观察者模式
//******************************************* //观察者模式 //按照依赖倒置原则 //观察者抽象成一个interface基类,主题抽象成一个abstract基类,abstract主题基类依赖interface观察者基类,不依赖于具体的观察类。 public class UserAccountArgs//用户参数:email,phone等terminal信息。 { private string userEmail; public string UserEmail { get { return userEmail; } set { userEmail = value; } } private string userPhoneNumber; public string UserPhoneNumber { get { return userPhoneNumber; } set { userPhoneNumber = value; } } } public abstract class Subject { private IList<IObserver> observerList = new List<IObserver>(); public void Attach(IObserver observer) { observerList.Add(observer); } public void Detach(IObserver observer) { observerList.Remove(observer); } public virtual void Notify(UserAccountArgs args) { foreach (IObserver observer in observerList) { observer.Update(args); } } } public class BankAccount : Subject { public void Withdraw(int data) { UserAccountArgs args = new UserAccountArgs(); Notify(args); } } interface IObserver { public abstract void Update(UserAccountArgs args); } public class Emailer : IObserver { public override void Update(UserAccountArgs args) { string userEmail = args.UserEmail; //... } } public class Mobile : IObserver { public override void Update(UserAccountArgs args) { string userPhoneNumber=args.UserPhoneNumber; //... } } public class ATM { UserAccountArgs args = new UserAccountArgs(); Subject bankAccount = new BankAccount(); IObserver emailer = new Emailer(); IObserver mobile = new Emailer(); void Process() { bankAccount.Attach(emailer); bankAccount.Attach(mobile); bankAccount.Notify(args); } }
3.事件模式
//*************************** //事件模式 //委托AccountEventHandler方法来实现观察者的方法,主题类不需要依赖IObject类,也不需要知道观察者的方法名。 public class Emailer { public void SendEmail(UserAccountArgs args) { string userEmail = args.UserEmail; //... } } public class Mobile { public void SendMessage(UserAccountArgs args) { string userPhoneNumber = args.UserPhoneNumber; //... } } public interface Subject { void Notify(UserAccountArgs args); } public delegate void AccountEventHandler(UserAccountArgs args); public class BankAccount : Subject { public event AccountEventHandler Update; public void Notify(UserAccountArgs args) { Update(args); } } public class ATM { UserAccountArgs args = new UserAccountArgs(); BankAccount bankAccount = new BankAccount(); Emailer emailer = new Emailer(); Mobile mobile = new Mobile(); void Process() { bankAccount.Update += new AccountEventHandler(emailer.SendEmail); bankAccount.Update += new AccountEventHandler(mobile.SendMessage); bankAccount.Notify(args); } } public class UserAccountArgs//用户参数:email,phone等terminal信息。 { private string userEmail; public string UserEmail { get { return userEmail; } set { userEmail = value; } } private string userPhoneNumber; public string UserPhoneNumber { get { return userPhoneNumber; } set { userPhoneNumber = value; } } }
Main Point:
使用面向对象的抽象,Observer模式使得我们可以独立地改变目标与观察者,从而使二者之间的依赖关系达到松耦合。
目标发送通知时,无需指定观察者,通知(可以携带通知信息作为参数)会自动传播。观察者自己决定是否需要订阅通知,目标对象对此一无所知。
在C#的event中,委托充当了抽象的Observer接口,而提供事件的对象充当了目标对象。委托是比抽象Observer接口更为松耦合的设计。
时间: 2024-10-11 22:32:26