0


C++创建型模式之原型模式

C++ 原型模式(Prototype Pattern)

1. 解决的问题

原型模式(Prototype Pattern)是一种创建型设计模式,用于解决对象创建的问题,特别是在需要创建多个相似对象时,避免使用重复的构造代码。原型模式通过复制已有对象(原型)来创建新对象,而不是通过实例化一个类来创建。

2. 适用场景
  • 当系统需要创建多个相似对象,并且这些对象之间的差异只是部分属性值不同。
  • 当对象的创建过程比较复杂,并且通过复制现有对象可以简化创建过程。
  • 当需要避免使用子类的创建方式来生成对象时。
3. 模式的参与者角色
  • Prototype(抽象原型):声明一个克隆自身的接口。
  • ConcretePrototype(具体原型):实现克隆自身的操作。
  • Client(客户端):使用原型对象来克隆新的对象。
4. 示例代码

假设我们正在开发一个复杂的角色扮演游戏(RPG),游戏中有各种不同的角色,这些角色可以是玩家角色(Player)或敌人角色(Enemy)。每个角色都有不同的属性和能力,例如生命值、攻击力、防御力等。为了简化角色的创建过程,我们可以使用原型设计模式来复制现有的角色,并根据需要进行微调。

角色类图
  1. +----------------+
  2. | Prototype |
  3. |----------------|
  4. | + clone() |
  5. | + print() |
  6. +----------------+
  7. ^
  8. |
  9. +----------------+
  10. | Player |
  11. |----------------|
  12. | + clone() |
  13. | + print() |
  14. +----------------+
  15. ^
  16. |
  17. +----------------+
  18. | Enemy |
  19. |----------------|
  20. | + clone() |
  21. | + print() |
  22. +----------------+
代码
  1. #include <iostream>
  2. #include <string>
  3. #include <memory>
  4. #include <vector>
  5. // Prototype 接口
  6. class Prototype {
  7. public:
  8. virtual ~Prototype() {}
  9. virtual std::unique_ptr<Prototype> clone() const = 0;
  10. virtual void print() const = 0;
  11. virtual void setHealth(int health) = 0;
  12. virtual void setAttack(int attack) = 0;
  13. virtual void setDefense(int defense) = 0;
  14. };
  15. // BaseCharacter 抽象类
  16. class BaseCharacter : public Prototype {
  17. public:
  18. BaseCharacter(std::string name, int health, int attack, int defense)
  19. : name_(name), health_(health), attack_(attack), defense_(defense) {}
  20. void setHealth(int health) override { health_ = health; }
  21. void setAttack(int attack) override { attack_ = attack; }
  22. void setDefense(int defense) override { defense_ = defense; }
  23. void print() const override {
  24. std::cout << "Name: " << name_ << ", Health: " << health_
  25. << ", Attack: " << attack_ << ", Defense: " << defense_ << std::endl;
  26. }
  27. protected:
  28. std::string name_;
  29. int health_;
  30. int attack_;
  31. int defense_;
  32. };
  33. // Player 具体原型
  34. class Player : public BaseCharacter {
  35. public:
  36. Player(std::string name, int health, int attack, int defense)
  37. : BaseCharacter(name, health, attack, defense) {}
  38. std::unique_ptr<Prototype> clone() const override {
  39. return std::make_unique<Player>(*this);
  40. }
  41. };
  42. // Enemy 具体原型
  43. class Enemy : public BaseCharacter {
  44. public:
  45. Enemy(std::string name, int health, int attack, int defense)
  46. : BaseCharacter(name, health, attack, defense) {}
  47. std::unique_ptr<Prototype> clone() const override {
  48. return std::make_unique<Enemy>(*this);
  49. }
  50. };
  51. // 客户端代码
  52. int main() {
  53. // 创建原型对象
  54. auto playerPrototype = std::make_unique<Player>("Hero", 100, 20, 15);
  55. auto enemyPrototype = std::make_unique<Enemy>("Goblin", 50, 10, 5);
  56. // 创建角色列表
  57. std::vector<std::unique_ptr<Prototype>> characters;
  58. // 克隆玩家角色
  59. auto player1 = playerPrototype->clone();
  60. player1->setHealth(80); // 微调生命值
  61. characters.push_back(std::move(player1));
  62. auto player2 = playerPrototype->clone();
  63. player2->setHealth(90); // 微调生命值
  64. player2->setAttack(25); // 微调攻击力
  65. characters.push_back(std::move(player2));
  66. // 克隆敌人角色
  67. auto enemy1 = enemyPrototype->clone();
  68. characters.push_back(std::move(enemy1));
  69. auto enemy2 = enemyPrototype->clone();
  70. enemy2->setHealth(60); // 微调生命值
  71. enemy2->setAttack(15); // 微调攻击力
  72. characters.push_back(std::move(enemy2));
  73. // 打印所有角色信息
  74. for (const auto& character : characters) {
  75. character->print();
  76. }
  77. return 0;
  78. }
