c++代理类

来源:互联网 发布:exif信息查看器 mac 编辑:程序博客网 时间:2024/06/05 18:38

其实代理模式跟这个差不多,对象A(相当于浏览器)不是直接访问对象C(相当Web服务器),而是通过一个中间对象B(相当于代理服务器)间接访问对象C。对象B则可以利用这一有利位置为A提供一个与C完全不同的接口,或做一些C本来不做的事!流程如下图所示:


A -----> B ------> C

这样B就是C的代理类,C可被称作实现类,A是客户代码。

==================
下面是源代码,一共4个文件。其中实现类成员函数为全部写成内联函数。
1. 实现类文件implementation.h:
// implementation.h --
// 2006-07-21 14:20

#ifndef IMPLEMENTATION_H_
#define IMPLEMENTATION_H_

class Implementation {
public:

Implementation(int v) { value = v; }

void setValue(int v) { value = v; }

int  getValue() const { return value; }


private:

int value;

};
#endif

2. 代理类头文件interface.h:
// interface.h -- Interface类是Implementation类的代理类
// 2006-07-21 14:23

#ifndef INTERFACE_H_
#define INTERFACE_H_

class Implementation;  // forward class declaration

class Interface {      // Interface代理类
public:

Interface(int v);

void setValue(int v);

int  getValue() const;

~Interface();


private:

Implementation * ptr;

};

#endif

3. 代理类实现文件interface.cpp:
// interface.cpp
// 2006-07-21 14:25

#include "implementation.h"
#include "interface.h"

Interface::Interface(int v) : ptr(new Implementation(v)) {
}

void Interface::setValue(int v) {

ptr->setValue(v);

}

int Interface::getValue() const {

return ptr->getValue();

}

Interface::~Interface() {

delete ptr;

}

4. 客户代码,这里只是一个主函数,使用代理模式,文件:useproxy.cpp:
// useproxy.cpp -- Use proxy class
// 2006-07-21 14:29

#include <iostream>
#include "implementation.h"
#include "interface.h"
using namespace std;

int main() {

Interface i(5);


cout << "Interface contains: " << i.getValue() << " before setValue/n";


i.setValue(10);

cout << "Interface contains: " << i.getValue() << " after setValue/n";

return 0;

}

=======================
运行结果:
Interface contains: 5 before setValue
Interface contains: 10 after setValue
Press any key to continue

=========================
说明:在useproxy.cpp文件中,只有一个Interface类对象,即代理类对象,所有的操作都是调用代理类的公有函数,间接操作实现类。



---------------------------------------


// 代理类 Demo// 将继承和容器共用,迫使我们要处理两个问题:// 控制内存分配和把不同类型的对象放入同一个容器中。// 代理类的每个对象都代表另一个对象,该对象可以是// 位于一个完整继承层次中的任何类的对象。通过在容器中// 用代理对象而不是对象本身来解决以上两个问题#include <process.h>        // system()#include <iostream>using namespace std;// 所有交通工具的基类class Vehicle{public:    virtual void start() = 0;    // 动态复制    virtual Vehicle* copy() const = 0;    // 虚析构函数    virtual ~Vehicle() {}};// 交通工具的代理类class VehicleSurrogate{public:    // 无参构造函数,用于创建数组    VehicleSurrogate();    // 用Vehicle 及其派生类构造    VehicleSurrogate(const Vehicle&);    ~VehicleSurrogate();    // 拷贝及赋值    VehicleSurrogate(const VehicleSurrogate&);    VehicleSurrogate& operator=(const VehicleSurrogate&);    // Vehicle 的方法    void start();private:    Vehicle* p;};VehicleSurrogate::VehicleSurrogate() : p(0) {}VehicleSurrogate::VehicleSurrogate(const Vehicle& v) : p(v.copy()) {}VehicleSurrogate::VehicleSurrogate(const VehicleSurrogate& vs) : p(vs.p ? vs.p->copy() : 0) {}VehicleSurrogate & VehicleSurrogate::operator =(const VehicleSurrogate& vs){    if (p != vs.p)    {        delete p;        p = vs.p ? vs.p->copy() : 0;    }    return *this;}VehicleSurrogate::~VehicleSurrogate() { delete p; }void VehicleSurrogate::start(){    if (p)        p->start();    else        cout << "Error" << endl;}class RoadVehicle : public Vehicle{public :    void start()    {        cout << "RoadVehicle start." << endl;    }    Vehicle* copy() const    {        return (Vehicle*) new RoadVehicle(*this);    }    ~RoadVehicle()    {    }};class AutoVehicle : public RoadVehicle{public :    void start()    {        cout << "AutoVehicle start." << endl;    }    Vehicle* copy() const    {        return (Vehicle*) new AutoVehicle(*this);    }    ~AutoVehicle()    {    }};void main(){    VehicleSurrogate pa[3];    RoadVehicle* prv = new RoadVehicle();    pa[0] = *prv;    delete prv;    pa[1] = AutoVehicle();    pa[2] = RoadVehicle();    pa[0].start();    pa[1].start();    pa[2].start();    system("pause");}


