0%

观察者模式实现的几点收获

2020年5月18日 上午9:54

总结:

  1. 基类的设计思路:
    1. 需要先后站在两个角度:
      1. 为了用户角度:
        1. 我们作为基类,要提供给所有的所有用户基本的功能。继承类中可以添加新的功能,但是基本功能是必须保证的。
      2. 为了继承类的角度:
        1. 我们作为基类,需要为继承类提供哪些通用功能,这些功能时候所有继承类都很有可能用到的,我提供好了,你们这些基类就不用重复再写了。做到代码复用
    2. private :
      1. 我的理解来自与算法题,当我们写一道算法题的时候,我们常常需要把某个核心的子功能封装成一个private方法,这样做的原因是为了避免我们的代码写出来是一坨,让代码第一眼从结构和函数名上看上去更有逻辑,更容易让人看懂。
    3. virtual :在用户直接调用的方法中,找到哪些是可以让子类自定义的
  2. 强制转换的使用场景:
    1. 函数调用过程:
      1. GetSomeNews(string str)
      2. SetChange(string news) —— 发送者
      3. Notify(void* pArg) —— 传递者
      4. Update(void* pArg) ——— 传递者
      5. einterpret_cast<char*>(pArg) —— 接受者

附录:

main.cpp

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
#include "stdafx.h"

using namespace std;
class News : public Observerable
{
public:
virtual void GetSomeNews(string str)
{
SetChange("News: " + str);
}
};

class User1:public Observer
{
public:
virtual void Update(void* pArg)
{
cout << "User1 Got News: " << reinterpret_cast<char*>(pArg) <<endl;
}
};
class User2 :public Observer
{
public:
virtual void Update(void* pArg)
{
cout << "User2 Got News: " << reinterpret_cast<char*>(pArg) <<endl;
}
};

int main()
{
User1 u1;
User2 u2;

News n1;
n1.GetSomeNews("T0");
cout << n1.GetObseverCount() << endl; // 0

n1.Attach(&u1);
n1.Attach(&u2);
n1.GetSomeNews("T1");
cout << n1.GetObseverCount() << endl; // 2

n1.Detach(&u2);
n1.GetSomeNews("T2");
cout << n1.GetObseverCount() << endl; // 1

n1.DetachAll();
n1.GetSomeNews("T3");
cout << n1.GetObseverCount() << endl; // 0

return 0;
}

Observer.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#pragma once

# ifndef OBSEVER_H_1
# define OBSEVER_H_1
class Observer
{
public:
Observer() { ; }
virtual ~Observer() { ; }

// 当被观察对象发生变化时,通知被观察者调用这个方法
virtual void Update(void* pArg) = 0;
};
# endif

Observerable.cpp

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
#include "stdafx.h"
#include "Observerable.h"


Observerable::Observerable():_bChange(false)
{

}


Observerable::~Observerable()
{
}


// 注册观察者
void Observerable::Attach(Observer* pOb)
{
if (pOb == NULL)
{
return;
}

// 看看当前列表中是否有这个观察者
auto it = _Obs.begin();
for (; it != _Obs.end(); it++)
{
if (*it == pOb)
{
return;
}
}

_Obs.push_back(pOb);
}

// 反注册观察者
void Observerable::Detach(Observer* pOb)
{
if ((pOb == NULL) || (_Obs.empty() == true))
{
return;
}

_Obs.remove(pOb);
}

void Observerable::SetChange(string news)
{
_bChange = true;

Notify( ( (void*)news.c_str() ));
}


void Observerable::Notify(void* pArg)
{
if (_bChange == false)
{
return;
}

// 看看当前列表中是否有这个观察者
auto it = _Obs.begin();
for (; it != _Obs.end(); it++)
{
(*it)->Update(pArg);
}

_bChange = false;
}

Observerable.h

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
#pragma once

#include "Observer.h"
class Observer;

#include <string>
#include <list>
using namespace std;
class Observerable
{
public:
Observerable();
virtual ~Observerable();

// 注册观察者
void Attach(Observer* pOb);
// 反注册观察者
void Detach(Observer* pOb);

int GetObseverCount() const
{
return _Obs.size();
}

void DetachAll()
{
_Obs.clear();
}

virtual void GetSomeNews(string str)
{
SetChange(str);
}
protected:
void SetChange(string news); // 有变化,需要通知

private:
void Notify(void* pArg);

private:
bool _bChange;
list<Observer*> _Obs;
};