/*编程小技巧
1.声明和定义最好分别写在.h和.cpp文件,避免循环依赖
2.前向声明只能使用指针和引用的声明,不能初始化对象和调用方法
3.共同的方法最好集成在基类,避免代码冗余
4.代码是人看的,不要用很炫的技巧把自己坑了
5.virtual override static可以用在声明但不能用在定义
6.inline要用在定义开头,用在声明无效
7.避免转成基类截断,最好用智能指针或者boost库
8.小心类对象的重新生成,成员变量状态不一致,最好采用注入依赖而不是成员变量*/
观察者模式
定义:
定义对象之间一种一对多的依赖关系,实现莫一对象状态改变时同步通知更新依赖对象
优点:
(1)起到MVC作用将表示层与逻辑层隔离,采用消息传递扩展观察者角色
(2)观察者模式支持广播通信,实现1对多的通信机制
(3)观察目标和观察者建立抽象耦合,观察目标维护观察者集合,无需关系观察者真正动作
缺点:
(1)观察目标有很多观察者会造成每个都通知到,消耗时间
(2)存在循环依赖,耦合性高
使用范围:
存在1对多的依赖关系,并需要广播通信的系统,如MVC,群聊,委托事件等
结构:
实现一个聊天室功能,实现一人发消息触发其他人响应
实现:
namespace behavioral_pattern
{
class member;
class msg_info;
class observer_pattern
{
public:
virtual void add(std::shared_ptr<member> mem) = 0;
virtual void del(std::shared_ptr<member> mem) = 0;
virtual void notify(msg_info& msg) = 0;
};
class room_observer_pattern : public observer_pattern
{
public:
virtual void add(std::shared_ptr<member> mem) override;
virtual void del(std::shared_ptr<member> mem) override;
virtual void notify(msg_info& msg) override;
private:
std::vector<std::shared_ptr<member>>list_mem{};
};
}
namespace behavioral_pattern
{
class msg_info
{
public:
msg_info(std::string m, unsigned long i) :msg(m), id(i) {};
std::string msg{};
unsigned long id{ 0 };
};
class member
{
public:
virtual void update();
virtual void call_notify(std::shared_ptr<observer_pattern> room);
virtual int get_id() = 0;
protected:
};
class mom_member : public member
{
public:
int get_id() override;
};
class son_member : public member
{
public:
int get_id() override;
};
}
//定义代码
void behavioral_pattern::room_observer_pattern::add(std::shared_ptr<member> mem)
{
list_mem.push_back(mem) ;
}
void behavioral_pattern::room_observer_pattern::del(std::shared_ptr<member> mem)
{
for(auto itr= list_mem.begin();itr!=list_mem.end();++itr)
{
if (itr->get()->get_id() == mem->get_id())
{
list_mem.erase(itr);
break;
}
}
}
void behavioral_pattern::room_observer_pattern::notify(msg_info& msg)
{
for each(auto itr in list_mem)
{
if (itr->get_id() != msg.id)
{
itr->update();
}
}
}
void behavioral_pattern::member::update()
{
std::cout << get_id() << "__accept" << std::endl;
}
void behavioral_pattern::member::call_notify(std::shared_ptr<observer_pattern> room)
{
msg_info info("send msg", get_id());
std::cout << get_id() << "__send msg" << std::endl;
room->notify(info);
}
int behavioral_pattern::mom_member::get_id()
{
return 1;
}
int behavioral_pattern::son_member::get_id()
{
return 2;
}
测试:
基于GoogleTest 的单元测试框架;框架可参考如下网址:
https://www.cnblogs.com/jycboy/p/gtest_catalog.html
using namespace behavioral_pattern;
TEST(test_observer_pattern_add_notify, success_add_notify)
{
std::shared_ptr<observer_pattern> obs{ new room_observer_pattern() };
std::shared_ptr<member> mom{ new mom_member() };
std::shared_ptr<member> son{ new son_member() };
obs->add(mom);
obs->add(son);
son->call_notify(obs);
mom->call_notify(obs);
}
总结
(1)观察者模式是常用模式,必须掌握的
(2)重点是观察目标维持观察者集合,广播通知
(3)注意触发条件,如果是观察者相互触发需要观察者依赖观察目标。并调用观察目标的通知接口
(4)详见开头编程技巧