设计模式--观察者模式

it2024-12-05  21

定义:

定义了对象之间一对多的关系,这样一来,当一个对象发生变化时,他的所有依赖者都会收到通知,并自动更新.

关键词:

observer : 观察者

subject : 主题

concreteObserver: 具体观察者

结构图:

应用场景:

当一个对象的状态变化时,需要通知其他多个对象进行同步更新时,可以使用此模式(如果有且只有一个对象需要更新,就没有必要了)

当需要动态增加删除需要同步的对象时

对象仅仅需要将自己的更新通知其他对象,而无需知道其他对象实现细节时.

优点:

subject 和 observer是高内聚,低耦合的,他们仅通过接口进行联系

无需指定具体的observer

缺点:

松耦合导致代码之间看起来关系不明显,比较难理解.

例子:

日志记录.当发生一个事件或者有状态变化时,需要日志记录下来.要求同时有数据库记录和文件记录.该如何写的?

通常写法是:

public class Record { public void notify() { DatabaseLog d = new DatabaseLog(); d.RecordToDataBase(); FileLog f = new FileLog(); f.RecordToFile(); } } public class DatabaseLog { public void RecordToDataBase() { //TODO } } public class FileLog { public void RecordToFile() { //TODO } }

当有变化时,页面上只需要调用

Record r = new Record(); r.notify();

即可.

但是:如果要求新增一种记录方式,web记录时,该如何处理呢?

新增一个WebLog类,然后修改Record类.

public class Record { public void notify() { DatabaseLog d = new DatabaseLog(); d.RecordToDataBase(); FileLog f = new FileLog(); f.RecordToFile(); WebLog w = new WebLog(); w.RecordToWeb(); } } public class DatabaseLog { public void RecordToDataBase() { //TODO } } public class FileLog { public void RecordToFile() { //TODO } } public class WebLog { public void RecordToWeb() { //TODO } } 于是,我们发现:针对实际编程,每当有新增时,我们都需要添加新的记录类,并且修改Record类. 仔细观察三种记录方式,其实都是在对所发生的事情那个做记录,只是记录的方式不一样罢了. 类图: 代码: public interface ISubject { void RegisterObserver(IObserver observer); void RemoveObserver(IObserver observer); void NotifyObservers(); } public class Record : ISubject { private ArrayList observersList; public Record() { observersList = new ArrayList(); } public void RegisterObserver(IObserver observer) { observersList.Add(observer); } public void RemoveObserver(IObserver observer) { observersList.Remove(observer); } public void NotifyObservers() { foreach (IObserver observer in observersList) { observer.Record(); } } public void SetEvent(int el) { if (el > 10) { NotifyObservers(); } } } public interface IObserver { void Record(); } public class DatabaseLog : IObserver { private ISubject subject; public DatabaseLog(ISubject subject) { this.subject = subject; subject.RegisterObserver(this); } public void Record() { //TODO } } public class FileLog : IObserver { private ISubject subject; public FileLog(ISubject subject) { this.subject = subject; subject.RegisterObserver(this); } public void Record() { //TODO } } public class WebLog : IObserver { private ISubject subject; public WebLog(ISubject subject) { this.subject = subject; subject.RegisterObserver(this); } public void Record() { //TODO } } 页面调用: protected void Page_Load(object sender, EventArgs e) { Record r = new Record(); DatabaseLog dbl = new DatabaseLog(r); FileLog fl = new FileLog(r); WebLog wl = new WebLog(r); r.SetEvent(100); } 此时,如果需要增加其他的记录方式的话,需要添加一个类实现Iobserver,然后还需要修改客户端页面. 通过配置文件,我们还可以使客户端做到易插拔. <hr/> 以下来自<<深入浅出设计模式>>   涉及到的设计原则: 封装变化 在观察者模式中,会改变的是主题(Subject)的状态,以及观察者(Observer)的数量和具体类型. 面向接口编程 观察者和主题都使用接口,观察者使用主题的接口,主题使用观察者的接口.做到了松耦合. 优先使用对象组合,而不是继承 观察者模式利用组合讲许多观察者组合进主题,对象之间的这种关系不是通过继承得到的,而是在运行时运用动态的组合生成的.

转载于:https://www.cnblogs.com/oneword/archive/2009/04/30/1447013.html

最新回复(0)