VC,BCB,C#,Delphi,Java的委託方案

委託(delegate)有委託接收方和委託發出方兩個實例。委託接收方需要有一個函數實現,然後“拜託”別人調用。委託發出方需要有一個“服務員”接受委託接收方的“委託”請求,並記錄調用入口,在非面向對象的時候用的是函數指針,現在面向對象,需要保存this後調用纔行,所以不同的語言用了不同的實現方法。

BCB, 使用關鍵字__closure 基本上可以解決。
先聲明“服務員”能接受什麼樣的申請:
typedef BOOL __fastcall(__closure *FSynchronizationCaller)(SynchronizationManager *synchronization_manager);

委託發出方,這裏用ExitCallers保存調用入口
class SynchronizationChecker
{
public:
FSynchronizationCaller ExitCallers;
};
普通賦值語句就可以保存入口,實現“拜託”的工作
ExitCallers=FirstBranch;//FirstBranch的函數與“服務員”對應
調用的時候ExitCallers象普通函數一樣使用,但是this已經是委託接收方的了。

Delphi更簡單, __closure關鍵字都不用
先聲明“服務員”能接受什麼樣的申請:
type FSynchronizationCaller = function (synchronization_manager:TObject):Boolean of object;
後面的做法與BCB類似

這裏着重講VC的
VC6,VC7:參照fast delegate。但是比它還要快和易懂
首先聲明委託通用類,即所有this的通用化
class GenClass{};
//設置成與BCB類似的形式
#define __Closure GenClass::
定義模板
template<class T,typename FunctionType>
class Closure
{
public:
    FunctionType Func;
    T *This;
};
template<typename FunctionType,typename RetType=void *>
class Delegate
{
    typedef Closure<GenClass,FunctionType> ClosureType;
    ClosureType *ClosureClass;
public:
    Delegate(){ClosureClass=0;}
    ~Delegate(){delete ClosureClass;}
public:
  
    //--------------for no param function
    template <class X>
        inline void bind(X *pthis, void (X::* function_to_bind)())//for void return function
    {
        typedef void (X::*LocalFunctionType)();
        typedef Closure<X,LocalFunctionType> X_ClosureType;
        X_ClosureType *c=new X_ClosureType;
        c->This=pthis;
        c->Func=function_to_bind;
        ClosureClass=(ClosureType *)c;
    }
    template <class X>
        inline void bind(X *pthis, RetType (X::* function_to_bind)())//for other(not void) return function
    {
        typedef RetType (X::*LocalFunctionType)();
        typedef Closure<X,LocalFunctionType> X_ClosureType;
        X_ClosureType *c=new X_ClosureType;
        c->This=pthis;
        c->Func=function_to_bind;
        ClosureClass=(ClosureType *)c;
    }
    inline RetType operator()()
    {
        typedef RetType (GenClass::*LocalFunctionType)();//convert to void to void*,if it is appointed
        return (ClosureClass->This->*(LocalFunctionType)ClosureClass->Func)();
    }
  
    //--------------for 1 param function
    template <class X,typename Param1>
        inline void bind(X *pthis, void (X::* function_to_bind)(Param1))//for void return function
    {
        typedef void (X::*LocalFunctionType)(Param1);
        typedef Closure<X,LocalFunctionType> X_ClosureType;
        X_ClosureType *c=new X_ClosureType;
        c->This=pthis;
        c->Func=function_to_bind;
        ClosureClass=(ClosureType *)c;
    }
    template <class X,typename Param1>
        inline void bind(X *pthis, RetType (X::* function_to_bind)(Param1))//for other(not void) return function
    {
        typedef RetType (X::*LocalFunctionType)(Param1);
        typedef Closure<X,LocalFunctionType> X_ClosureType;
        X_ClosureType *c=new X_ClosureType;
        c->This=pthis;
        c->Func=function_to_bind;
        ClosureClass=(ClosureType *)c;
    }
    template <typename Param1>
        inline RetType operator()(Param1 p1)
    {
        typedef RetType (GenClass::*LocalFunctionType)(Param1);//convert to void to void*,if it is appointed
        return (ClosureClass->This->*(LocalFunctionType)ClosureClass->Func)(p1);
    }
};
如果有更多的參數需要擴展響應的模板成員函數。
使用的時候
先聲明“服務員”能接受什麼樣的申請
typedef BOOL (__Closure *myfunc)(int a);
typedef Delegate<myfunc,BOOL> MyDelegete_t;

#include <stdio.h>
struct A
{
  BOOL f(int a){printf("%d",a);return TRUE;}//與 myfunc對應
};

LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
  MyDelegete_t d;
  A a;
  d.bind(&a,A::f);
  d(100);
  ............
}

其餘部分與BCB類似,不再贅述。
要理解C++如何用實現委託的,可以參照fastdelegate,和http://www.x5dj.com/UserForum/00100079/00009471.shtml
上述源代碼從Duceland Designer 打開例子後生成代碼所得,模板這裏下載http://duceland.com/Download/VC6.zip


C#:
“服務員”能接受什麼樣的申請是自動完成的,只有保存要函數入口的地方就可以了,這就是進步啊,雖然不是原創。
public delegate bool DSynchronizationCaller(SynchronizationManager synchronization_manager);
其餘部分類似,不再贅述。

Java不是很精通,只好這樣了
“服務員”是統一的,默認的
保存調用入口比較麻煩
public class DSynchronizationCaller{
    public Method m_Method;
    public Object m_Object;
    public boolean bind(Class cls,Object object,String method_name){
        m_Object=object;

        // By obtaining a list of all declared methods.
        Method[] methods = cls.getDeclaredMethods();
        for (int i=0; i<methods.length; i++) {
            if(methods[i].getName().equals(method_name)){
                m_Method=methods[i];
                return true;
            }
        }
        return false;
    }

//調用的時候也不是很自然,用invoke ,參數被轉入Object[]數組
    public Object invoke(SynchronizationManager synchronization_manager){
        try {
            Object result=m_Method.invoke(m_Object, new Object[] {synchronization_manager});
            return result;
        } catch (Exception e) {System.err.println(e);}
        return null;
    }
};

事件通過bind綁定後用invoke執行。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章