---------------------------------

问题:怎样设计一个c++容器,使它有能力包含类型不同而彼此相关的对象?

假设有一个表示不同种类的交通工具的类派生层次:

class Vehicle

{

public:

virtual double weight() const = 0;

virtual void start() = 0;

//.....

};

class RoadVehicle:public Vehicle {/*...*/};

class AutoVehicle:public RoadVehicle{/*....*/};

为了表述简单,使用数组来实现。由浅入深的提出以下几个方案:

方案一: 数组直接存储对象

Vehicle parking_lot[1000];

AutoVehicle x = /*.....*/

parking_lot[num_vehicles++] = x;

这里出现两个问题:

(1) Vehicle 为抽象基类,类Vehicle本身不会有对象,因此定义对象数组也就不可行了。

(2) 即使去掉类Vehicle中的纯虚函数,parking_lot 保存的是派生类裁剪后的对象,而不是所有继承自Vehicle类的对象的集合。

方案二:数组存储指针

Vehicle* parking_lot[1000];

AutoVehicle x = /*...*/;

parking_lot[num_vehicles++] = &x;

这里出现下面的问题:

我们存储在parking_lot中的是指向x的指针,如果x是个局部变量,一但变量x没有了,parking_lot就不知道指向什么东西了。我们可以改进一下,放入parking_lot中的值,不是指向原对象的指针,而是指向它们的副本的指针。在释放数组的时候,也释放其中所指向的全部对象。上面的代码可以改写为:

AutoVehicle x = /*...*/;

parking_lot[num_vehicles++] = AutoVehicle(x);

但是这样改也带来了动态内存管理的负担。另外,只有当我们知道要放到parking_lot中的对象的静态类型后,这种方法才能起作用。为了解决这个问题可以使用用虚复制函数, c++中处理未知类型的对象的方法就是使用虚函数。我们可以在类Vehicle中添加纯虚函数: virtual Vehicle* copy() const = 0; 则在派生类AutoVehicle 中 copy() 函数可以如下实现:

Vehicle* AutoVehicle::copy() const

{

return new AutoVehicle(*this);

}

然后就可以这样存储了: parking_lot[num_vehicles++] = x->copy(); 这里可以在运行时确定所要调用的copy函数。

方案三:定义代理类

方案二已经能较好的解决问题了,但是我们想避免显示的处理内存分配,又能保持类Vehicle在运行时绑定。这里采用代理类技术,就是定义一个行为和Vehicle对象相似,而又潜在地表示所有继承自Vehicle类的对象的东西。每个Vehicle代理都代表某个继承自Vehicle类的对象。只要该代理关联着这个对象,该对象就肯定存在。简单的实现了一下代理类,代码如下:

#include <iostream>
using namespace std;

class Vehicle
{
public:
virtual double weight() const = 0;
virtual Vehicle* copy() = 0;
virtual ~Vehicle() {}
};

class AutoVehicle:public Vehicle
{
public:
double weight() const
{
cout << "AutoVehicle weight" << endl;
return 1;
}
Vehicle* copy()
{
return new AutoVehicle(*this);
}
};
class RoadVehicle:public Vehicle
{
public:
double weight() const
{
cout << "RoadVehicle weight" << endl;
return 2;
}
Vehicle* copy()
{
return new RoadVehicle(*this);
}
};

class VehicleSurrogate
{
public:
VehicleSurrogate();
VehicleSurrogate(Vehicle&);
~VehicleSurrogate();
VehicleSurrogate(const VehicleSurrogate&);
VehicleSurrogate& operator=(const VehicleSurrogate&);
double weight() const;
private:
Vehicle *vp;
};

VehicleSurrogate::VehicleSurrogate():vp(0){} //空代理

VehicleSurrogate::VehicleSurrogate(Vehicle &v):vp(v.copy()){}

VehicleSurrogate::~VehicleSurrogate()
{
delete vp;
}
VehicleSurrogate::VehicleSurrogate(const VehicleSurrogate &v):
vp(v.vp ? v.vp->copy() : 0){}
VehicleSurrogate& VehicleSurrogate::operator=(const VehicleSurrogate &v)
{
if(this != &v)
{
delete vp;
vp = (v.vp ? v.vp->copy() : 0);
}
return *this;
}
double VehicleSurrogate::weight() const
{
if(vp == 0)
{
cout << "empty VehicleSurrogate" << endl;
}
else
{
return vp->weight();
}
}

int main()
{
VehicleSurrogate parking_lot[1000];
AutoVehicle x;
int num_vehicles = 0;
parking_lot[num_vehicles++] = x;
parking_lot[0].weight();

RoadVehicle y;
parking_lot[num_vehicles++] = VehicleSurrogate(y);
parking_lot[1].weight();
return 0;
}

个人感觉代理类最主要的好处就是隐藏的内存的分配,方案二中copy就已经可以实现了,只不过看起来不是那么顺眼。代理类用类来表示概念,通过在容器中代理对象而不是对象本身,解决了我们的问题。



原创粉丝点击