设计模式
组件模式之"Observer"(观察者模式)
未经授权,禁止转载!创作不易,尊重原创!~~
背景
在软件构建过程中, 我们需要为某些对象建立一种“通知依赖关系”–一个对象(目标对象)的状态发生改变, 所有的依赖对象(观察者对象)都将得到通知,如果这样的依赖过于紧密,将使软件不能很好的抵御变化。
使用面向对象技术,可以将这种依赖关系弱化,并形成一种稳定的依赖关系。从而实现软件体系结构的松耦合。
定义
定义对象间的一种一对多(变化)的依赖关系,以便当一个对象(Subject)的状态发生改变时,所有依赖于它的对象都得到通知并自动更新。
case
王者荣耀游戏在新赛季通常会更新一次,需要用户重新下载安装包(class DownloadPkg)并进行安装。由于下载的安装包通常都比较大,因此下载界面的下方通过都会有一个进度条用来显示下载的进度,供召唤师们参考。“显示进度条”可以抽象成一个独立的功能,不仅在下载的过程中可以用,也可以在其他的场景下使用,例如“解压缩安装包”, 甚至打怪升级的游戏,在对战模式下怪物的血量(class HeroHP),本质上也是一个进度条(class ProgressBar)。
进度条可以进行各种花里胡哨的改进升级,但我们不希望每次升级进度条操作后, 还要对DownloadPkg, HeroHP这些类里的进度条功能跟着修改,这样维护的成本就太高了(上层调用的类千千万,一个个维护,累死个人)。我们希望修改完ProgressBar这个类后,自动通知到所有依赖它的类中,这样维护的成本就大大降低了。这就是观察者模式,
代码实现。
#include<iostream>
class ProgressBar {
public:
void showProgress(int cur_num, int total_num) {
std::cout << "current progrss is: " << 100 * (cur_num*1.0 /total_num) << "% ." << std::endl;
}
};
class DownloadPkg {
public:
void download() {
int total_num = 10;
for (int i = 0; i < total_num; i++) {
// fake download
// show download progress
progress_bar_.showProgress(i, total_num);
}
}
private:
ProgressBar progress_bar_;
};
// main.cc
#include<iostream>
#include "progress_bar.h"
int main() {
DownloadPkg pb;
pb.download();
return 0;
}
//方案2
class DownloadPkg {
public:
void download() {
int total_num = 10;
for (int i = 0; i <= total_num; i++) {
// fake download
// show download progress
for (Progress* p : progress_vec_) {
p->doProgress(i, total_num);
}
}
}
..
void add_progress(Progress* p) {
progress_vec_.push_back(p);
}
void remove_progress() {
if (!progress_vec_.empty()) {
progress_vec_.pop_back();
}
}
private:
std::vector<Progress*> progress_vec_ ;
};
class HeroHP {
public:
void showHP() {
int total_num = 10;
for (int i = total_num; i > 0; i--) {
// show download progress
for (Progress* p : progress_vec_) {
p->doProgress(i, total_num);
}
}
}
void add_progress(Progress* p) {
progress_vec_.push_back(p);
}
void remove_progress() {
if (!progress_vec_.empty()) {
progress_vec_.pop_back();
}
}
private:
std::vector<Progress*> progress_vec_ ;
..
};
// main.cc
#include<iostream>
#include "progress_bar.h"
int main() {
DownloadPkg d_pkg;
ProgressPercent p_percent;
ProgressBar p_bar;
d_pkg.add_progress(&p_percent);
d_pkg.add_progress(&p_bar);
d_pkg.download();
HeroHP h_hp;
h_hp.add_progress(&p_percent);
h_hp.showHP();
return 0;
}