1. 程式人生 > >設計模式之物件建立型 — prototype 原型模式

設計模式之物件建立型 — prototype 原型模式

本系列部落格示例程式碼均為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