• C++设计模式---原型模式



    如何从工厂方法模式演变到原型模式

    假设你还是一名游戏程序员,上次三种类型怪物的工厂设计模式游戏策划非常喜欢,他接着又提出了新的需求,怪物在被玩家攻击以后,会损失一些状态(比如生命值、攻击力)。
    现在怪物有了一个新的能力,他能够克隆出一个新的自己,并且状态完全和自己一样。
    你该如何实现呢?

    如果我们仍然使用以前的工厂模式来实现这个功能,会遇到一个麻烦,那就是我们需要获取我们当前怪物对象的属性,然后再通过工厂模式实现创建新的对象。这样太麻烦了,因为我们通过构造函数,就可以构造出和他一模一样的对象出来。

    因此,我们只需要给父类增加拷贝构造,然后在子类中实现一个克隆接口就可以了。

    #include 
    using namespace std;
    namespace hjl_project1
    {
        //怪物父类
        class Monster
        {
        public:
            Monster(int life, int magic, int attack)
                : m_life(life), m_magic(magic), m_attack(attack)
            {
            }
            //父类实现其构造函数
            Monster(const Monster &m)
                : m_life(m.m_life), m_magic(m.m_magic), m_attack(m.m_attack)
            {
            }
            //增加一个克隆函数
            virtual Monster *clone() = 0;
            virtual ~Monster() {}
    
        protected:
            //怪物属性
            int m_life;
            int m_magic;
            int m_attack;
        };
        //亡灵类怪物
        class M_Undead : public Monster
        {
        public:
            M_Undead(int life, int magic, int attack)
                : Monster(life, magic, attack)
            {
                cout << "创建了一个亡灵类怪物" << endl;
            }
            M_Undead(const M_Undead &m)
                : Monster(m)
            {
                cout << "进行了一次克隆" << endl;
                printf("克隆对象的生命值:%d 魔法值:%d 攻击力%d\n", m.m_life, m.m_magic, m.m_attack);
            }
            Monster *clone()
            {
                return new M_Undead(*this);
            }
        };
        //元素类怪物
        class M_Element : public Monster
        {
        public:
            M_Element(int life, int magic, int attack)
                : Monster(life, magic, attack)
            {
                cout << "创建了一个元素类怪物" << endl;
            }
            M_Element(const M_Undead &m)
                : Monster(m)
            {
            }
            Monster *clone()
            {
                return new M_Element(*this);
            }
        };
        //机械类怪物
        class M_Mechanic : public Monster
        {
        public:
            M_Mechanic(int life, int magic, int attack)
                : Monster(life, magic, attack)
            {
                cout << "创建了一个机械类怪物" << endl;
            }
            M_Mechanic(const M_Undead &m)
                : Monster(m)
            {
            }
            Monster *clone()
            {
                return new M_Mechanic(*this);
            }
        };
    
        //实现工厂模式,代码省略
    }
    
    int main()
    {
    
        hjl_project1::Monster *p1 = new hjl_project1::M_Undead(400, 0, 1);
        hjl_project1::Monster *p2 = p1->clone();
        return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95

    在这里插入图片描述

    在这里插入图片描述


    原型模式的定义与特点

    原型模式是用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象。它属于创建型设计模式,用于创建重复的对象,同时又能保证性能(用这种方式创建对象非常高效)。

    优缺点:

    1. 原型模式实现了一个原型接口,该接口用于创建当前对象的克隆。当直接创建对象的代价比较大时,则采用这种模式。例如,一个对象需要在一个高代价的数据库操作之后被创建。我们可以缓存该对象,在下一个请求时返回它的克隆,在需要的时候更新数据库,以此来减少数据库调用。
    2. 原型模式不存在额外的等级结构,即不需要额外的工厂类。
    3. 有些情况下,产品类中存在克隆方法,也会给开发提供一些遍历,比如抽象类的怪物指针指向具体的怪物类,但是并不知道具体指向哪个怪物类,如果不使用原型模式来克隆,就需要先判断抽象类指针指向哪一个子类对象。
      在这里插入图片描述

    工厂方法模式与原型模式在创建对象时的异同点

    1. 这两种设计模式都不需要程序员知道所创建对象所属的类名。
    2. 工厂方法模式中的createMonster函数仍旧属于根据类名来生成对象。原型模式则是根据现有对象的构造函数来生产对象的拷贝。
  • 相关阅读:
    Standard part function
    docker对已经启动的容器添加目录映射(挂载目录)
    操作系统--进程概念
    分布式日志和链路追踪
    【Oracle数据库CRS-2878: Failed to restart resource ‘ora.chad‘】
    InnoDB存储引擎中锁的范围
    Python | GUI | tinker不完全总结
    进程信号之产生
    K8S:配置资源管理 Secret和configMap
    作为大厂面试官,原来这种学生最吃香!
  • 原文地址:https://blog.csdn.net/qq_52670477/article/details/126635035