高调设计情势C

   
本篇发轫前头阵个有利于,程杰的《大话设计形式》一书高清电子版(带目录)已上传至CSDN,免积分下载。
下载地址:http://download.csdn.net/detail/gufeng99/8843487

   
代理方式是一种相比不难但却实用的设计方式,他得以灵活的更换代理的靶子,但保障功能的完整性,就像卖衣裳的代理商,他得以代劳美特斯邦威的行装,倘诺美特斯邦威的衣裳被世家吐槽不佳卖了,他还足以换去代理卖佐丹奴的,但不管怎么更换,还能满意大家的急需——买衣物。
    上边以大话设计方式书中的例子为例,设计一个代理帮小明送花给小红。

1、依据接口编程,设计代理对象的接口

class IPursuit
{
public:
    virtual ~IPursuit() {}

    virtual void    SendFlowers() = 0;
};

2、代理类,也持续代理对象类,保持接口一致

class CProxy : public IPursuit
{
public:
    CProxy() : m_poIPursuit(NULL)   {}
    ~CProxy()
    {
        if (m_poIPursuit)
        {
            delete  m_poIPursuit;
            m_poIPursuit = NULL;
        }
    }

    void    SetPursuit(IPursuit* poIPursuit)
    {
        //如果有旧的代理,要先删除,否则会造成内存泄漏
        if (m_poIPursuit)
        {
            delete  m_poIPursuit;
        }

        m_poIPursuit = poIPursuit;
    }

    void    SendFlowers()
    {
        if (m_poIPursuit)
        {
            printf("Proxy help ");
            m_poIPursuit->SendFlowers();
        }
    }

private:
    IPursuit*   m_poIPursuit;
};

   
代理类实际上啥也没干,只是对同一的函数调用了手段被代理的对象的对应函数,当了一次二传手的角色。那里要留心代理对象由于会在代理中被释放,所以代理的目的一律必须是new出来的,即需在堆上创设的。
3、被代理对象类

class CPursuit : public IPursuit
{
public:
    CPursuit(TString tstrName) : m_tstrName(tstrName) {}
    ~CPursuit() {}

    void    SendFlowers()
    {
        _tprintf(_T("%s sent flowers to Xiaohong\n"), m_tstrName.c_str());
    }

private:
    TString m_tstrName;
};

另附上TString宏

#ifdef  UNICODE
    #define TString std::wstring
#else
    #define TString std::string
#endif

4、测试示例

void   Test()
{
    IPursuit*   poIXiaoMing = new CPursuit(_T("XiaoMing"));
    CProxy      oCProxy;

    oCProxy.SetPursuit(poIXiaoMing);
    oCProxy.SendFlowers();
}

5、代理类的应用
   
这么些事例很形象,但却很难看出代理情势的运用和长处。实际上在《高调设计情势C++版——抽象工厂情势电子版,》中有一个操作数据库管理员工音信的事例,由于可能会在动用数据库的过程中切换数据库,如从前用的MySql,可能某个客户要求帮忙Access,这时就得举行切换了,此时用代理情势一样可以完毕。
5.1 代理情势完毕职工数据库管理类对数据库的切换

typedef    struct Employee 
{
    int     nID;
    TString tstrName;
};

class IEmployee
{
public:
    ~IEmployee()    {}

    virtual bool        InserttoDB(Employee& stEmployee) = 0;
    virtual Employee    GetEmployee(int nID) = 0;
};

class CProxy : public IEmployee
{
public:
public:
    CProxy() : m_poIEmployee(NULL)  {}
    ~CProxy()
    {
        if (m_poIEmployee)
        {
            delete  m_poIEmployee;
            m_poIEmployee = NULL;
        }
    }

    void        SetEmployee(IEmployee* poIEmployee)
    {
        if (m_poIEmployee)
        {
            delete  m_poIEmployee;
        }

        m_poIEmployee = poIEmployee;
    }

    bool        InserttoDB(Employee& stEmployee)
    {
        if (m_poIEmployee)
        {
            return  m_poIEmployee->InserttoDB(stEmployee);
        }

        return  false;
    }

    Employee    GetEmployee(int nID)
    {
        if (m_poIEmployee)
        {
            return  m_poIEmployee->GetEmployee(nID);
        }

        Employee    stEmployee;
        return  stEmployee;
    }

private:
    IEmployee*  m_poIEmployee;
};

class CEmployeefromMysql : public IEmployee
{
public:
    bool        InserttoDB(Employee& stEmployee)
    {
        _tprintf(_T("Insert employee %s into mysql\n"), stEmployee.tstrName.c_str());
        return  true;
    }

    Employee    GetEmployee(int nID)
    {
        Employee    stEmployee;
        printf("Get an employee from mysql by id %d\n", nID);
        return  stEmployee;
    }
};

class CEmployeefromAccess : public  IEmployee
{
public:
    bool        InserttoDB(Employee& stEmployee)
    {
        _tprintf(_T("Insert employee %s into access\n"), stEmployee.tstrName.c_str());
        return  true;
    }

    Employee    GetEmployee(int nID)
    {
        Employee    stEmployee;
        printf("Get an employee from access by id %d\n", nID);
        return  stEmployee;
    }
};

5.2 使用示例

void   DataBaseTest()
{
    IEmployee*  poIEmployee = new CEmployeefromMysql();
    CProxy      oCProxy;

    oCProxy.SetEmployee(poIEmployee);

    Employee    stEmployee;
    stEmployee.nID = 1;
    stEmployee.tstrName = _T("Jim");

    oCProxy.InserttoDB(stEmployee);

    //切换数据库对象
    poIEmployee = new   CEmployeefromAccess();

    oCProxy.SetEmployee(poIEmployee);
    oCProxy.InserttoDB(stEmployee);
}

   
从利用示例中就足以观察,代理类协助客户使用进程中动态切换数据库,那是和工厂情势最大的一些不比,越发适用于在不时索要切换类似对象形式的地点。

相关文章