C++模拟实现Objective-C协议和代理模式

Objective-C的协议和代理是运用最多的特性之一,可以说在苹果系列开发中无处不在。事实上很多人都不知道其背后的原理。事实上简单点说,这就是设计模式中的代理模式的经典运用。代理模式简单点说就是为其他对象提供一种代理以控制对这个对象的访问,而在OC当中形象点说就是如果A完成一件事,但是自己不能完成,于是他找个代理人B 替他完成这个事情,他们之间便有个协议 (protocol),B继承该协议来完成A代理给他的事情。

举个例子:有一个婴儿,他本身不会自己吃饭和洗澡等等一些事情,于是婴儿就请了一个保姆,于是婴儿和保姆之间商定了一个协议,协议中写明了保姆需要做什么事情, 而保姆就是这个代理人, 即:婴儿和保姆之间有个协议,保姆继承该协议,于是保姆就需要实现该协议中的条款成为代理人。

那么回到Objective-C,举一个很简单的例子,tableview是运用最多的控件之一,其用法相信每一个做ios开发的童鞋都很清楚。其实这也是一个代理委托的经典运用。

首先初始化tableview控件,并且指定好代理和委托

_tableview = [[UITableView alloc] init];
[_tableview setDelegate:self];
[_tableview setDataSource:self];
[self.view addSubview:_tableview];

_data = [[NSMutableArray alloc] initWithObjects:@"中国", @"美国", @"英国", nil];

真正要把数据显示到界面上的时候,其实只需要重载下面这个函数就可以了

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

至于为什么会调用到tableView这个函数上面,开发者完全不用关心。并且获取data中数据个人等等,这些都不需要自己去做。回到最初举得例子,其实tableview就相当一个婴儿,他根本不会把数据画到界面上去,于是他找了一个保姆做代理,就是主界面。主界面继承并且实现了这个协议(其实协议就是tableView函数)来玩成整个系列功能。

如果用C++来模拟实现,其简单代码可以如下所示:

// proxyproj.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <stdio.h>
#include <Windows.h>

class NSObject
{
public:
    virtual void callfun(){}
    virtual void tableview(int nShow){}
    NSObject *delegate;
};

DWORD WINAPI UIViewControlerThreadProc(LPVOID lpParam)
{
    //do something
    //......

    NSObject *pSelf = (NSObject *)lpParam;
    pSelf->delegate->tableview(100);
    return 0;
}

DWORD WINAPI proxyThreadProc(LPVOID lpParam)
{
    //do something
    //......

    NSObject *pSelf = (NSObject *)lpParam;
    pSelf->callfun();
    return 0;
}

class proxy : public NSObject
{
public:
    virtual void callfun()
    {
        CloseHandle(CreateThread(NULL,0,proxyThreadProc,this,0,NULL));
    }
};

class TableView : public proxy
{


};

class UIViewControler : public proxy
{
public:
    void init()
    {
        TableView *tabView = new TableView;
        tabView->delegate = this;
        CloseHandle(CreateThread(NULL,0,UIViewControlerThreadProc,tabView,0,NULL));
    }
    void tableview(int nShow){    printf("Show Number %d \n",nShow);}
};

int _tmain(int argc, _TCHAR* argv[])
{
    UIViewControler ui;
    ui.init();
    getchar();
    return 0;
}

UIViewControler就相当于主界面,init就是初始化过程。在其中为TableView初始化代理,然后通过代理回调到tableview函数内部。而作为主界面方,只需要重载tableview函数即可,根本不需要关心内部实现。