设计模式——观察者模式

来源:互联网 发布:h5小游戏源码 编辑:程序博客网 时间:2024/06/11 11:35
观察者模式说明:定义了一种一对多的依赖关系,让多个观察者对象同时监听某一主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使他们能够自动更新自己。
观察者模式还是比较好理解的,举个猫捉老鼠的例子,一群老鼠在找食物,那么这群老鼠都是观察者,当猫来了的时候,所有的老鼠应该都会受到惊吓,然后做出相应的反应。
以下是观察者模式的简单模版:

//主题,抽象通知者,一般由一个抽象类或者接口 abstract class Subject { private IList<Observer> observers = new List<Observer>(); //增加观察者 public void Attach(Observer obs) { observers.Add(obs); } //移除观察者 public void Detach(Observer obs) { observers.Remove(obs); } //通知 public void Notify() { foreach (Observer item in observers) { item.Update(); } } }

//具体通知者 class ConcreteSubject : Subject { private string subjectState; //具体被观察者状态 public string SubjectState { get { return subjectState; } set { subjectState = value; } } }

//抽象观察者,为所有的具体观察者定义一个接口,用于更新自己 abstract class Observer { public abstract void Update(); }

//具体观察者 class ConcreteObserver : Observer { private string name; private string observerState; private ConcreteSubject subject;//观察的对象 public ConcreteSubject Subject { get { return subject; } set { subject = value; } } public ConcreteObserver(ConcreteSubject subject, string name) { this.subject = subject; this.name = name; } //观察者做出回应 public override void Update() { observerState = subject.SubjectState; Console.WriteLine("观察者 {0} 的新状态是 {1}", name, observerState); } }

//主程序代码

public class MainProgram { public void Main() { ConcreteSubject s = new ConcreteSubject();//首先创建主题对象 s.Attach(new ConcreteObserver(s, "1"));//添加观察者 s.Attach(new ConcreteObserver(s, "2")); s.Attach(new ConcreteObserver(s, "3")); s.SubjectState = "逃跑"; s.Notify(); //通知 Console.ReadKey(); } }

顾名思义,当一个对象的改变需要同时改变其他对象的时候,而且不知道具体有多少对象有待改变时,应该考虑使用观察者模式。观察者模式所做的工作其实就是在接触耦合,让耦合的双方都依赖于抽象,而不是依赖于具体。
以上简单模版有一个不足,就是所有的观察者对象都需要继承同一个抽象,当继承较多时,维护会比较麻烦。而C#中有一种更简单的实现机制,那就是事件委托的实现。委托就是一种引用方法的类型,一旦为委托分配了方法,委托将于该方法具有完全相同的行为。委托可以看作是对函数的抽象,是函数的“类”,委托的实例将代表一个具体的函数。一个委托可以搭载多个方法,所有方法被依次唤起。以下是通过事件委托来实现观察者模式的代码:

//具体观察者 class ConcreteObserver { private string name; private string observerState; private ConcreteSubject subject; public ConcreteSubject Subject { get { return subject; } set { subject = value; } } public ConcreteObserver(ConcreteSubject subject, string name) { this.subject = subject; this.name = name; } public void Update() { observerState = subject.SubjectState; Console.WriteLine("观察者 {0} 的新状态是 {1}", name, observerState); } }

//通知者接口 interface class Subject { //通知 void Notify(); }

//具体通知者 class ConcreteSubject : Subject {

public delegate void EventHandler();//声明委托,无参数和返回值

public event EventHandler Update;//创建一个委托事件变量

private string subjectState; //具体被观察者状态 public string SubjectState { get { return subjectState; } set { subjectState = value; } }

public void Notify(){

Update();//直接调用委托变量

}

}

//客户端代码

public class MainProgram
{
public void Main()
{
ConcreteSubject s = new ConcreteSubject();//首先创建主题对象
ConcreteObserver obs1 = new ConcreteObserver("1");//添加观察者

s.Update += new ConcreteSubject.EventHandler(obs1.Update);//添加通知事件

ConcreteObserver obs2 = new ConcreteObserver("2");

s.Update += new ConcreteSubject.EventHandler(obs2.Update);
ConcreteObserver obs3 = new ConcreteObserver("3");

s.Update += new ConcreteSubject.EventHandler(obs3.Update);

s.Notify(); //通知

Console.ReadKey();
}
}

委托对象所搭载的所有方法必须具有相同的原形和形式,也就是拥有相同的参数列表和返回值类型。
原创粉丝点击