Prototype 原型模式

      Prototype 原型模式的意图是,用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

      适用于:当一个系统应该独立于它的产品创建、构成和表示时,要使用 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:  }
    其中,MapSite 相当于上图中的 Prototype,Door、Room、Wall 相当于 ConcretePrototype1、ConcretePrototype2、ConcretePrototype3,当然,图中并没有画出 ConcretePrototype3。
书中没有给出 MapSite 在 Prototype 模式这一章的代码原型,所以我将其声明成了 Virtual MapSite* Clone() const = 0;
    不过对于继承自 Wall 等的更加具体的类,其返回值应该返回 Room。比如:
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:  }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值