#观察这模式(Observer Pattern)

观察模式是一种行为模式,定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

观察者模式包含以下四个角色:

  • 抽象目标类:所有具体目标的父类,约束目标类应实现的接口。
  • 具体目标类:实现具体的功能,并在某个事件发生时通知所有观察自己的观察者。
  • 观察者类:观察者的抽象基类,约束观察者类应实现的接口。
  • 具体观察者类:继承自观察者类,实现具体功能。

举例说明,在游戏中,当主角击败BOSS时(即BOSS死亡事件发生),通知 动画管理类播放胜利动画,音效管理类播放胜利音乐。
在这个例子中,存在具体目标类BOSS,具体观察者类动画管理类音效管理类。代码设计如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
using System;
using System.Collections.Generic;

namespace ObserverPattern
{
//抽象目标类
abstract class Subject
{
//目标类的观察类列表
protected List<Observer> obsLists = new List<Observer>();
//抽象注册方法
public abstract void AddObs(Observer obs);
//抽象移除方法
public abstract void RemoveObs(Observer obs);
//抽象通知方法
public abstract void Notify();
}
//抽象观察者类
abstract class Observer
{
public abstract void Update();
}
//boss类
class BOSS : Subject
{
public override void AddObs(Observer obs)
{
obsLists.Add(obs);
}
public override void RemoveObs(Observer obs)
{
obsLists.Remove(obs);
}
public override void Notify()
{
Console.WriteLine("BOSS死亡!");
foreach(Observer obs in obsLists)
{
obs.Update();
}
}
}
class AnimatorManager : Observer
{
public override void Update()
{
Console.WriteLine("我是胜利动画!");
}
}
class AudioManager : Observer
{
public override void Update()
{
Console.WriteLine("我是胜利音乐!");
}
}

class Program
{
static void Main(string[] args)
{
Subject sub = new BOSS();
Observer obs1 = new AnimatorManager();
Observer obs2 = new AudioManager();
//注册事件
sub.AddObs(obs1);
sub.AddObs(obs2);
//BOSS死亡
sub.Notify();
/**
* 输出:
* BOSS死亡!
* 我是胜利动画!
* 我是胜利音乐!
* */
Console.ReadKey();
}
}
}

模式分析:

  • 优点:
    1. 观察者模式在只是在观察者和观察者之间建立一个抽象的耦合,因此对业务的逻辑进行了解耦。
    2. 使用观察者模式建立一套触发机制,支持广播通讯,被观察者会向所有的登记过的观察者发出通知。
  • 缺点:
    1. 如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
    2. 如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。
    3. 观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。

使用场景:

  • 一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。
  • 一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。
  • 一个对象必须通知其他对象,而并不知道这些对象是谁。
  • 需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制。

 评论