Skip to content

Commit 649f3f4

Browse files
committed
add obsever
1 parent 34558ed commit 649f3f4

File tree

10 files changed

+242
-1
lines changed

10 files changed

+242
-1
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050

5151
[备忘录模式 Memento](doc/20-备忘录.md)
5252

53-
观察者模式 Observer
53+
[观察者模式 Observer](doc/21-观察者.md)
5454

5555
状态模式 State
5656

code/20_observer/CMakeLists.txt

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
cmake_minimum_required(VERSION 3.0)
2+
PROJECT(memento_test)
3+
4+
include(CheckCXXCompilerFlag)
5+
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
6+
CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
7+
8+
# 使用变量设置编译标志
9+
if(COMPILER_SUPPORTS_CXX11)
10+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
11+
elseif(COMPILER_SUPPORTS_CXX0X)
12+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
13+
else()
14+
message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")
15+
endif()
16+
17+
18+
SET(SRC_LIST client.cpp)
19+
SET(PATTERN_SRC observer_types.cpp)
20+
21+
include_directories(./)
22+
23+
ADD_EXECUTABLE(observer_test ${SRC_LIST} ${PATTERN_SRC})

code/20_observer/client.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#include "observer_types.h"
2+
3+
int main(){
4+
Product* ihponex = new IPhoneX();
5+
Buyer* buyerA = new BuyerA();
6+
Buyer* buyerB = new BuyerB();
7+
8+
ihponex->addBuyer(buyerA);
9+
ihponex->addBuyer(buyerB);
10+
11+
ihponex->setAmount(100);
12+
return 1;
13+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#include "observer_types.h"
2+
3+
void IPhoneX::addBuyer(Buyer *buyer)
4+
{
5+
buyers.push_back(buyer);
6+
}
7+
8+
void IPhoneX::removeBuyer(Buyer *buyer)
9+
{
10+
for (vector<Buyer *>::iterator itr = buyers.begin();
11+
itr != buyers.end(); itr++)
12+
{
13+
if (*itr == buyer)
14+
{
15+
buyers.erase(itr);
16+
return;
17+
}
18+
}
19+
}
20+
21+
void IPhoneX::notifyBuyers()
22+
{
23+
for (vector<Buyer *>::iterator itr = buyers.begin();
24+
itr != buyers.end();
25+
itr++)
26+
{
27+
(*itr)->action();
28+
}
29+
}
30+
31+
void BuyerA::action()
32+
{
33+
std::cout << "A: OK I will buy it." << std::endl;
34+
}
35+
36+
void BuyerB::action()
37+
{
38+
std::cout << "B: Take another look." << std::endl;
39+
}
40+
41+
IPhoneX::~IPhoneX()
42+
{
43+
buyers.clear();
44+
}

code/20_observer/observer_types.h

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
#ifndef __OBSERVER_TYPES_H__
2+
#define __OBSERVER_TYPES_H__
3+
4+
#include <iostream>
5+
#include <string>
6+
#include <vector>
7+
using namespace std;
8+
9+
class Buyer
10+
{
11+
public:
12+
virtual ~Buyer() {}
13+
virtual void action() = 0;
14+
};
15+
16+
class Product
17+
{
18+
public:
19+
Product() : amount(0) {}
20+
virtual ~Product() {}
21+
virtual void addBuyer(Buyer *buyer) = 0;
22+
virtual void removeBuyer(Buyer *buyer) = 0;
23+
virtual void notifyBuyers() = 0;
24+
void setAmount(int amount)
25+
{
26+
this->amount = amount;
27+
if (this->amount > 0)
28+
{
29+
std::cout << "Goods arrived!" << std::endl;
30+
notifyBuyers();
31+
}
32+
}
33+
34+
protected:
35+
int amount;
36+
};
37+
38+
class IPhoneX : public Product
39+
{
40+
public:
41+
~IPhoneX();
42+
void addBuyer(Buyer *buyer);
43+
void removeBuyer(Buyer *buyer);
44+
void notifyBuyers();
45+
46+
private:
47+
vector<Buyer *> buyers;
48+
};
49+
50+
class BuyerA : public Buyer
51+
{
52+
public:
53+
void action();
54+
};
55+
56+
class BuyerB : public Buyer
57+
{
58+
public:
59+
void action();
60+
};
61+
62+
#endif // __OBSERVER_TYPES_H__

code/20_observer/result.png

4.46 KB
Loading

doc/21-观察者.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Observer
2+
3+
多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。这种模式有时又称作发布-订阅模式、模型-视图模式,它是对象行为型模式。
4+
5+
6+
## UML
7+
8+
* Subject: 抽象主题(抽象被观察者)角色,抽象主题角色把所有观察者对象保存在一个集合里,每个主题都可以有任意数量的观察者,抽象主题提供一个接口,可以增加和删除观察者对象。
9+
* ConcreteSubject:具体主题(具体被观察者)角色,该角色将有关状态存入具体观察者对象,在具体主题的内部状态发生改变时,给所有注册过的观察者发送通知。
10+
* Observer:抽象观察者角色,是观察者者的抽象类,它定义了一个更新接口,使得在得到主题更改通知时更新自己。
11+
* ConcrereObserver:具体观察者角色,实现抽象观察者定义的更新接口,以便在得到主题更改通知时更新自身的状态。
12+
13+
![figure20_observer](img/figure20_observer.png)
14+
15+
## 优缺点
16+
17+
* 优点
18+
* 降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系。符合依赖倒置原则。
19+
* 目标与观察者之间建立了一套触发机制
20+
21+
* 缺点
22+
* 目标与观察者之间的依赖关系并没有完全解除,而且有可能出现循环引用。
23+
* 当观察者对象很多时,通知的发布会花费很多时间,影响程序的效率。
24+
25+
## 使用场景
26+
* 对象间存在一对多关系,一个对象的状态发生改变会影响其他对象。
27+
* 当一个抽象模型有两个方面,其中一个方面依赖于另一方面时,可将这二者封装在独立的对象中以使它们可以各自独立地改变和复用。
28+
* 实现类似广播机制的功能,不需要知道具体收听者,只需分发广播,系统中感兴趣的对象会自动接收该广播。
29+
* 多层级嵌套使用,形成一种链式触发机制,使得事件具备跨域(跨越两种观察者类型)通知。
30+
31+
32+
33+
## 用例
34+
35+
京东商城商品到货通知, 京东app上可以在商品缺货上设置到货通知.
36+
37+
![figure20_observer_case](img/figure20_observer_case.png)
38+
39+
[code](../code/20_observer)
40+
41+
![result](../code/20_observer/result.png)

doc/img/figure20_observer.png

12.4 KB
Loading

doc/img/figure20_observer_case.png

16.7 KB
Loading

doc/uml/20_observer.pu

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
@startuml "figure20_observer"
2+
caption figure 20: Observer
3+
4+
interface Subject{
5+
+ addObserver(observer:Observer)
6+
+ removeObserver(observer:Observer)
7+
+ notifyObservers()
8+
}
9+
10+
interface Observer{
11+
+ update()
12+
}
13+
14+
class ConcreteSubject{
15+
}
16+
17+
class ConcreteObserver{
18+
19+
}
20+
21+
Subject <|-- ConcreteSubject
22+
Observer <|-- ConcreteObserver
23+
24+
Subject -right-> Observer : use
25+
@enduml
26+
27+
28+
@startuml "figure20_observer_case"
29+
caption figure 20: Observer case
30+
31+
interface Product{
32+
+ addBuyer(user:Buyer*)
33+
+ removeBuyer(user:Buyer*)
34+
+ notifyBuyers()
35+
+ setAmount(amount:int)
36+
}
37+
38+
interface Buyer{
39+
+ action()
40+
}
41+
42+
class IPhoneX{
43+
- buyers : std::List<Buyer*>
44+
- amount : int
45+
}
46+
47+
class BuyerA{}
48+
49+
class BuyerB{}
50+
51+
52+
53+
Product <|-- IPhoneX
54+
Buyer <|-- BuyerA
55+
Buyer <|-- BuyerB
56+
57+
Product -right-> Buyer : use
58+
@enduml

0 commit comments

Comments
 (0)