Để thêm vào, tôi đã sử dụng các đối tượng hàm để khớp một phương thức kế thừa hiện có với mẫu lệnh; (chỉ nơi mà vẻ đẹp của mô hình OO đúng OCP tôi cảm thấy); Cũng thêm vào đây các mẫu bộ điều hợp chức năng liên quan.
Giả sử phương thức của bạn có chữ ký:
int CTask::ThreeParameterTask(int par1, int par2, int par3)
Chúng ta sẽ thấy làm thế nào chúng ta có thể điều chỉnh nó cho mẫu Lệnh - trước tiên, bạn phải viết một bộ điều hợp chức năng thành viên để nó có thể được gọi là một đối tượng hàm.
Lưu ý - điều này thật tệ và có thể bạn có thể sử dụng trình trợ giúp liên kết Boost, v.v., nhưng nếu bạn không thể hoặc không muốn, đây là một cách.
// a template class for converting a member function of the type int function(int,int,int)
//to be called as a function object
template<typename _Ret,typename _Class,typename _arg1,typename _arg2,typename _arg3>
class mem_fun3_t
{
public:
explicit mem_fun3_t(_Ret (_Class::*_Pm)(_arg1,_arg2,_arg3))
:m_Ptr(_Pm) //okay here we store the member function pointer for later use
{}
//this operator call comes from the bind method
_Ret operator()(_Class *_P, _arg1 arg1, _arg2 arg2, _arg3 arg3) const
{
return ((_P->*m_Ptr)(arg1,arg2,arg3));
}
private:
_Ret (_Class::*m_Ptr)(_arg1,_arg2,_arg3);// method pointer signature
};
Ngoài ra, chúng ta cần một phương thức trợ giúp mem_fun3 cho lớp trên để hỗ trợ gọi.
template<typename _Ret,typename _Class,typename _arg1,typename _arg2,typename _arg3>
mem_fun3_t<_Ret,_Class,_arg1,_arg2,_arg3> mem_fun3 ( _Ret (_Class::*_Pm) (_arg1,_arg2,_arg3) )
{
return (mem_fun3_t<_Ret,_Class,_arg1,_arg2,_arg3>(_Pm));
}
Bây giờ, để liên kết các tham số, chúng ta phải viết hàm binder. Vì vậy, ở đây nó đi:
template<typename _Func,typename _Ptr,typename _arg1,typename _arg2,typename _arg3>
class binder3
{
public:
//This is the constructor that does the binding part
binder3(_Func fn,_Ptr ptr,_arg1 i,_arg2 j,_arg3 k)
:m_ptr(ptr),m_fn(fn),m1(i),m2(j),m3(k){}
//and this is the function object
void operator()() const
{
m_fn(m_ptr,m1,m2,m3);//that calls the operator
}
private:
_Ptr m_ptr;
_Func m_fn;
_arg1 m1; _arg2 m2; _arg3 m3;
};
Và, một hàm trợ giúp để sử dụng lớp binder3 - bind3:
//a helper function to call binder3
template <typename _Func, typename _P1,typename _arg1,typename _arg2,typename _arg3>
binder3<_Func, _P1, _arg1, _arg2, _arg3> bind3(_Func func, _P1 p1,_arg1 i,_arg2 j,_arg3 k)
{
return binder3<_Func, _P1, _arg1, _arg2, _arg3> (func, p1,i,j,k);
}
Bây giờ, chúng ta phải sử dụng điều này với lớp Command; sử dụng typedef sau:
typedef binder3<mem_fun3_t<int,T,int,int,int> ,T* ,int,int,int> F3;
//and change the signature of the ctor
//just to illustrate the usage with a method signature taking more than one parameter
explicit Command(T* pObj,F3* p_method,long timeout,const char* key,
long priority = PRIO_NORMAL ):
m_objptr(pObj),m_timeout(timeout),m_key(key),m_value(priority),method1(0),method0(0),
method(0)
{
method3 = p_method;
}
Đây là cách bạn gọi nó:
F3 f3 = PluginThreadPool::bind3( PluginThreadPool::mem_fun3(
&CTask::ThreeParameterTask), task1,2122,23 );
Lưu ý: f3 (); sẽ gọi phương thức task1-> ThreeParameterTask (21,22,23);.
Toàn bộ bối cảnh của mẫu này tại liên kết sau