菜鸟教程连接https://www.runoob.com/design-pattern/prototype-pattern.html
《大话设计模式》的UML类图入下 :
菜鸟教程的UML类图如下:
解决的问题 :
- 在运行期间建立和删除原型
- 逃避构造函数的约束
-
接口类
ICloneable.hpp
里要有clone()
函数#ifndef _ICLONEABLE_H #define _ICLONEABLE_H #include <stdlib.h> #include "MajiaoObject.hpp" class ICloneable : public MajiaoObject { public : ICloneable() { } ~ICloneable() { } // 纯虚函数 virtual ICloneable* clone() = 0; // 一个简单拷贝,浅拷贝 virtual ICloneable* clone(int objSize) { char* objClone = (char*) malloc(objSize); memcpy(objClone, this, objSize); return (ICloneable*) objClone; } }; #endif // _ICLONEABLE_H
-
图形类
Shape
要实现ICloneable
的函数#ifndef _SHAPE_H #define _SHAPE_H #include "ICloneable.hpp" class Shape : public ICloneable { public : int color; int w, h; Shape() { } ~Shape() { } // 重写父类的clone函数 virtual ICloneable* clone() override { Shape* objClone = new Shape(); *objClone = *this; return objClone; } virtual double calcArea() { return w * h; } }; #endif // _SHAPE_H
-
图形的子类
Circle
,Rect
和Oval
都要重写父类的clone()
-
没有新的成员变量,可以用父类的
clone()
#ifndef _RECT_H #define _RECT_H #include "Shape.hpp" // Rect没有重写clone,因为没有新的成员变量,可以直接用父类的clone class Rect : public Shape { public : Rect() { } ~Rect() { } }; #endif // _RECT_H
-
有新的成员变量,需要重写
clone()
#ifndef _OVAL_H #define _OVAL_H #include <math.h> #include "Shape.hpp" // 椭圆 class Oval : public Shape { public : double a, b, c; // 焦点,在x轴上,在y轴上 enum FOCUS { FOCUS_X, FOCUS_Y }; Oval() { } ~Oval() { } // 有新成员a,b,c,要重写拷贝 virtual ICloneable* clone() override { // Oval* objClone = new Oval(); // *objClone = *this; // return (ICloneable*)(objClone); return ICloneable::clone(sizeof(Oval)); } virtual double calcArea() { // S = PI * A * B return acos(-1) * a * b; } }; #endif // _CIRCLE_H
-
当有成员变量是指针时,要深拷贝,书上重载了构造函数,在构造的时候
clone
#ifndef _CIRCLE_H #define _CIRCLE_H #include "Oval.hpp" // 圆形是特殊的椭圆,使用装饰器(这里其实应该继承,用装饰器只是为了演示“有指针变量”的clone) class Circle : public Oval { public : Oval* oval; Circle() { } // 书上说,在构造里添加一个对 成员指针的clone即可 Circle(Oval* oval) { this->oval = (Oval*) oval->clone(); } ~Circle() { } virtual ICloneable* clone() { // 调用构造去克隆成员指针 Circle* objClone = new Circle(this->oval); objClone->h = this->h; objClone->w = this->w; objClone->color = this->color; return objClone; } }; #endif // _CIRCLE_H
-
-
在调用方就直接
xxx->clone()
即可signed main() { Shape* shape = new Rect(), *oval = new Oval(); Circle *circle = new Circle(new Oval()); circle->oval->a = 999; shape->color = 0xff; circle->color = 0x77; // 两种clone方式 ICloneable *rectColone = shape->clone(), //成员变量浅拷贝,成员变量是指针类型时要小心 *rectClone2 = shape-> ICloneable::clone(int(sizeof(Shape))), *overClone = oval->clone(), // "成员变量是指针" 的深拷贝clone方式 *circleClone = circle->clone(); cout << shape->color << endl; cout << ((Shape*)rectColone)->color << endl; cout << ((Shape*)rectClone2)->color << endl; cout << ((Shape*)circleClone)->color << " " << ((Circle*)circleClone)->oval->a << endl; return 0; }
-
TODO,使用宏来实现
clone()
函数