设为首页 加入收藏

TOP

从观察者模式的实现,看c/c++的语言特性(一)
2015-07-20 17:49:02 来源: 作者: 【 】 浏览:8
Tags:观察者 模式 实现 c/c 语言 特性

观察者模式,是我们在开发过程中经常会遇到或者使用的设计模式。

比较常见的,我们在GUI库里便能看到其身影,譬如:键盘敲击事件后,需要将这一事件通知到所有观测键盘事件的对象。但凡涉及到这种一对多的通知,基本上都是观察者模式的应用。

?

?

我们经常使用的开发库中经常会存在这种模式,但是实现方式却不尽相同。所以,了解c/c++语言下观察者模式的实现方式,对于我们学习和掌握各种开源库将非常有帮助。一旦了解到该模式的存在,对整个代码会更增加一层了解和信心。

?

下面,我以我所知道的几种方式来分别实现一个非常简单的观察者模式,以示语言特性和该模式的一些特征。

假设,Subject会接受整数A和B,同时该Subject绑定了若干个Observer,在接受到整数A和B之后,需要及时通知所有Observer(例子里作为观察者的Adder和Muler皆简单输出A和B的和以及乘积)

?

先看c风格的代码实现:

?

#include 
  
   

// c style
int Add(int iA, int iB)
{
	printf(Add(%d,%d)=%d
, iA, iB, iA + iB);
	return iA + iB;
}
int Mul(int iA, int iB)
{
	printf(Mul(%d,%d)=%d
, iA, iB, iA * iB);
	return iA * iB;
}
typedef int (*fpCallBack)(int iA, int iB);

int main()
{
	fpCallBack fpcb[2] = {&::Add, &::Mul};
	fpcb[0](1, 2);
	fpcb[1](1, 2);
        return 0;}

  

?

这种方式间接明了,一路了然。c的风格就是这样的,不同的人写一小段代码,可能都大同小异。

?

#include 
  
   
#include 
   
     // cpp style1 struct IObserver1 { virtual int OnAB(int iA, int iB)=0; }; struct Subject1 { void AddObserver(IObserver1*pObserver) { m_vecObserver.push_back(pObserver); } void Notify(int iA, int iB) { for (unsigned i = 0; i < m_vecObserver.size(); ++i) { m_vecObserver[i]->OnAB(iA, iB); } } std::vector
    
      m_vecObserver; }; struct Adder1 : public IObserver1 { virtual int OnAB(int iA, int iB) { printf(Add1(%d,%d)=%d , iA, iB, iA + iB); return iA + iB; } }; struct Muler1 : public IObserver1 { virtual int OnAB(int iA, int iB) { printf(Mul1(%d,%d)=%d , iA, iB, iA * iB); return iA * iB; } }; int main() { Subject1 subj1; Adder1 adder1; Muler1 muler1; subj1.AddObserver(&adder1); subj1.AddObserver(&muler1); subj1.Notify(1, 2); return 0; }
    
   
  
这个也是比较显而易见的方式,定义一个虚基类,各个观察者必须继承并实现该接口,以方便管理并及时收到通知。这种方式的可读性比较好,但是耦合性比较大。

?

?

再看一个c++实现的方式:

?

#include 
  
   
#include 
   
     // cpp style2 struct IObserver2 { }; typedef int (IObserver2::*Ofp)(int iA, int iB); struct Subject2 { void AddObserver(IObserver2*pObj, Ofp fp) { m_vecpObj.push_back(pObj); m_vecOfp.push_back(fp); } void Notify(int iA, int iB) { for (unsigned i = 0; i < m_vecpObj.size(); ++i) { (((IObserver2*)m_vecpObj[i])->*m_vecOfp[i])(iA, iB); } } std::vector
    
      m_vecpObj; std::vector
     
       m_vecOfp; }; struct Adder2 : public IObserver2 { int OnAB(int iA, int iB) { printf(Add2(%d,%d)=%d , iA, iB, iA + iB); return iA + iB; } }; struct Muler2 : public IObserver2 { int OnAB(int iA, int iB) { printf(Mul2(%d,%d)=%d , iA, iB, iA * iB); return iA * iB; } }; int main() { Subject2 subj2; Adder2 adder2; Muler2 muler2; subj2.AddObserver(&adder2, (Ofp)&Adder2::OnAB); subj2.AddObserver(&muler2, (Ofp)&Muler2::OnAB); subj2.Notify(1, 2); return 0 }
     
    
   
  
这个方法是基于类的成员函数指针来实现的,同样是继承,但是并不要求Observer类必须实现制定的虚函数,只需要保证有相同的成员函数签名。一个Observer类甚至能容纳多个Observer方法。这种方式相对前一种方式更灵活一点,但是同样要求继承一个基类,还是有一定的耦合性。

?

?

再看最后一个,c++11的版本

?

// cpp11
typedef std::function
  
    IntOpFun;

struct Subject3
{
	void AddObserver(IntOpFun of)
	{
		m_vecOf.push_back(of);
	}

	void Notify(int iA, int iB)
	{
		for (auto iter = m_vecOf.begin(); iter != m_vecOf.end(); ++iter)
		{
			(*iter)(iA, iB);
		}
	}
	std::vector
   
     m_vecOf; }; struct Adder3 { int OnAB(int iA, int iB) { printf(Add3(%d,%d)=%d , iA, iB, iA + iB); return iA + iB; } }; struct Muler3 { int OnAB(int iA, int iB) { printf(Mul3(%d,%d)=%d , iA, iB, iA * iB); return iA * iB; } }; int main() { Subject3 subj; Adder3 adder; Muler3 muler; subj.AddObserver(std::bind(&Adder3::OnAB, &adder, std::placeholders::_1, std::placeholders::_2)); subj.AddObserver(std::bind(&Muler3::OnAB, &muler, std::placeholders::_1, std::placeholders::_2)); subj.Notify(1, 2); return 0; }
   
  
这种方式不需要继承基类,不需
首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇SDUT 2894-C(最短路spfa) 下一篇HDU 4951 Multiplication table(..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·Python中文网 - 人生 (2025-12-24 18:49:47)
·【整整648集】这绝对 (2025-12-24 18:49:44)
·Python超详细一条龙 (2025-12-24 18:49:42)
·【超详细】JDK 下载 (2025-12-24 18:19:32)
·Java_百度百科 (2025-12-24 18:19:29)