场景出发

一个月高风黑的晚上,突然传来了尖锐的猫叫,宁静被彻底打破,狗开始吠了,大人醒了,婴儿哭了,小偷跑了

这个过程,如果用面向对象语言来描述,简单莫过于下:

    public class Cat
{
public void Miao()
{
Console.WriteLine("猫叫了.........."); new Dog().Wang();
new Parents().Wake();
new Baby().Cry();
new Thief().Run();
}
}
public class Dog
{
public void Wang()
{
Console.WriteLine("狗汪了..........");
}
} public class Parents
{
public void Wake()
{
Console.WriteLine("大人醒了..........");
}
} public class Baby
{
public void Cry()
{
Console.WriteLine("婴儿哭了..........");
}
} public class Thief
{
public void Run()
{
Console.WriteLine("小偷跑了..........");
}
}

Object

     class Program
{
static void Main(string[] args)
{
Cat cat = new Cat();
cat.Miao();
}
}

Main

代码分析

分析上述代码,显然违背了面向对象语言几大原则中的:

1单一职责原则:猫这个对象的内部还依赖其他对象细节,致使其本来的职责与其他对象的职责耦合在一起

2开闭原则(Open-Closed Principle,OCP):即对扩展开放,对修改关闭,很显然,如果我们要扩展,例如改变上述动作的顺序,那么我们就不得不去修改猫内部代码

上述代码问题的核心:猫这个对象很不稳定,在我们整个过程中,猫应该是独立存在,且不能够修改的

观察者模式

针对上面的问题场景,在面向对象语言中有一种适用的设计模式——观察者模式

观察者模式将上述对象分为2类:

主题(Subject):被关注的对象,当它的状态发生变化时,会触发观察者的反应,上述的猫就是一个主题,它发出猫叫这个状态变化的信号

观察者(或订阅者,Observer):即关注主题的对象,当主题的状态发生变化,它们会做出反应,上述的狗,大人,婴儿,小偷都是观察者

观察者模式采用的方式是将主题对观察者的直接依赖,转为对它们的抽象的依赖,具体代码如下:

    /// <summary>
/// 观察者的抽象
/// </summary>
public interface IObserver
{
void Action();
}

IObserver

     /// <summary>
/// 主题
/// </summary>
public class Cat
{
/// <summary>
/// 观察者集合
/// </summary>
private List<IObserver> _observerList = new List<IObserver>();
/// <summary>
/// 添加观察者
/// </summary>
/// <param name="observer"></param>
public void AddObserver(IObserver observer)
{
_observerList.Add(observer);
}
/// <summary>
/// 状态变化
/// </summary>
public void Miao()
{
Console.WriteLine("猫叫了.........."); ///后续动作
foreach (var item in _observerList)
{
item.Action();
}
}
}

Subject

     public class Dog : IObserver
{
public void Wang()
{
Console.WriteLine("狗汪了..........");
}
public void Action()
{
Wang();
}
} public class Parents : IObserver
{
public void Wake()
{
Console.WriteLine("大人醒了..........");
}
public void Action()
{
Wake();
}
} public class Baby : IObserver
{
public void Cry()
{
Console.WriteLine("婴儿哭了..........");
}
public void Action()
{
Cry();
}
} public class Thief : IObserver
{
public void Run()
{
Console.WriteLine("小偷跑了..........");
}
public void Action()
{
Run();
}
}

Observers

     class Program
{
static void Main(string[] args)
{
Cat cat = new Cat();
cat.AddObserver(new Dog());
cat.AddObserver(new Parents());
cat.AddObserver(new Baby());
cat.AddObserver(new Thief());
cat.Miao();
Console.ReadKey();
}
}

Main

通过观察者模式,主题与观察者之间的依赖被转移到了接口之上,面对新的扩展,完全不用再去修改主题,当我们需要添加新的观察者,只需要实现IObserver这个接口就可以,当我们需要修改顺序的时候,只需要在上端改变添加的顺序就可以

观察者模式的类图:

观察者模式存在的3种角色:

1主题角色(Cat):被关注的对象

2抽象观察者角色(IObserver):具体观察者角色的抽象

3具体观察者角色(Dog,Parents,Baby,Thief):关注主题的对象,在主题状态改变后,作出响应

Csharp下更优选择

相比于上述使用观察者模式解决问题,在.Net里有更加优秀的解决方案,那就是委托事件

同样是上述这个问题,使用委托事件来解决,代码如下

     public class Cat
{
public event Action MiaoEvent;
public void Miao()
{
Console.WriteLine("猫叫了.........."); MiaoEvent.Invoke();
}
}

Subject

    public class Dog
{
public void Wang()
{
Console.WriteLine("狗汪了..........");
}
} public class Parents
{
public void Wake()
{
Console.WriteLine("大人醒了..........");
}
} public class Baby
{
public void Cry()
{
Console.WriteLine("婴儿哭了..........");
}
} public class Thief
{
public void Run()
{
Console.WriteLine("小偷跑了..........");
}
}

