观察者模式是经常使用到的一种设计模式,在我们的生活中也经常遇到,小到学校上学让同学帮忙看着老师有没有过来,在教室里做一些与学习无关的事情,大到股市里面我们遇到的,到股票涨到或者跌到一定程度的时候通知我们,卖出或者买入一定的股份,貌似观察者模式是经常使用到的一种设计模式。

  下面我就用生活中的一个实例来简单的说明观察者模式怎么使用。

  小明有一天发现自己原有的手机卡资费有点贵,准备换一张资费便宜的手机卡,换手机卡好麻烦,首先应该解决的问题就是一定要通知他之前的一个班级同学,把新的手机号告诉他们,以便有事情的时候能够经常的联系,好了这个该怎么设计呢?

  首先,我们先进行分析一下这个设计的方法,小明如果要是通知自己的班级同学,首先应该是采用批量通知的方式,一个一个的通知是不是很不便利了,既然是批量通知,我们应该在通知者类中添加所有的要通知的同班同学(观察者),然后实现遍历通知,既然要使用遍历通知,那么一定要保证每个同学里面包含的通知方法应该是一样的,这样就需要抽象出来一个同学基类,这样子的分析以后就应该很清楚了,但是一定要弄明白的是,这些通知最终调用的还是同学(观察者)自身的方法,那么,作为通知者,通知的内容怎么传递过去,最简单的办法就是在其基类的构造函数中进行传递。好了,分析结束,那么我们具体应该建立哪些类呢,首先应该建立一个通知者基类、具体的通知者,另外观察者呢?也应该建立相应的观察者基类,具体的观察者。

  首先,我们来看一下具体的UML图:

  

  上图就是整个观察者模式的一个UML简图,那么,具体类的实现我们怎么实现呢?代码如下

namespace Observer
{
public interface Subject
{
void Add(Observer observer);
void Remove(Observer observer);
void Notify();
string SubjectState { set; get; }
}
}

Subject

namespace Observer
{
public class XiaoMing : Subject
{
private string changeCard;
private List<Observer> List = new List<Observer>();
public void Add(Observer observer)
{
List.Add(observer);
} public void Remove(Observer observer)
{
List.Remove(observer);
} public void Notify()
{
foreach (Observer observer in List)
{
observer.Update();
}
} public string SubjectState
{
get
{
return changeCard;
}
set
{
changeCard = value;
}
}
}
}

XiaoMing

namespace Observer
{
public abstract class Observer
{
protected string name;
protected Subject sub;
public Observer(string name, Subject sub)
{
this.name = name;
this.sub = sub;
}
public abstract void Update();
}
}

Observer

namespace Observer
{
public class BuilderContact : Observer
{
public BuilderContact(string name, Subject sub)
: base(name, sub)
{ }
public override void Update()
{
Console.WriteLine("{0},{1},伟大的社会建设者,麻烦您记一下!", this.sub.SubjectState, this.name);
}
}
}

BuilderContact

namespace Observer
{
public class TeacherContact : Observer
{
public TeacherContact(string name, Subject sub)
: base(name, sub)
{ } public override void Update()
{
Console.WriteLine("{0},{1},伟大的人民教师,麻烦您记一下!", this.sub.SubjectState, this.name);
}
}
}

TeacherContact

namespace Observer
{
class Program
{
static void Main(string[] args)
{
XiaoMing xiaoMing = new XiaoMing() { SubjectState = "我手机号换了" };
BuilderContact builder = new BuilderContact("李四", xiaoMing);
TeacherContact teacher = new TeacherContact("小红", xiaoMing);
xiaoMing.Add(builder);
xiaoMing.Add(teacher);
xiaoMing.Notify();
Console.ReadKey();
}
}
}

