在软件构建过程中,我们需要为某些对象建立一种“通知依赖关系” ——一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知。如果这样的依赖关系过于紧密,将使软件不能很好地抵御变化。使用面向对象技术,可以将这种依赖关系弱化,并形成一种稳定的依赖关系。从而实现软件体系结构的松耦合。
定义:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新
生活场景: 假设有个超女,有很多粉丝追求她,每次开发布会,说:“姐来了,快出来给我投票啊!我要发行新专辑了,要签名的都过来啊”;结果,一群粉丝都蜂拥而上,找她签名,满足追星的愿望。这样就形成了:超女——粉丝,关注和被关注的关系,在软件方面可以归为:观察者模式
终极目标:实现 召开招聘会就发消息给粉丝们。
第一种思路:我这水平的人的普遍想法

{
static void Main(string[] args)
{
Girl qqGril=new Girl();
Boy haha1 = new Boy("haha", qqGril);
qqGril.Addboys(haha1);
qqGril.SetMsg = "我要开发布会啦,想找我签名的快死过来!";
qqGril.SendMsg();
Console.ReadLine();
}
}
class Girl
{
List<Boy> boyLs = new List<Boy>();//泛型集合 装载 粉丝门
public void Addboys(Boy sx)
{//添加一个粉丝
boyLs.Add(sx);
}
public void Removeboys(Boy sx)
{//看这家伙不爽 ,删除掉
boyLs.Remove(sx);
}
public void SendMsg()
{//开发布会给粉丝们发消息
foreach (Boy b in boyLs)
{
b.ShowMsg();
}
}
/// <summary>
/// 设置发送信息
/// </summary>
private string _SetMsg;
public string SetMsg
{
get { return _SetMsg; }
set { _SetMsg = value; }
}
}
class Boy
{
private string name;
private Girl girl;
public Boy(string name, Girl girl)
{
this.name = name;
this.girl = girl;
}
public void ShowMsg()
{
Console.WriteLine("美女发消息给:{0},{1}", name, girl.SetMsg);
}
}
运行结果
这样写不好的地方是耦合度太高,如果要发消息给电视台 还要在增加一个电视台的类,这样就需要提取重构

{
static void Main(string[] args)
{
Girl qqGril=new Girl();
Boy haha1 = new Boy("haha", qqGril);
CCTV cctv = new CCTV("电视台", qqGril);
qqGril.Addboys(haha1);
qqGril.Addboys(cctv);
qqGril.SetMsg = "我要开发布会啦";
qqGril.SendMsg();
Console.ReadLine();
}
}
class Girl
{
List<Observer> boyLs = new List<Observer>();//泛型集合 装载 粉丝门
public void Addboys(Observer sx)
{//添加一个粉丝
boyLs.Add(sx);
}
public void Removeboys(Observer sx)
{//看这家伙不爽 ,删除掉
boyLs.Remove(sx);
}
public void SendMsg()
{//开发布会给粉丝们发消息
foreach (Observer b in boyLs)
{
b.ShowMsg();
}
}
/// <summary>
/// 设置发送信息
/// </summary>
private string _SetMsg;
public string SetMsg
{
get { return _SetMsg; }
set { _SetMsg = value; }
}
}
/// <summary>
/// 观察者基类
/// </summary>
abstract class Observer
{
protected string name;
protected Girl girl;
public Observer(string name, Girl girl)
{
this.name = name;
this.girl = girl;
}
public abstract void ShowMsg();//虚方法
}
class Boy:Observer
{
public Boy(string name, Girl girl)
: base(name, girl)
{ }
public override void ShowMsg()
{
Console.WriteLine("美女发消息给:{0},{1},快来要签名",name,girl.SetMsg);
}
}
class CCTV : Observer
{
public CCTV(string name, Girl girl)
: base(name, girl)
{ }
public override void ShowMsg()
{
Console.WriteLine("美女发消息:{0},快来采访", girl.SetMsg);
}
}
结果如下:
但是只完成了一半,因为 超女毕竟也会老去,也不可能一直红下去,所以我们可能又去关注其它方面,比如,房价怎么还没降啊,物价又上涨了等等,这些都可以抽象为一个接口,然后让具体的被观察者去继承这个接口:

