最近在读《设计模式》这本书,细细嚼来觉得对以前见过的代码有了不同的感觉,今天对观察者模式进行一点说明,主要希望把我自己给将明白。
结构:
参与者:
Subject 目标:
目标知道它的观察者,可以有任意多个观察者观察同一个目标。
提供注册和删除观察者对象的接口。
Observer 观察者:
为那些在目标放生改变时需要获得通知的对象定义一个更新接口。
ConcreteSubject 具体目标:
将有关状态存入各ConcreteObserver对象。
当它的状态发生改变时,向它的各个观察者发出通知。
ConcreteObserver具体观察者:
维护一个指向ConcreteSubject对象的引用;
存储有关状态,这些状态应与目标的状态保持一致。
实现Observer的更新接口以使自身状态与目标的状态保持一致。
下面给出C#实现示例:
class Program
{
static void Main(string[] args)
{
ConcreteSubject subject = new ConcreteSubject();
ConcreteObserver observer = new ConcreteObserver();
subject.Attach(observer);
subject.SubjectState = "new state1";
subject.SubjectState = "new state2";
Console.ReadKey();
}
}
public delegate void MySubjectEventHandler(object sender, MyArguments e);
public class MyArguments
{
public MyArguments(string argument)
{
args = argument;
}
public string args { set; get; }
}
public interface INotifyChanged
{
event MySubjectEventHandler SubjectMemberChanged;
}
public interface ISubject : INotifyChanged
{
void Attach(IObserver observer);
void Detach(IObserver observer);
void Notify(MyArguments e);
}
public interface IObserver
{
void Update(object sender, MyArguments e);
}
public class ConcreteSubject : ISubject
{
public void Attach(IObserver observer)
{
SubjectMemberChanged += new MySubjectEventHandler(observer.Update);
}
public void Detach(IObserver observer)
{
SubjectMemberChanged -= new MySubjectEventHandler(observer.Update);
}
public void Notify(MyArguments e)
{
if(SubjectMemberChanged!=null)
SubjectMemberChanged(this, e);
}
private string sujectState;
public string SubjectState
{
get { return sujectState; }
set
{
sujectState = value;
Notify(new MyArguments("SubjectState"));
}
}
public event MySubjectEventHandler SubjectMemberChanged;
}
public class ConcreteObserver : IObserver
{
public void Update(object sender, MyArguments e)
{
Console.WriteLine("I have found the changes of [" + sender.GetType().Name + " : " + sender.GetHashCode().ToString() + "]\n" + e.args+" : "+ ((ConcreteSubject)sender).SubjectState);
}
}
基本原理就是这样,而C#中提供的事件订阅机制使实现观察者模式变得更加灵活。如下面的代码示例:
class Program
{
static void Main(string[] args)
{
Observer o = new Observer();
Publisher p = new Publisher();
p.PropertyChanged += new PropertyChangedEventHandler(o.MyActions);
p.Property = "value1";
Console.ReadKey();
}
}
public class Publisher : System.ComponentModel.INotifyPropertyChanged
{
private string _property;
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public string Property
{
set
{
_property = value;
OnPropertyChanged("Property");
}
get { return _property; }
}
public event PropertyChangedEventHandler PropertyChanged;
}
public class Observer
{
public void MyActions(object sender, PropertyChangedEventArgs e)
{
Console.WriteLine("Publisher is : "+sender.ToString()+" , Property "+ e.PropertyName+" changed ");
}
}