ObjectForAction

     class Program
{
static void Main(string[] args)
{
Cat cat = new Cat();
cat.MiaoEvent += new Dog().Wang;
cat.MiaoEvent += new Parents().Wake;
cat.MiaoEvent += new Baby().Cry;
cat.MiaoEvent += new Thief().Run;
cat.Miao();
Console.ReadKey();
}
}

Main

使用观察者模式,主题内部维护的是一堆观察者的抽象对象,使用事件的方式,主题内部维护的是一张方法列表

适用场景和优劣势

当存在一对多的依赖关系,且需要监听状态变化的时候,观察者模式是一个很好的解决方案,例如:服务订阅通知,警报监控等等

优势:

1隔离了对象之间的直接依赖,降低了程序的耦合度

2增加了程序的可读性,方便了维护和扩展

3不需要熟悉观察者的细节详情,只用实现接口就可以

劣势:

1增加了程序的复杂度,设计模式的通病

2观察者模式的效率是个问题,一个后续动作出现问题,会堵塞整个过程

出自:博客园-半路独行

原文地址:https://www.cnblogs.com/banluduxing/p/9279571.html

本文出自于http://www.cnblogs.com/banluduxing 转载请注明出处。

c#设计模式之观察者模式(Observer Pattern)的更多相关文章

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

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

  2. 二十四种设计模式:观察者模式(Observer Pattern)

    观察者模式(Observer Pattern) 介绍定义对象间的一种一对多的依赖关系,以便当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动刷新. 示例有一个Message实体类,某些对象 ...

  3. [设计模式] 19 观察者模式 Observer Pattern

    在GOF的<设计模式:可复用面向对象软件的基础>一书中对观察者模式是这样说的:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新.当一个 ...

  4. 设计模式之观察者模式(Observer pattern)

    最近参加了一次面试,其中笔试题有一道编程题,在更换掉试题的描述场景后,大意如下: 上课铃声响起,学生A/B/C/D进入教室:下课铃声响起,学生A/B/C/D离开教室. 要求使用设计模式的思想完成铃与学 ...

  5. 设计模式九: 观察者模式(Observer Pattern)

    简介 观察者属于行为型模式的一种, 又叫发布-订阅模式. 如果一个对象的状态发生改变,依赖他的对象都将发生变化, 那么这种情况就适合使用观察者模式. 它包含两个术语,主题(Subject),观察者(O ...

  6. 【设计模式】观察者模式 Observer Pattern

    定义:观察者模式定义了对象之间的一对多依赖.当“主题”(Object)状态改变事,所有依赖它的“观察者”(Observer)都会受到通知并自动更新.主题支持观察者订阅和退订. 观察者模式提供了一种对象 ...

  7. 【UE4 设计模式】观察者模式 Observer Pattern

    概述 描述 定义对象间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新.观察者模式又叫做 发布-订阅(Publish/Subscribe)模式 模型-视图(M ...

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

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

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

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

随机推荐

  1. python manage.py runserver 0.0.0.0:8000

    python manage.py runserver 这种命令行,可以在服务器端输入IP:8000直接访问 在 python manage.py runserver 127.0.01:8000 在服务 ...

  2. 765. Couples Holding Hands

    ▶ n 对夫妻共 2n 个人随机坐成一排,“交换其中某两人的位置” 称为一次操作,求最少的操作此次数,使 n 对夫妻两人都相邻.初始座位为非负整数列 D1n-1,其中值为 2k 和 2k+1 的两个元 ...

  3. Nginx Linux yum安装

    -- 安装>yum install nginx -y -- 查看>whereis nginx >目录>/usr/sbin/nginx 执行命令>/etc/nginx 配置 ...

  4. Java路程

    Java学习这一部分其实也算是今天的重点,这一部分用来回答很多群里的朋友所问过的问题,那就是你是如何学习Java的,能不能给点建议?今天我是打算来点干货,因此咱们就不说一些学习方法和技巧了,直接来谈每 ...

  5. springmvc 类型转换器 数据回显及提示信息

    处理器的写法: 类型转换器的写法: 类型转换器在springmvc.xml中的配置如下: index.jsp的写法:

  6. Create a Basic Shader in Shader Forge

    [Create a Basic Shader in Shader Forge] 1.打开ShaderForge.Window-> Shader Forge.(打开速度较慢) 2.通过NewSha ...

  7. testng参数化(提供测试数据)

    testng提供测试数据的两个注释:@DataProvide和@Parameter   一.通过testng.xml中设置参数 (实际上testng.xml只是一个名字,可以起任何一个名字,只要是.x ...

  8. synchronized的简单理解

    synchronized能够保证在同一时刻只有一个线程执行该段代码. 使用synchronized能够防止多个线程同时并发访问程序的某些资源. synchronized既可以修饰变量,也可以修饰方法, ...

  9. codeforces:Michael and Charging Stations分析和实现

    题目大意 迈克尔接下来n天里分别需要支付C[1], C[2], ... , C[n]费用,但是每次支付费用可以选择使用优惠或不使用优惠,每次使用价值X的优惠那么迈克尔所能使用的优惠余量将减少X并且当天 ...

  10. 28. Implement strStr() (String)

    Implement strStr(). Returns the index of the first occurrence of needle in haystack, or -1 if needle ...