{
static void Main(string[] args)
{
Subject qqGril = new Girl();
Boy haha1 = new Boy("haha", qqGril);
CCTV cctv = new CCTV("电视台", qqGril);
qqGril.Addboys(haha1);
qqGril.Addboys(cctv);
qqGril.SetMsg = "我要开发布会啦";
qqGril.SendMsg();
Console.ReadLine();
}
}
interface Subject
{
void Addboys(Observer sx);
void SendMsg();
string SetMsg
{
get;
set;
}
}
class Girl : Subject
{
List<Observer> boyLs = new List<Observer>();//泛型集合 装载 粉丝门
public void Addboys(Observer sx)
{//添加一个粉丝
boyLs.Add(sx);
}
public void Removeboys(Observer sx)
{//看这家伙不爽 ,删除掉
boyLs.Remove(sx);
}
public void SendMsg()
{//开发布会给粉丝们发消息
foreach (Observer b in boyLs)
{
b.ShowMsg();
}
}
/// <summary>
/// 设置发送信息
/// </summary>
private string _SetMsg;
public string SetMsg
{
get { return _SetMsg; }
set { _SetMsg = value; }
}
}
/// <summary>
/// 观察者基类
/// </summary>
abstract class Observer
{
protected string name;
protected Subject girl;
public Observer(string name, Subject girl)
{
this.name = name;
this.girl = girl;
}
public abstract void ShowMsg();//虚方法
}
class Boy:Observer
{
public Boy(string name, Subject girl)//这样的好处是:观察者观察的是 抽象的被观察着,这样就不局限在“超女”这一方面,可以是国家物价局,国家铁道部等等,只要实现了Subject接口
: base(name, girl)
{ }
public override void ShowMsg()
{
Console.WriteLine("美女发消息给:{0},{1},快来要签名",name,girl.SetMsg);
}
}
class CCTV : Observer
{
public CCTV(string name, Subject girl)
: base(name, girl)
{ }
public override void ShowMsg()
{
Console.WriteLine("美女发消息:{0},快来采访", girl.SetMsg);
}
}
观察者模式:定义了一对多的关系,让多个观察者对象同时监听某一主题对象,这个主题对象在状态发生改变的时候就会通知所有观察对象,使他们能够自动更新自己。
虽然上面的观察者和被观察者都被抽象出来,但是还有问题:抽象通知者还是依赖抽象观察者,如果没有抽象观察者这个接口,就没法完成通知任务,而且并不是每个具体的观察方法都有ShowMsg()这个方法,所以还是有不足之处
委托和事件解决方法:

{
static void Main(string[] args)
{
Girl qqGril = new Girl();
Boy haha1 = new Boy("haha", qqGril);
CCTV cctv = new CCTV("电视台", qqGril);
qqGril.SendAllMsg += new EventHander(haha1.ShowBoyMsg);
qqGril.SendAllMsg += new EventHander(cctv.ShowCCTVMsg);
qqGril.SendMsg();
Console.ReadLine();
}
}
interface Subject
{
//void Addboys(Observer sx);//抽象通知者由于不依赖抽象观察者,所以增加的方法也不要了
void SendMsg();
string SetMsg
{
get;
set;
}
}
delegate void EventHander();//声明一个无参数,无返回值的委托 EventHander
class Girl : Subject
{
//List<Observer> boyLs = new List<Observer>();
//public void Addboys(Observer sx)
//{//添加一个粉丝
// boyLs.Add(sx);
//}
//public void Removeboys(Observer sx)
//{//看这家伙不爽 ,删除掉
// boyLs.Remove(sx);
//}
//public void SendMsg()
//{//开发布会给粉丝们发消息
// foreach (Observer b in boyLs)
// {
// b.ShowMsg();
// }
//}
public event EventHander SendAllMsg;//声明一个 委托为 eventHander的事件
public void SendMsg()
{//开发布会给粉丝们发消息
if (SendAllMsg != null)
SendAllMsg();
}
/// <summary>
/// 设置发送信息
/// </summary>
private string _SetMsg;
public string SetMsg
{
get { return _SetMsg; }
set { _SetMsg = value; }
}
}
class Boy
{
protected string name;
protected Subject girl;
public Boy(string name, Subject girl)
{
this.name = name;
this.girl = girl;
}
public void ShowBoyMsg()//修改方法名称为ShowBoyMsg
{
Console.WriteLine("美女发消息给:{0},{1},快来要签名", name, girl.SetMsg);
}
}
class CCTV
{
protected string name;
protected Subject girl;
public CCTV(string name, Subject girl)
{
this.name = name;
this.girl = girl;
}
public void ShowCCTVMsg()////修改方法名称为ShowCCTVMsg
{
Console.WriteLine("美女发消息:{0},快来采访", girl.SetMsg);
}
}
这是在看完《大话设计模式》这本书后,根据里面的内容自己小结的,当然更具体的介绍还要去仔细阅读那本书,
《大话设计模式》这本书真的很不错,特别推荐。当然自己也是菜鸟,今天工作不忙就整理了,也希望能提高自己