Main

  以上是一个简单的观察者模式的实例,但是问题来了,不管是哪个观察者执行的都是Update方法,这样的设计显然影响了程序的可读性,但是我们怎样才能是程序的可读性更强呢?又或者当小明刚办好这个手机卡,糟糕的事情发生了,欢喜之下,手机卡丢了,手机也丢了,联系方式全都没有呢,悲剧又一次在小明的身上发生了,怎么才能获取所有同学的联系方式呢,还好聪明的小明记得其中一个同学的号码,然他通知所有的同学,让同学给他发联系方式,这种方法真的是太棒了,那具体到我们的代码又该怎样的实现呢?

  具体的代码实现如下:

namespace DelegateObserver
{
public interface Subject
{
void Notify();
string SubjectState { set; get; }
}
}

Subject

namespace DelegateObserver
{
public delegate void Update();
public class XiaoMing : Subject
{
public Update Update;
private string losePhone;
public void Notify()
{
Update();
} public string SubjectState
{
get
{
return losePhone;
}
set
{
losePhone = value;
}
}
}
}

XiaoMing

namespace DelegateObserver
{
public class BuilderContact
{
private string name;
private Subject sub;
public BuilderContact(string name, Subject sub)
{
this.name = name;
this.sub = sub;
}
public void StopBuilder()
{
Console.WriteLine("{0},{1},伟大的社会建设者,请你给他发一个信息!", this.sub.SubjectState, this.name);
}
}
}

BuilderContact

namespace DelegateObserver
{
public class TeacherContact
{
private string name;
private Subject sub;
public TeacherContact(string name, Subject sub)
{
this.name = name;
this.sub = sub;
} public void StopTeach()
{
Console.WriteLine("{0},{1},伟大的人民教师,请你给他发一个信息!", this.sub.SubjectState, this.name);
}
}
}

TeacherContact

namespace DelegateObserver
{
public class XiaoWang
{
private XiaoMing xiaoMing;
public XiaoWang(string subjectState)
{
xiaoMing = new XiaoMing { SubjectState = subjectState };
TeacherContact teacher = new TeacherContact("小红", xiaoMing);
BuilderContact builder = new BuilderContact("李四", xiaoMing);
xiaoMing.Update += new Update(teacher.StopTeach);
xiaoMing.Update += new Update(builder.StopBuilder);
} public void Nofity()
{
xiaoMing.Notify();
}
}
}

XiaoWang

namespace DelegateObserver
{
class Program
{
static void Main(string[] args)
{
XiaoWang xiaoWang = new XiaoWang("小明手机丢了");
xiaoWang.Nofity();
Console.ReadKey();
}
}
}

Main

  好了,以上通过委托进行了解耦,同时可读性也增强了,在此证明了一点,在实际的使用过程中带有委托的观察者模式更加强大,总归,观察者模式的运用场景就是在一个类的改变影响到其他的类的时候使用。

  本篇文章观察者模式至此,谢谢您收看我的博客。

  

