设计模式-观察者模式(Observer)
观察者模式是微软顶级技术大师Jeffrey Richter的作品, Observer模式是经典设计模式中应用最为广泛也最为灵活多变的模式之一.
虽然设计模式并不是万能丹,但确实是一个非常强大的工具,开发人员或架构师可使用它积极地参与任何项目。设计模式可确保通过熟知和公认的解决方案解决常见问题。模式存在的事实基础在于:大多数问题,可能已经有其他个人或开发小组解决过了。因此,模式提供了一种在开发人员和组织之间共享可使用解决方案的形式。无论这些模式的出处是什么,这些模式都利用了大家所积累的知识和经验。这可确保更快地开发正确的代码,并降低在设计或实现中出现错误的可能性。此外,设计模式在工程小组成员之间提供了通用的术语。参加过大型开发项目的人员都知道,使用一组共同的设计术语和准则对成功完成项目来说是至关重要的。最重要的是,如果能正确地使用,设计模式可以节省您大量的时间。
观察者模式(Oberver)就是一个被观察者和一个或者多个观察者组成!事件,事件委托,做事人为被观察者!监督他们运行和行动并做出自己的响应的人为观察者!通过抽象类或者接口实现观察者和被观察者的对象不会紧密连接在一起,并能更好的实现多个观察者.!就好象一个部门的运做,上司叫一个人或多个人来监督这个部门的运做!做的好的给予奖励,做的差的给予惩罚
逻辑模型
虽然Observer模式有很多变体,但该模式的基本前提包含两个角色:观察者(observer)和被观察者(subject)。在用户界面的环境中,观察者是负责向用户显示数据的对象。另一方面,被观察者表示从问题域中模拟的业务抽象。正如图1中所描述的一样,在观察者和主体之间存在逻辑关联。当主体对象中发生更改时,(例如,修改实例变量),观察者就会观察这种更改,并相应地更新其显示
观察者模式有很多形式,比较直观的一种是使用一种“注册—通知—撒销通知”的形式。下面的三个图详细的描述了这样一种过程:
1. 观察者(Observer)将自己注册到被观察对象(Subject)中,被观察对象将观察者存放在一个容器里。
2. 被观察对象发生了某种变化,从容器中得到所有注册过的观察者,将变化通知观察者。
3. 观察者告诉被观察者要撒销观察,被观察者从容器中将观察者去除。
意图
l 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新.
适用性
l 当一个抽象模型有两个方面,其中一个方面依赖于另一方面.将这二者封装在独立的对象中以使它们可以各自独立地改变和复用.
l 当对一个对象的改变需要同时改变其他对象,而不知道具体有多少对象有待改变.
l 当一个对象必须通知其他对象,而它又不能假定其他对象是谁.换言之,你不希望这些对象是紧密耦合的.
C#中的事例
一. 建立模型
using System;
namespace Obserevr
{
/// <summary>
/// Model模块,声明委托,委托类型和触发事件的方法
/// 在观察者模式中,此类为Subject(主体)和抽象基类.
/// </summary>
public abstract class Model
{
public Model()
{
//
// TODO: 在此处添加构造函数逻辑
//
}
public delegate void MyDelegate1(); //声明一个不带返回类型和参数的委托
// public delegate int MyDelegate2(int x);
public event MyDelegate1 MyDelegateEvent1; //声明委托,用于捆绑上面的所定义的委托事件
// public event MyDelegate2 MyDelegateEvent2;
/// <summary>
/// 封装了触发事件的方面
/// 为程序提供完整性,除观察者以外的所有成员都不能直接调用.
/// </summary>
protected void Notify1()
{
this.MyDelegateEvent1() ;
}
二. 建立观察者基类
using System;
namespace Obserevr
{
/// <summary>
/// 构造函数中,注册事件。
/// 在观察者模式中,此类相当与所有观察者的基类
/// 所有观察者都必须继承此类
/// </summary>
public abstract class Obserever1
{
public Obserever1(Model ChilModel) //通过传入模型对象,把观察者和模型联系起来.把观察者行为Hack注册于委托事件.
{
ChilModel.MyDelegateEvent1 +=new Obserevr.Model.MyDelegate1(hack);
}
public abstract void hack();
}
}
三. 建立具体目标
using System;
namespace Obserevr
{
/// <summary>
/// Policeman 继承Model模块,并做出自己的响应
/// 此类为观察者模式中的具体目标,其继承于模型.
/// 其中包含了在模型中被封装好的触发委托事件的方法.
/// </summary>
public class Policeman:Model
{
public Policeman()
{
}
/// <summary>
/// 定义了一种行为
/// </summary>
public void Thief()
{
Console.WriteLine ("有人报警了");
this.Notify1(); //调用委托已订阅方法
}
}
}
四. 建立具体观察者
using System;
namespace Obserevr
{
/// <summary>
/// 此类为观察者模式中的具体观察者.
/// 观察者覆盖了基类的方法,并做出自己的响应.
/// </summary>
public class Enfant:Obserever1
{
public Enfant(Model ChilModel):base(ChilModel) //继承了基类的构造函数,实现了方法的订阅
{
}
/// <summary>
/// 覆盖了基类实行自己的响应方法的具体实现
/// 已经在观察者模式的基类中注册于委托事件,由委托事件调用执行.
/// </summary>
public override void hack()
{
Console.WriteLine ("警察来了");
}
}
}
using System;
namespace Obserevr
{
/// <summary>
/// 此类为观察者模式中的具体观察者
/// 覆盖了基类的方法并做出自己的响应
/// </summary>
public class Man:Obserever1
{
/// <summary>
/// 继承了基类的构造函数,实现了方法的订阅.
/// </summary>
/// <param name="ChilModel"></param>
public Man(Model ChilModel):base(ChilModel)
{
}
/// <summary>
/// 覆盖了基类实行自己的响应方法的具体实现
/// 已经在观察者模式的基类中注册于委托事件,由委托事件调用执行.
/// </summary>
public override void hack()
{
Console.WriteLine ("贼被抓住了");
}
}
}
五. 主函数,运行测试
using System;
namespace Obserevr
{ /// <summary>
/// Observer(观察者模式)事例分析
/// 题目:有人报警了(人),贼开始逃跑了,警察来了,贼被抓住了.
/// 关于目标(发布方):
/// 在此事例中,只有一个目标对象(发布方)人,因为其他全部实体的行为都是
/// 响应它的"报警"所执行的.人是主动方,它的报警引起一系列的连锁反应.
///
/// 关于观察者(订阅方):
/// 至于此事例的中的观察者分别有两大类,一类是听到人报警后只作出一种
/// 反应的观察者(贼,警察).
public class MainTread
{
public MainTread()
{
}
public static void
{
Policeman myPM=new Policeman ();
Thief myMouse1=new Thief ("贼",myPM);
Enfant myEnfant=new Enfant (myPM);
Man Myman=new Man (myPM);
myPM.Thief();
}
}
}
浙公网安备 33010602011771号