代码说明
  1. Prototype 接口定义了克隆和打印方法,以及设置角色属性的方法。
  2. BaseCharacter 是一个抽象类,实现了 Prototype 接口的通用部分,包括角色属性的设置和打印方法。
  3. PlayerEnemy 是具体原型类,继承自 BaseCharacter,并实现了 clone 方法。
  4. Clientmain 函数中创建了原型对象,并通过克隆这些原型对象来创建新的角色。客户端可以根据需要微调角色的属性。

总结

通过原型设计模式,我们可以轻松地复制现有角色,避免了重复的构造代码,并且可以根据需要对克隆的角色进行微调。这种模式在复杂的游戏场景中非常有用,特别是在需要创建多个相似角色时。

原型模式与 C++ 拷贝构造函数的相似性与不同点

相似性
  1. 对象复制:- 原型模式:原型模式的核心思想是通过复制已有对象来创建新对象。- 拷贝构造函数:拷贝构造函数用于从已有对象创建一个新对象。
  2. 避免重复构造:- 原型模式:避免了重复的构造代码,通过复制已有对象来创建新对象。- 拷贝构造函数:避免了重复的构造代码,通过复制已有对象来创建新对象。
  3. 对象状态的复用:- 原型模式:可以复用已有对象的状态来创建新对象。- 拷贝构造函数:可以复用已有对象的状态来创建新对象。
不同点
  1. 设计模式 vs. 语言特性:- 原型模式:是一种设计模式,属于面向对象编程的设计原则之一。- 拷贝构造函数:是 C++ 语言的一个特性,用于实现对象的复制。
  2. 接口定义:- 原型模式:通常定义一个 clone() 方法,用于克隆对象。- 拷贝构造函数:是类的构造函数,定义为 ClassName(const ClassName& other),用于从已有对象创建新对象。
  3. 实现方式:- 原型模式:可以由程序员显式实现 clone() 方法,并在方法内部调用拷贝构造函数或赋值操作符。- 拷贝构造函数:由编译器自动生成或由程序员显式实现。
  4. 灵活性:- 原型模式:提供了更灵活的对象复制机制,可以在运行时选择不同的原型进行复制。- 拷贝构造函数:是类的固有特性,无法在运行时选择不同的构造方式。
  5. 使用场景:- 原型模式:适用于需要创建多个相似对象,并且这些对象之间的差异只是部分属性值不同。- 拷贝构造函数:适用于任何需要从已有对象创建新对象的场景。
示例代码
  1. #include <iostream>
  2. #include <string>
  3. #include <memory>
  4. // 使用原型模式的类
  5. class Prototype {
  6. public:
  7. virtual ~Prototype() {}
  8. virtual std::unique_ptr<Prototype> clone() const = 0;
  9. virtual void print() const = 0;
  10. };
  11. class ConcretePrototype : public Prototype {
  12. public:
  13. ConcretePrototype(std::string name) : name_(name) {}
  14. std::unique_ptr<Prototype> clone() const override {
  15. return std::make_unique<ConcretePrototype>(*this);
  16. }
  17. void print() const override {
  18. std::cout << "ConcretePrototype: " << name_ << std::endl;
  19. }
  20. private:
  21. std::string name_;
  22. };
  23. // 使用拷贝构造函数的类
  24. class CopyConstructorExample {
  25. public:
  26. CopyConstructorExample(std::string name) : name_(name) {}
  27. CopyConstructorExample(const CopyConstructorExample& other) : name_(other.name_) {
  28. std::cout << "Copy Constructor Called" << std::endl;
  29. }
  30. void print() const {
  31. std::cout << "CopyConstructorExample: " << name_ << std::endl;
  32. }
  33. private:
  34. std::string name_;
  35. };
  36. int main() {
  37. // 原型模式示例
  38. auto prototype1 = std::make_unique<ConcretePrototype>("Prototype1");
  39. auto clone1 = prototype1->clone();
  40. clone1->print();
  41. // 拷贝构造函数示例
  42. CopyConstructorExample example1("Example1");
  43. CopyConstructorExample example2 = example1;
  44. example2.print();
  45. return 0;
  46. }

总结

  • 相似性:原型模式和拷贝构造函数都用于对象的复制,避免了重复的构造代码。
  • 不同点:原型模式是一种设计模式,通过 clone() 方法实现对象复制;拷贝构造函数是 C++ 语言特性,通过 ClassName(const ClassName& other) 实现对象复制。原型模式提供了更灵活的对象复制机制。

本文转载自: https://blog.csdn.net/joshua0137/article/details/143821436
版权归原作者 捕鲸叉 所有, 如有侵权,请联系我们删除。

“C++创建型模式之原型模式”的评论:

还没有评论