C++设计模式_创建型模式_原型模式Prototype

本文记录原型设计模式。下面举例时,还是以游戏打怪为例给出例子。

原型模式使用场景

**原型模式:**通过一个对象克隆出多个一模一样的对象。

**使用场景:**打BOSS到一半血时,BOSS分裂为两个半血的BOSS。

对象的克隆需要调用类的拷贝构造函数,因为如果直接new 一个类,new出来的是新类,满血的BOSS类,所以new半血的BOSS类,只能通过拷贝构造函数来new;

cpp 复制代码
    class CMonster
    {
    public:
        CMonster(int left, int magic, int attack) 
            :m_life(left)
            , m_magic(magic)
            , m_attack(attack) 
        {}

		// 原型模式的克隆函数,使用拷贝构造函数实现
        CMonster(const CMonster& obj)
        {
			cout << "CMonster::CMonster(const CMonster& obj)" << endl;
            m_life = obj.m_life;
            m_magic = obj.m_magic;
			m_attack = obj.m_attack;
        }

        virtual ~CMonster()
        {
            cout << "CMonster::~CMonster()" << endl;
		}

        // 克隆函数
        virtual CMonster* clone() = 0;

		// 减少生命值 魔法值,攻击力
        virtual void reduce() = 0;

		// 输出当前的生命值、魔法值和攻击力
        virtual void printStatus() const = 0;

    protected:
        int m_life;  //生命值
        int m_magic; //魔法值
        int m_attack;  //攻击力
    };

    // 实现三个怪物类
    class CUndead : public CMonster
    {
    public:
        CUndead(int left, int magic, int attack)
            : CMonster(left, magic, attack)
        {

        }

        CUndead(const CUndead& obj)
            : CMonster(obj)
        {
			cout << "CUndead::CUndead(const CUndead& obj)" << endl;
        }

        // 克隆函数
        virtual CMonster* clone() override
        {
			return new CUndead(*this);// 调用拷贝构造函数
        }

        // 减少生命值 魔法值,攻击力
        virtual void reduce() override
        {
			m_life -= 10; // 假设每次减少10点生命值
			m_magic -= 5; // 假设每次减少5点魔法值
			m_attack -= 2; // 假设每次减少2点攻击力
        }

        virtual void printStatus() const override
        {
            cout << "Undead Status: Life = " << m_life 
                 << ", Magic = " << m_magic 
				<< ", Attack = " << m_attack << endl;
        }
    };

    class CElement : public CMonster
    {
    public:
        CElement(int left, int magic, int attack)
            : CMonster(left, magic, attack)
        {

		}
		// 调用拷贝构造函数
        CElement(const CElement& obj)
            : CMonster(obj)
        {
        }

        // 克隆函数原理:每次克隆,new CElement(*this);先会调用拷贝构造函数
		// 在拷贝构造函数中,调用了父类CMonster的拷贝构造函数,然后完成了成员变量的拷贝
        // 如果没有父类,则直接在本类的拷贝构造函数中完成成员变量的赋值操作
        virtual CMonster* clone() override
        {
            return new CElement(*this);
        }

        // 减少生命值 魔法值,攻击力
        virtual void reduce() override
        {
            m_life -= 20; // 假设每次减少10点生命值
            m_magic -= 15; // 假设每次减少5点魔法值
            m_attack -= 22; // 假设每次减少2点攻击力
        }

        // 输出状态
        virtual void printStatus() const override
        {
            cout << "Undead Status: Life = " << m_life
                << ", Magic = " << m_magic
                << ", Attack = " << m_attack << endl;
        }
    };

    void test()
    {
        // 创建一个亡灵类怪物
		CMonster* undead = new CUndead(100, 50, 30);
		undead->printStatus();
        // Undead Status: Life = 100, Magic = 50, Attack = 30
		undead->reduce();
		undead->printStatus();
        // Undead Status: Life = 90, Magic = 45, Attack = 28

		// 克隆一个亡灵类怪物
		CMonster* undeadClone = undead->clone();
        undeadClone->printStatus();
		// Undead Status: Life = 90, Magic = 45, Attack = 28
    }

克隆函数原理:基于现在的对象数据,拷贝一份新的对象。每次克隆,new CElement(*this);先会调用拷贝构造函数,在拷贝构造函数中,调用了父类CMonster的拷贝构造函数,然后完成了成员变量的拷贝。如果没有父类,则直接在本类的拷贝构造函数中完成成员变量的赋值操作

原型模式定义

用原型实例制定创建对象的种类,并且通过拷贝这些原型创建新的对象。

原型模式的两种角色,

Prototype(抽象原型类):CMonster类;

ConcretePrototype具体原型类,CEle CUndead 。

如果对象内部数据比较复杂多变,并且在创建对象的时候希望保持对象的当前状态,那么用原型模式显然比用工厂方法模式更合适。比如:BOSS的血量不断变化, 需要复制当前的BOSS,此时用原型更方便。

工厂方法模式和原型模式创建对象的共同点

1 都不需要知道所储行间对象所属的类名;工厂模式直接使用工厂来复制,原型模式直接使用clone()方法来复制。

2 工厂方法模式中的createMonster仍旧属于根据类名类生成的新对象;

3 原型模式中的clone() 是生成的当前对象的状态。

原型模式优缺点

1 如果创建新对象内部数据比较复杂多变,原型模式创建对象的效率可能会更高。

2 原型模式不存在额外的等级结构---原型模式不需要额外的工厂类;

3 clone() 接口的实现方法有多种,不用非要在clone()种拷贝构造。

4 有些情况下,产品类中存在一个克隆方法也会给开发提供一些便利。

使用全局方法

cpp 复制代码
// 使用全局方法创建CMonster
void Glb_CreateMonster(CMonster *pMonster)
{
	CMonster *p = nullptr;
	if (dynamic_cast<CUndead *> (pMonster) != nullptr)
	{
		cout << "这是CUndead 类型" << endl;
	}
	else if (dynamic_cast<CEle *>(pMonster) != nullptr)
	{
		cout << "这是CEle 类型" << endl;
	}
}

原型模式UML

相关推荐
解局易否结局11 分钟前
鸿蒙原生开发实战:用 Native C++ 与 OpenGL ES 构建高性能图形渲染管线
c++·elasticsearch·华为·harmonyos
学究天人13 分钟前
数学公理体系大全:第六章 选择公理的等价形式及证明
人工智能·线性代数·算法·机器学习·数学建模·概率论·原型模式
Starmoon_dhw31 分钟前
题解:P16108 「o.OI R-1」基础博弈练习题
c++·算法·图论
Kel1 小时前
管道、IPC、Socket:你以为的三种技术,其实是同一件事
javascript·设计模式·node.js
2601_949816351 小时前
C++内存对齐与结构体填充深度精讲:底层规则、内存裁剪、适配优化与工程避坑
开发语言·arm开发·c++
王老师青少年编程1 小时前
2026年全国青少年信息素养大赛复赛真题(算法应用主题赛C++初中组:带解析)(7月11日试卷一)【文末附答案和解析】
c++·真题·答案·复赛·2026年·青少年信息素养大赛·算法应用主题赛
大阿明2 小时前
C++智能指针与RAII机制精讲:彻底根治内存泄漏与野指针
java·jvm·c++
一生了无挂2 小时前
C++面向对象核心精讲:类、对象、封装、权限与生命周期全解析
java·jvm·c++
aaPIXa6222 小时前
C++ 用 Claude Code 的 defending-code-reference-harness:C/C++ 内存漏洞自动发现与修复 Pipeline
java·c语言·c++
郝学胜-神的一滴2 小时前
[简化版 GAMES 101] 计算机图形学 17:纹理技术从基础原理到多场景实战应用
c++·unity·游戏引擎·图形渲染·three.js·opengl·unreal