观察者模式(Observer)的更多相关文章

  1. 设计模式 - 观察者模式(Observer Pattern) 详细说明

    观察者模式(Observer Pattern) 详细说明 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26583157 版权全部 ...

  2. 设计模式 ( 十六 ) 观察者模式Observer(对象行为型)

    设计模式 ( 十六 ) 观察者模式Observer(对象行为型) 1.概述 一些面向对象的编程方式,提供了一种构建对象间复杂网络互连的能力.当对象们连接在一起时,它们就可以相互提供服务和信息. 通常来 ...

  3. 乐在其中设计模式(C#) - 观察者模式(Observer Pattern)

    原文:乐在其中设计模式(C#) - 观察者模式(Observer Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 观察者模式(Observer Pattern) 作者:weba ...

  4. 设计模式 - 观察者模式(Observer Pattern) 详细解释

    观察者模式(Observer Pattern) 详细解释 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26583157 版权全部 ...

  5. java设计模式--观察者模式(Observer)

    java设计模式--观察者模式(Observer) java设计模式--观察者模式(Observer) 观察者模式的定义: 定义对象间的一种一对多的依赖关系.当一个对象的状态发生改变时,所有依赖于它的 ...

  6. 观察者模式 Observer 发布订阅模式 源 监听 行为型 设计模式(二十三)

    观察者模式 Observer 意图 定义对象一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖他的对象都得到通知并自动更新. 别名:依赖(Dependents),发布订阅(Publish-Su ...

  7. 8.5 GOF设计模式四: 观察者模式Observer

    GOF设计模式四: 观察者模式Observer  现实中遇到的问题  当有许多不同的客户都对同一数据源感兴趣,对相同的数据有不同的处理方式,该如 何解决?5.1 定义: 观察者模式  观察者模式 ...

  8. 设计模式-观察者模式(Observer Pattern)

    观察者模式(Observer Pattern):定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象.这个主题对象在状态发生变化时,会通知所有观察者对象,使他们能够自动更新自己. 观察者 ...

  9. jQuery中的观察者模式(Observer Pattern)

    在jQuery中,on方法可以为元素绑定事件,trigger方法可以手动触发事件,围绕这2个方法,我们来体验jQuery中的观察者模式(Observer Pattern). ■ on方法绑定内置事件, ...

  10. [Android&amp;Java]浅谈设计模式-代码篇:观察者模式Observer

    观察者,就如同一个人,对非常多东西都感兴趣,就好像音乐.电子产品.Game.股票等,这些东西的变化都能引起爱好者们的注意并时刻关注他们.在代码中.我们也有这种一种方式来设计一些好玩的思想来.今天就写个 ...

随机推荐

  1. SQL Server 的事务和锁(二)-Range S-S锁

    在这篇随笔中,我们的主要关注点在 Key-Range Lock.Key-Range Lock有 S-S.S-U.I-N.X-X几种情况.我们一个一个来说,力求明白.遗憾的是,这里可能会比较冗长,那么死 ...

  2. Doing Homework 状态压缩DP

    Doing Homework 题目抽象:给出n个task的name,deadline,need.  每个任务的罚时penalty=finish-deadline;   task不可以同时做.问按怎样的 ...

  3. Android(java)学习笔记63:线程的优先级

    1. Java线程的优先级从1到10级别,值越大优先级越高线程默认优先级是5.值越大优先级越高 (1) 继承自Thread类创建线程类: package cn.itcast_04; public cl ...

  4. JavaScript中交换两个变量的值得三种做法(代码实现)

    javascript在编程时经常会涉及到如何交换两个变量的值,例如常见的冒泡排序,快速排序等:下面我讲根据自己近期所学总结几种常见的交换两个变量值的方法: 方法一:借助第三方变量交换两个变量的值 va ...

  5. Django升级1.6之后出现“Bad Request (400)”错误的解决方案

    Django从1.4升级到1.6之后发现之前的网站都无法访问了,会出现“Bad Request (400)”的错误,搜了半天终于找到了解决办法. 解决方法很简单: 在settings.py里面添加: ...

  6. asp.net在word页眉插入条形码

    条形码控件需要引用MSBCODE9.OCX组件.该组件的默认位置是C:\Program Files\Microsoft Office\Office12\2052\MSBCODE9.OCX using  ...

  7. 使用subversion搭建SVN

    使用subversion搭建SVN需要用到的软件包有subversion,apr,apr-util,sqlite,zlib,因为在编译安装subversion时需要指明apr.apr-util.sql ...

  8. 关于在windows环境下配置xampp多站点问题

    前言 由于开发要求,最近开始了php开发,于是就找到了xampp,wamp等集成环境,关于在windows下的xampp和wamp的配置,我过两天在写两篇分别阐述一下,下面就遇到的多站点的配置问题讲一 ...

  9. document.execCommand()命令小计

    2D-Position 允许通过拖曳移动绝对定位的对象. AbsolutePosition 设定元素的 position 属性为“absolute”(绝对). BackColor 设置或获取当前选中区 ...

  10. WebAPI GET和POST请求的几种方(转发)

    WebAPI GET和POST请求的几种方式 GET请求 1.无参数get请求 一般get请求有两种写法,一种是$.get()   一种是$.ajax({type:"get"}), ...