Prototype 原型模式的意图是,用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
适用于:当一个系统应该独立于它的产品创建、构成和表示时,要使用 Prototype 模式;以及当要实例化的类是在运行时刻指定时,如通过动态装载;或者为了避免创建一个与产品类层次平行的工厂类层次时;或者当一个类的实例只能有几个不同状态组合中的一种时。建立相应数目的原型并克隆它们可能比每次用合适的状态手工实例化该类更方便一些。
Prototype 模式的最简通用结构如下:
Prototype 声明一个克隆自身的接口,具体的子类实现一个克隆自身的操作,而用户则让一个原型克隆自身来创建一个新的对象。
Prototype 的每个子类必须实现 Clone 操作,且须将其实现为深拷贝(deep copy),有的情况下这是非常困难的。例如当一些类内部包括一些不支持拷贝或有循环引用的对象时。
对于这个模式的实现有一些不解:1)网上的代码都是按照上图给出的,即抽象基类 Prototype 有一纯虚成员函数 Clone,。2)子类实现 Clone,且返回的是也是指向抽象基类 Prototype 的指针。
但是设计模式一书中的迷宫示例却不是这样:1)子类的 Clone 返回的都是指向自身的指针,而不是指向抽象基类的指针。2)书中没有给出抽象基类的 Clone 原型,让我郁闷。
我于是想按照书中的示范实现上图的示例程序,但是却碰到了一个问题:1)如果我的子类 Clone 返回的是抽象基类的指针,那么在客户端调用时,就需要强制向下转换,这显然不是好的设计。2)如果我在子类的 Clone 函数返回自身指向自身的指针,那么一切正常,但是这样的话,子类 ConcretePrototype 中的 Clone 原型变成: virtual ConcreatePrototype* Clone() const; 而抽象基类的 Clone 原型则变为 virtual Prototype* Clone() const = 0; 于是出现子类的 Clone 返回值与父类的不同的情况,我们知道我们无法用返回值来进行重载的,当然这里不是重载,而是重写。但现在子类重写后的 Clone 和父类的 Clone 的返回值不同,是否应该这样做,这样做好不好?????
//网上的 Prototype 代码基本如下所示,只给出声明,Clone 返回值都是指向基类的指针:
1:
2: #pragma once
3:
4: // 虚拟基类,所有原型的基类,提供Clone接口函数
5: class Prototype
6: {
7: public:
8: Prototype(){}
9: virtual ~Prototype(){}
10:
11: virtual Prototype* Clone() = 0;
12: };
13:
14: // 派生自Prototype,实现Clone方法
15: class ConcreatePrototype1
16: : public Prototype
17: {
18: public:
19: ConcreatePrototype1();
20: ConcreatePrototype1(const ConcreatePrototype1&);
21: virtual ~ConcreatePrototype1();
22:
23: virtual Prototype* Clone();
24: };
25:
26: // 派生自Prototype,实现Clone方法
27: class ConcreatePrototype2
28: : public Prototype
29: {
30: public:
31: ConcreatePrototype2();
32: ConcreatePrototype2(const ConcreatePrototype2&);
33: virtual ~ConcreatePrototype2();
34:
35: virtual Prototype* Clone();
36: };
//设计模式书中,给出的迷宫示例基本如下,子类 Clone 返回的是指向自身的指针:
1:
2: #pragma once
3:
4: //enum Direction
5: enum Direction { North, South, East, West };
6:
7:
8: //abstract class
9: class MapSite
10: {
11: public:
12: virtual void Enter() = 0;
13: virtual MapSite* Clone() const = 0;
14: };
15:
16: //derive class
17: //Room
18: class Room : public MapSite
19: {
20: public:
21: Room(int roomNo);
22:
23: MapSite* GetSide(Direction) const;
24: void SetSide(Direction, MapSite*);
25:
26: virtual void Enter();
27:
28: //for prototype
29: Room(const Room& other);
30: virtual Room* Clone() const;
31:
32: private:
33: MapSite* _sides[4];
34: int _roomNumber;
35: };
36:
37: //Wall
38: class Wall : public MapSite
39: {
40: public:
41: Wall();
42:
43: virtual void Enter();
44:
45: //for prototype
46: Wall(const Wall& other);
47: virtual Wall* Clone() const;
48: };
49:
50: //Door
51: class Door : public MapSite
52: {
53: public:
54: Door(Room* r1 = 0, Room* r2 = 0);
55:
56: virtual void Enter();
57: Room* OtherSideRoom(Room*);
58:
59: //实现深拷贝, for prototype design
60: Door(const Door&);
61: virtual Door* Clone() const;
62:
63: virtual void Initialize(Room* , Room*);
64:
65: private:
66: Room* _room1;
67: Room* _room2;
68: bool _isOpen;
69: };
70:
71: //class Maze
72: class Maze
73: {
74: public:
75: Maze();
76:
77: void AddRoom(Room*);
78: Room* RoomNo(int) const;
79:
80: private:
81: //...
82: };
83:
84: //抽象工厂
85: class MazeFactory
86: {
87: public:
88: MazeFactory(){};
89:
90: virtual Maze* MakeMaze() const
91: {
92: return new Maze;
93: }
94: virtual Wall* MakeWall() const
95: {
96: return new Wall;
97: }
98: virtual Room* MakeRoom(int n) const
99: {
100: return new Room(n);
101: }
102: virtual Door* MakeDoor(Room* r1, Room* r2) const
103: {
104: return new Door(r1, r2);
105: }
106: };
107:
108: //Prototype 原型模式 工厂类
109: class MazePrototypeFactory : public MazeFactory
110: {
111: public:
112: MazePrototypeFactory(Maze*, Wall*, Room*, Door*);
113:
114: virtual Maze* MakeMaze() const;
115: virtual Room* MakeRoom(int) const;
116: virtual Wall* MakeWall() const;
117: virtual Door* MakeDoor() const;
118:
119: private:
120: Maze* _prototypeMaze;
121: Wall* _prototypeWall;
122: Room* _prototypeRoom;
123: Door* _prototypeDoor;
124: };
125:
126: //MazeGame, to create the Maze
127: class MazeGame
128: {
129: public:
130: //使用抽象工厂创建 Maze
131: Maze* CreateMaze(MazeFactory& factory);
132: };
133:
134: class BombeWall : public Wall
135: {
136: public:
137: BombeWall();
138: BombeWall(const BombeWall& other)
139: : Wall(other)
140: { };
141:
142: virtual Wall* Clone() const
143: {
144: return new BombeWall(*this);
145: }
146:
147: private:
148: bool _bomb;
149: };
1:
2: #include "Maze.h"
3:
4: //Room
5: Room::Room(int roomNo) : _roomNumber(roomNo) { }
6:
7: MapSite* Room::GetSide(Direction direction) const
8: {
9: return _sides[direction];
10: }
11: void Room::SetSide(Direction direction, MapSite* mp)
12: {
13: _sides[direction] = mp;
14: }
15: void Room::Enter()
16: {
17: //....
18: }
19: //for Room
20: Room::Room(const Room& other)
21: {
22: _sides[North] = other._sides[North];
23: _sides[South] = other._sides[South];
24: _sides[East] = other._sides[East];
25: _sides[West] = other._sides[West];
26: _roomNumber = other._roomNumber;
27: }
28: Room* Room::Clone() const
29: {
30: return new Room(*this);
31: }
32: //
33: //Wall
34: Wall::Wall()
35: {
36:
37: }
38: void Wall::Enter()
39: {
40: }
41:
42: //for prototype
43: Wall::Wall(const Wall& other)
44: {
45: }
46: Wall* Wall::Clone() const
47: {
48: return new Wall(*this);
49: }
50: //Door
51: Door::Door(Room* r1, Room* r2)
52: : _room1(r1), _room2(r2)
53: {
54: _isOpen = false;
55: }
56: void Door::Enter()
57: {
58: //....
59: }
60: Room* Door::OtherSideRoom(Room* rs)
61: {
62: ///.... 这个 。。。
63: return _room1;
64: }
65: //Door for prototype
66: Door::Door(const Door& other)
67: {
68: _room1 = other._room1;
69: _room2 = other._room2;
70: }
71: Door* Door::Clone() const
72: {
73: return new Door(*this);
74: }
75: void Door::Initialize(Room* r1, Room* r2)
76: {
77: _room1 = r1;
78: _room2 = r2;
79: }
80:
81: //
82: Maze::Maze()
83: {
84: }
85: void Maze::AddRoom(Room*)
86: {
87: //....
88: }
89: Room* Maze::RoomNo(int) const
90: {
91: //....
92: return 0;
93: }
94:
95: Maze* MazeGame::CreateMaze(MazeFactory& factory)
96: {
97: Maze* aMaze = factory.MakeMaze();;
98:
99: Room* r1 = factory.MakeRoom(1);
100: Room* r2 = factory.MakeRoom(2);
101: Door* aDoor = factory.MakeDoor(r1, r2);
102:
103: aMaze->AddRoom(r1);
104: aMaze->AddRoom(r2);
105:
106: r1->SetSide(North, factory.MakeWall());
107: r1->SetSide(East, aDoor);
108: r1->SetSide(South, factory.MakeWall());
109: r1->SetSide(West, factory.MakeWall());
110:
111: r2->SetSide(North, factory.MakeWall());
112: r2->SetSide(East, factory.MakeWall());
113: r2->SetSide(South, factory.MakeWall());
114: r2->SetSide(West, aDoor);
115:
116: return aMaze;
117: }
118:
119: //for Prototype Room, Door, Wall 等都必须实现 Clone()
120: //prototype MazeFactory
121: MazePrototypeFactory::MazePrototypeFactory(Maze* m, Wall* w, Room* r, Door* d)
122: {
123: _prototypeMaze = m;
124: _prototypeWall = w;
125: _prototypeRoom = r;
126: _prototypeDoor = d;
127: }
128: Maze* MazePrototypeFactory::MakeMaze() const
129: {
130: //return _prototypeMaze->Clone();
131:
132: return new Maze;
133: }
134: Room* MazePrototypeFactory::MakeRoom(int) const
135: {
136: return _prototypeRoom->Clone();
137: }
138: Wall* MazePrototypeFactory::MakeWall() const
139: {
140: return _prototypeWall->Clone();
141: }
142: Door* MazePrototypeFactory::MakeDoor() const
143: {
144: return _prototypeDoor->Clone();
145: }
146:
147: /*
148: // To Create Maze
149: Maze* MazeGame::CreateMaze()
150: {
151: //1):
152:
153: Maze* aMaze = new Maze;
154:
155: Room* r1 = new Room(1);
156: Room* r2 = new Room(2);
157: Door* theDoor = new Door(r1, r2);
158:
159: aMaze->AddRoom(r1);
160: aMaze->AddRoom(r2);
161:
162: r1->SetSide(North, new Wall);
163: r1->SetSide(East, theDoor);
164: r1->SetSide(South, new Wall);
165: r1->SetSide(West, new Wall);
166:
167: r2->SetSide(North, new Wall);
168: r2->SetSide(East, new Wall);
169: r2->SetSide(South, new Wall);
170: r2->SetSide(West, theDoor);
171:
172: return aMaze;
173: }//*/
1: //just for test, do nothing
2: #include "Maze.h"
3: #include
4:
5: int main()
6: {
7:
8: //for prototype
9: MazeGame game;
10: MazePrototypeFactory simpleMazeFactory(new Maze,
11: new Wall, new Room(2), new Door);
12: Maze* myProtoMaze = game.CreateMaze(simpleMazeFactory);
13:
14:
15: return EXIT_SUCCESS;
16: }
Class BombeWall : public Wall
{
public:
BombeWall();
BombeWall(const BombeWall& other)
: Wall(other)
{ };
virtual Wall* Clone() const
{
return new BombeWall(*this);
}
private:
bool _bomb;
};
这样,客户就不需要知道更加具体的子类。我由此判断,ConcretePrototype 应该返回自身。
所以自己的 Prototype 原型模式示例如下,感觉比较混乱,期待有简洁明了并且能准确说明该模式的代码展示:
1: //Prototype.h
2: #pragma once
3:
4: // 抽象基类, 所有原型的基类,提供Clone接口函数
5: class Prototype
6: {
7: public:
8: Prototype(){}
9: virtual ~Prototype(){}
10:
11: virtual Prototype* Clone() const = 0;
12:
13: //for test
14: virtual void PrintSelf() const { };
15: };
16:
17: //
18: // 派生自 Prototype, 实现 Clone() 方法
19: class ConcreatePrototype1 : public Prototype
20: {
21: public:
22: ConcreatePrototype1();
23: virtual ~ConcreatePrototype1();
24:
25: //必须实现拷贝构造函数,深拷贝
26: ConcreatePrototype1(const ConcreatePrototype1&);
27:
28: //调用拷贝构造函数
29: //virtual Prototype* Clone() const;
30:
31: //这里不太明白, 是应该返回基类指针, 还是返回自身
32: //网上的简略代码都是返回父类指针, 但太简略, 说明不了问题
33: //设计模式一书上的迷宫游戏,子类返回的都是自身,不过没给出父类的代码
34: //重写父类的纯虚函数,修改返回值是否是正确的做法???
35: virtual ConcreatePrototype1* Clone() const;
36:
37: virtual void PrintSelf() const;
38: };
39:
40: //
41: // 派生自 Prototype, 实现 Clone() 方法
42: class ConcreatePrototype2 : public Prototype
43: {
44: public:
45: ConcreatePrototype2(ConcreatePrototype1* p1);
46: virtual ~ConcreatePrototype2();
47:
48: //必须实现拷贝构造函数,深拷贝
49: ConcreatePrototype2(const ConcreatePrototype2&);
50:
51: //virtual Prototype* Clone() const;
52: virtual ConcreatePrototype2* Clone() const;
53:
54: virtual void PrintSelf() const;
55: private:
56: ConcreatePrototype1 *_pConcretePrototype1;
57: };
1: //for test, Product.h
2: #include "Prototype.h"
3: #include "ProductFactory.h"
4: #include
5: #include
6:
7: //产品类, 这里只是为了演示而已
8: class Product
9: {
10: public:
11: Product(){}
12: ~Product()
13: {
14: std::cout << std::endl << "~Product() ... " << std::endl;
15: std::vector
::iterator beg, temp;
16: for( beg = productVector.begin(); beg != productVector.end();)
17: {
18: temp = beg;
19: ++beg;
20: delete *temp;
21: }
22: //clear the productVector
23: productVector.clear();
24: std::cout << std::endl;
25: }
26:
27: void AddProduct(Prototype* prototype)
28: {
29: productVector.push_back(prototype);
30: }
31:
32: //注, 常成员函数, iterator 也必须声明为 常迭代器: const_iterator
33: void PrintProduct() const
34: {
35: std::cout << std::endl << "To display the member of Product---------- "
36: << std::endl;
37: std::vector
::const_iterator beg;
38: for(beg = productVector.begin(); beg != productVector.end(); ++beg)
39: {
40: (*beg)->PrintSelf();
41: }
42: }
43: private:
44: //just for test
45: std::vector
productVector;
46: };
47:
48: //定义类 MakeProduct, 用于创建 Product, 这里只是为了测试, 简单定义一下
49: class MakeProduct
50: {
51: public:
52: MakeProduct(){ }
53:
54: Product* CreateProduct(const ProductPrototypeFactory& pFactory)
55: {
56: Product* p = new Product;
57: p->AddProduct(pFactory.MakeProto1());
58: p->AddProduct(pFactory.MakeProto2());
59:
60: return p;
61: }
62: };
1: //for test, ProductFactory.h 这里只为结合一下工厂方法,没别的意图
2: #pragma once
3:
4: #include "Prototype.h"
5:
6: //这里只是为了测试,类结构类似于 设计模式书中 Maze 的示例
7: //工厂类, 这里只是为了结合一下工厂方法
8: class ProdutctFactory
9: {
10: //
11: virtual ConcreatePrototype1* MakeProto1() const
12: {
13: return new ConcreatePrototype1;
14: }
15: virtual ConcreatePrototype2* MakeProto2() const
16: {
17: return new ConcreatePrototype2(new ConcreatePrototype1);
18: }
19: };
20:
21: //用于展示 Prototype 原型模式的 工厂类
22: class ProductPrototypeFactory : public ProdutctFactory
23: {
24: public:
25: ProductPrototypeFactory(ConcreatePrototype1* p1,
26: ConcreatePrototype2* p2)
27: {
28: _proto1 = p1;
29: _proto2 = p2;
30: }
31:
32: //
33: virtual ConcreatePrototype1* MakeProto1() const
34: {
35: return _proto1->Clone();
36: }
37: virtual ConcreatePrototype2* MakeProto2() const
38: {
39: return _proto2->Clone();
40: }
41:
42: private:
43: ConcreatePrototype1* _proto1;
44: ConcreatePrototype2* _proto2;
45: };
//Prototype 的实现
1: //Prototype.cpp
2: #include "Prototype.h"
3: #include
4:
5: //ConcreatePrototype1
6: ConcreatePrototype1::ConcreatePrototype1()
7: {
8: std::cout << "ConcreatePrototype1()" << std::endl;
9: }
10:
11: ConcreatePrototype1::~ConcreatePrototype1()
12: {
13: std::cout << "~ConcreatePrototype1" << std::endl;
14: }
15:
16: ConcreatePrototype1::ConcreatePrototype1(const ConcreatePrototype1& p1)
17: {
18: //实现深拷贝
19: std::cout << "copy construction of ConcreatePrototype1" << std::endl;
20: }
21: //ConcreatePrototype1::Clone()
22: //Prototype* ConcreatePrototype1::Clone() const
23: ConcreatePrototype1* ConcreatePrototype1::Clone() const
24: {
25: return new ConcreatePrototype1(*this);
26: }
27: void ConcreatePrototype1::PrintSelf() const
28: {
29: std::cout << "I am ConcreatePrototype1"
30: << std::endl;
31: }
32: //
33: //ConcreatePrototype2
34: ConcreatePrototype2::ConcreatePrototype2(ConcreatePrototype1* p1)
35: {
36: std::cout << "ConcreatePrototype2()" << std::endl;
37: _pConcretePrototype1 = p1;
38: }
39:
40: ConcreatePrototype2::~ConcreatePrototype2()
41: {
42: std::cout << "~ConcreatePrototype2" << std::endl;
43: }
44:
45: ConcreatePrototype2::ConcreatePrototype2(const ConcreatePrototype2& p2)
46: {
47: //实现深拷贝
48: std::cout << "copy construction of ConcreatePrototype2" << std::endl;
49: _pConcretePrototype1 = p2._pConcretePrototype1;
50: }
51:
52: //ConcreatePrototype2::Clone()
53: //Prototype* ConcreatePrototype2::Clone() const
54: ConcreatePrototype2* ConcreatePrototype2::Clone() const
55: {
56: return new ConcreatePrototype2(*this);
57: }
58: void ConcreatePrototype2::PrintSelf() const
59: {
60: std::cout << "I am ConcreatePrototype2, with a member of ConcreatePrototype1"
61: << std::endl;
62:
63: std::cout << "And the member ConcreatePrototype1 is : ";
64: _pConcretePrototype1->PrintSelf();
65: }
//main, for test
1: //test.cpp
2: #include "Product.h"
3: #include
4:
5: int main()
6: {
7: ConcreatePrototype1* cp1 = new ConcreatePrototype1();
8: ConcreatePrototype2* cp2 = new ConcreatePrototype2(cp1);
9: ProductPrototypeFactory factory(cp1, cp2);
10:
11: MakeProduct makeProduct;
12: Product *product = makeProduct.CreateProduct(factory);
13:
14: //product do something
15: product->PrintProduct();
16:
17: delete product;
18:
19: return 0;
20: }