您的位置:首页 > 编程语言

以简单的设计模式代码阐述如何设计委托

2017-12-04 22:26 453 查看
先来看看composite组合模式下,是怎么实现委托的,如果现在面对一个问题,file system,有目录,目录里可以放文件,目录还能和其他的文件结合在一起放在另外的目录里面,这时候需要写个个体,需要一个组合物,这个组合物应该可以容纳组合物和个体,那么如何做到,一个容器容纳2个不同的东西,除非他们是is a拥有父类,这样其实就是属于同一种东西,只是不同的表现罢了,所以由如下的关系图:


class Component{
private:
int value;
public:
virtual void add(Component*){}//如果设计为纯虚函数,那就不行了,Primitive不应该去定义
};

class Primitive:public Component{
public:
Primitive(int value):Component(value){}
};
class Composite:public Component{
private:
vector<Component*> c;
public:
Composite(int value):Component(value){}
virtual void add(Component*){
c.push_back(Component);
}
...
}
如果现在有个题目是我需要一个继承体系,需要去创建未来的子类,是被客户买去以后才会出现,客户要用到这个类(框架)的数据,不能再父类里面new,子类还未出现,客户自己创建子类,能被我现在的类看得到。所以由了prototype设计模式。

客户在子类里创造了一个静态的对象,自己创造自己,把这个原型添加到父类里,父类就可以看到了。


-号代表私有,#号代表protect,+(一般不写)表示Public,通过Static 创建静态对象,在私有的构造函数里,把这个this传递给父类,然后创建一个clone()函数,创建副本,通过之前在父类里的原型调用clone()函数,如果没有的话就不行了,可能会想到clone()为静态函数,可以通过类名调用,但是这个类名是未来的  所以不可以。

通过整体设计模式图,我们可以写出源代码


父类通过将addPrototype(Image*)设置为静态函数,让所有的类都可以调用它(不用写类名),就可以把自己添加到父类中的数组里

首先父类如下所示:

enum imageType{
LSAT,SPOT;
}
class Image{
private:
static Image* _prototypes[10];//储存各个子类传递来的原型
static int _nextSlot;//标记原型个数
protected:
static void addPrototype(Image*){
_prototypes[_nextSlot++] = Image;//给所有的子类通用的函数接口,可以把自己添加到静态数组里面去
}
virtual Image* clone() = 0;
virtual imageType returnType() = 0;//在子类中重载,返回各个子类特有的标识符
public:
virtual void draw() = 0;
static Image* findandclone(imageType);//找到该类型的函数原型,并且调用子类中重载的clone()进行创建副本返回。
};定义式:
static Image* _prototypes[];
static int _nextSlot;
Image* Image::findandclone(imageType type){
for(int i=0;i<_nextSlot;i++){
if(_prototypes[i]->returnType() == Type)
return _prototypes[i]->clone();
}
}接下来以其中一个子类为例,编写程序:

class LandSatImage:public Image{
public:
virtual imageType returnType{
return LSAT;
}
void draw(){
cout << "LandSatImage::draw" << endl;
}
Image* clone(){
return new LandSatImage(1);//返回的是指针所以new
}
protected:
LandSatImage(int){
id=count++;
}
private:
static LandSatImage landsatimage;//就是下面的this 自己的静态变量,交给父类的原型
LandSatImage(){
addPrototype(this);
}
int id;
static int count;
};
int LandSatImage::count = 1;
LandSatImage LandSatImage::landsatimage;














                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: