設計模式之物件建立型 — prototype 原型模式
阿新 • • 發佈:2019-02-01
本系列部落格示例程式碼均為C++程式碼,個人之言,請持懷疑態度參考。如有錯誤,歡迎留言指正。
什麼是原型模式
建立一個應用需要由很多元件構成,原型模式旨在通過給工廠傳遞原型例項,讓後工廠通過拷貝構造這些原型來元件應用。
舉個例子:在abstract模式中有貪吃蛇遊戲的例子。他每實現一種模式,都需要寫一個snakeFactory的子類。如果用原型模式的話則不需要建立辣麼多子類,通過傳遞不同的原型就可以了。
示例程式碼
示例程式碼有點長,建議把程式碼直接拷貝到VS專案中除錯 。
//maze.h檔案
#ifndef MAZE_H
#define MAZE_H
#include <iostream>
using namespace std;
/************************************************************************/
/* 這是一個簡單的迷宮遊戲的例子,程式碼只是示意設計模式 */
/************************************************************************/
//迷宮類
class Maze
{
public:
Maze();
~Maze();
Maze(const Maze &); //拷貝構造 這裡需要用深拷貝,而不是使用預設的拷貝建構函式
virtual Maze* clone(); //克隆函式,一些克隆出例項的一個副本 並且返回其指標
virtual void dis();
private:
};
//房間類
class Room
{
public:
Room();
~Room();
Room(Room & other);
virtual Room* clone();
virtual void dis();
private:
};
//牆壁類 預設為牆壁1號,也是牆壁的基類;這個可以根據實際設計,也可以寫成一個抽象類
class Wall
{
public:
Wall();
~Wall();
Wall(Wall &other);
virtual Wall* clone();
virtual void dis();
private:
};
//繼承牆壁1號 並且改進 成為 牆壁2號
class Wall_2:public Wall
{
public:
Wall_2();
~Wall_2();
//子類必須重新實現Clone 並實現相應的拷貝構造器
Wall_2(const Wall_2 &other);
Wall *clone();
void init(int a,int b); //初始化並非必須的,根據情況實現
void dis();
private:
};
//迷宮的抽象工廠
class MazeFactory
{
public:
MazeFactory();
~MazeFactory();
virtual Wall* makeWall() const=0;
virtual Room *makeRoom() const=0;
virtual Maze *makeMaze() const = 0;
private:
};
class Pro_MazeFactory: public MazeFactory
{
public:
Pro_MazeFactory();
~Pro_MazeFactory();
/*以原型為引數的構造器*/
Pro_MazeFactory(Wall*, Room *,Maze *);
/*重寫基類方法*/
Wall* makeWall() const;
Room *makeRoom() const;
Maze *makeMaze() const;
private:
Wall * _pro_wall;
Room *_pro_room;
Maze *_pro_maze;
};
//客戶的類,用來組織遊戲邏輯
class Game
{
public:
Game();
~Game();
Maze * creat_game(MazeFactory& factory);
private:
};
#endif
//maze.cpp檔案
#include "maze.h"
MazeFactory::MazeFactory()
{
}
MazeFactory::~MazeFactory()
{
}
Room::Room()
{
}
Room::Room(Room & other)
{
/**拷貝構造的程式碼**/
}
Room* Room::clone()
{
return new Room(*this);
}
void Room::dis()
{
cout << "我是房間1號" << endl;
}
Room::~Room()
{
}
Wall::Wall()
{
}
Wall::Wall(Wall &other)
{
/**拷貝構造的程式碼**/
}
Wall* Wall::clone()
{
return new Wall(*this);
}
void Wall::dis()
{
cout << "我是Wall 1號" << endl;
}
Wall::~Wall()
{
}
Maze::Maze()
{
}
Maze::Maze(const Maze &)
{
/**拷貝構造的程式碼**/
}
Maze::~Maze()
{
}
Maze* Maze::clone()
{
return new Maze(*this); //呼叫拷貝構造器
}
void Maze::dis()
{
cout << "我是迷宮1號" << endl;
}
Wall_2::Wall_2()
{
}
Wall_2::Wall_2(const Wall_2 &other)
{
/****/
}
Wall * Wall_2::clone()
{
return new Wall_2(*this);
}
Wall * Wall_2::init(int a,int b)
{
/*做一些初始化工作*/
}
Wall_2::~Wall_2()
{
}
void Wall_2::dis()
{
cout << "我是牆壁2號" << endl;
}
Game::Game()
{
}
Game::~Game()
{
}
Maze * Game::creat_game(MazeFactory& factory)
{
Maze *amaze=factory.makeMaze();
Room *room = factory.makeRoom();
Wall* wall = factory.makeWall();
/* 其他的邏輯程式碼 */
amaze->dis();
room->dis();
wall->dis();
return amaze;
}
Pro_MazeFactory::Pro_MazeFactory()
{
}
Pro_MazeFactory::Pro_MazeFactory(Wall* w, Room * r,Maze *m)
{
_pro_room = r;
_pro_wall = w;
_pro_maze = m;
}
Wall* Pro_MazeFactory::makeWall() const
{
return _pro_wall->clone();
}
Room * Pro_MazeFactory::makeRoom() const
{
return _pro_room->clone();
}
Maze * Pro_MazeFactory::makeMaze() const
{
return _pro_maze->clone();
}
Pro_MazeFactory::~Pro_MazeFactory()
{
}
//main.cpp檔案
#include <iostream>
using namespace std;
#include "maze.h"
int main()
{
Game game;
Pro_MazeFactory factory(new Wall, new Room, new Maze); //傳遞原型例項給工廠 這是第一種組合 迷宮1號 牆壁1號 房間1號
Maze* m = game.creat_game(factory);
cout << "---完美分割線----" << endl;
Pro_MazeFactory factory_2(new Wall_2, new Room, new Maze); //傳遞原型例項給工廠 這是第二種組合 迷宮1號 牆壁2號 房間1號
Maze *m_2 = game.creat_game(factory_2);
getchar();
return 0;
}
提示:示例程式碼是沒有提供 記憶體釋放的方法的 也就是說這份程式碼是有記憶體洩漏的缺陷,不過作為示例程式碼,旨在理解何為原型模式。如果在實際專案中 必須提供釋放記憶體的程式碼 。
適用性
- 當實力化的類是在執行時刻指定時,比如通過動態裝載。
- 當一個類的例項只能有幾種不同的狀態組合中的一種時。
效果
原型模式的效果有很多是與abstract、builder重疊的
他的一些獨特的特點 :
- 可以動態的增刪在執行時刻
- 無需通過新建子類就可以得到新的類,極大的減少了系統所需要類的數目。
- 允許例項化複雜的、使用者定義的結構。比如,每次多次使用的特定子電路,遊戲中多次使用的特定場景等。
實現
實現在程式碼中已經做過註釋了,可以做如下概括:
- 實現克隆操作
- 初始化克隆物件
- 使用一個原型管理器,當系統中的原型數目不確定時,要保持一個可用原型的登錄檔。這個在程式碼示例中並沒實現,自己根據需要實現就可以了。
轉載請註明出處 小風code www.breeziness.cn