设计模式——观察者模式
- 设计模式分为创建型、结构型、行为型三大类。
- 创建型设计模式主要解决“对象的创建”问题
- 比较常用的有单例模式和工厂模式,相关链接如下:
- 设计模式——单例模式
- 设计模式——工厂模式
- 结构型设计模式主要解决“类或对象的组合”问题
- 比较常用的有代理模式,装饰器模式,相关链接如下:
- 设计模式——代理模式
- 设计模式——装饰器模式
- 行为型设计模式主要解决的就是“类或对象之间的交互”问题
- 比较常用的有观察者模式,策略模式,模板模式
- 设计模式——观察者模式
- 设计模式——策略模式
- 设计模式——模板模式
目录
- 模式定义和使用场景
- 模式结构
- 观察者模式优点?
- 观察者模式缺点?
- 观察者模式代码实现
1. 模式定义和使用场景
- 观察者模式也称发布订阅模式,在对象之间定义一个一对多的依赖,当一个对象状态改变的时候,所有依赖的对象都会自动收到通知。
a. 被依赖的对象叫作被观察者(Observable),依赖的对象叫作观察者(Observer) - 使用场景:比如用户注册成功后发送“欢迎注册成功”的信息,以及发送优惠券等动作,又或者游戏中队友牺牲将给所有成员进行提示等,涉及到一对一或者一对多的对象交互场景都可以使用观察者模式。
2. 模式结构
- 观察者模式包含如下角色:
a. Subject: 目标
b. ConcreteSubject: 具体目标
c. Observer: 观察者
d. ConcreteObserver: 具体观察者

3. 观察者模式优点?
- 观察者模式可以实现表示层和数据逻辑层的分离,并定义了稳定的消息更新传递机制,抽象了更新接口,使得可以有各种各样不同的表示层作为具体观察者角色。
- 观察者模式在观察目标和观察者之间建立一个抽象的耦合。
- 观察者模式支持广播通信。
- 观察者模式符合“开闭原则”的要求。
4. 观察者模式缺点?
- 如果一个观察目标对象有很多直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
- 如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。
- 观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。
5. 观察者模式代码实现
1. C++代码实现
#include <iostream>
#include <vector>
using namespace std;
class Subject;
class Observer {
public:
Observer() {}
virtual ~Observer() {}
virtual void update(Subject *sub) = 0;
};
class Subject {
public:
Subject() {}
virtual ~Subject() {}
Observer *observer;
void attach(Observer *pObserver) {
vObj.push_back(pObserver);
}
void detach(Observer *pObserver) {
for (auto it = vObj.begin(); it != vObj.end(); it++) {
if (*it == pObserver) {
vObj.erase(it);
return;
}
}
}
void notify() {
for (auto i: vObj) {
i->update(this);
}
}
virtual int getState() = 0;
virtual void setState(int i) = 0;
private:
vector<Observer *> vObj;
};
class ConcreteSubject : public Subject {
public:
ConcreteSubject() {}
virtual ~ConcreteSubject() {}
int getState() {
return state;
}
void setState(int i) {
state = i;
}
private:
int state;
};
class ConcreteObserver : public Observer {
private:
string objName;
int observerState;
public:
ConcreteObserver(string name) : objName(name) {}
virtual ~ConcreteObserver() {}
void update(Subject *sub) {
observerState = sub->getState();
cout << "update oberserver[" << objName << "] state:" << observerState << endl;
}
};
int main() {
Subject *subject = new ConcreteSubject();
Observer *objA = new ConcreteObserver("A");
Observer *objB = new ConcreteObserver("B");
subject->attach(objA);
subject->attach(objB);
subject->setState(1);
subject->notify();
cout << "--------------------" << endl;
subject->detach(objB);
subject->setState(2);
subject->notify();
delete subject;
delete objA;
delete objB;
return 0;
}
update oberserver[A] state:1
update oberserver[B] state:1
--------------------
update oberserver[A] state:2
2. Go代码实现
package main
import "fmt"
type Subject2 struct {
observers []Observer2
content string
}
func NewSubject() *Subject2 {
return &Subject2{
observers: make([]Observer2, 0),
}
}
func (s *Subject2) AddObserver(o Observer2) {
s.observers = append(s.observers, o)
}
func (s *Subject2) UpdateContext(content string) {
s.content = content
s.notify()
}
func (s *Subject2) notify() {
for _, o := range s.observers {
o.Do(s)
}
}
type Observer2 interface {
Do(*Subject2)
}
type Reader struct {
name string
}
func NewReader(name string) *Reader {
return &Reader{
name: name,
}
}
func (r *Reader) Do(s *Subject2) {
fmt.Println(r.name + " get " + s.content)
}
func ExampleObserver() {
subject := NewSubject()
boy := NewReader("小明")
girl := NewReader("小美")
subject.AddObserver(boy)
subject.AddObserver(girl)
subject.UpdateContext("hi~")
}