C++设计模式笔记(10) - Prototype 原型模式

  • C++设计模式笔记(09) - Abstract Factory 抽象工厂:
    https://blog.csdn.net/mofan6930/article/details/104637632
    *C++设计模式课件(11) - builder 生成器 | 构建器 模式:
    https://blog.csdn.net/mofan6930/article/details/105149305

  • 参考书籍:
    《设计模式:可复用面向对象软件的基础》
    设计模式:可复用面向对象软件的基础
    《Head First 设计模式》
    在这里插入图片描述

  • 参考课程:《C++设计模式》-李建忠
    李建忠-C++设计模式

0.“对象创建"模式.

➢通过“对象创建”模式绕开new,来避免对象创建(new) 过程中所导致的紧耦合(依赖具体类), 从而支持对象创建的稳定。它是接口抽象之后的第一步工作。

➢典型模式

  • Factory Method
  • Abstract F actory
  • Prototype
  • Builder

1.动机(Motivation).

➢在软件系统中,经常面临着“某些结构复杂的对象’的创建工作;由于需求的变化,这些对象经常面临着剧烈的变化,但是它们却拥有比较稳定一致的接口。

➢如何应对这种变化?如何向“客户程序(使用这些对象的程序)"隔离出“这些易变对象”,从而使得“依赖这些易变对象的客户程序”不 随着需求改变而改变?

2.模式定义.

使用原型实例指定创建对象的种类,然后通过拷贝这些原型来创建新的对象。
          ——《设计模式:可复用面向对象软件的基础》

3.结构(Structure)

C++设计模式笔记(10) - Prototype 原型模式_第1张图片

4.要点总结

C++设计模式笔记(10) - Prototype 原型模式_第2张图片➢要点:

  • Prototype模式同样用于隔离类对象的使用者和具体类型(易变类)之间的耦合关系,它同样要求这些“易变类”拥有“稳定的接口”。
  • Prototype模式对于“如何创建易变类的实体对象’采用“原型克隆’的方法来做,它使得我们可以非常灵活地动态创建“拥有某些稳定接口”的新对象一-所需 工作仅仅是注册一一个新类的对象(即原型),然后在任何需要的地方Clone。
  • Prototype模式中的Clone方法可以利用某些框架中的序列化来实现深拷贝。

➢原型的优点

  • 向客户隐藏制造新实例的复杂性。
  • 提供让客 户能够产生未知类型对象的选项。
  • 在某些环境下,复制对象比创建新对象更有效。

➢原型的用途和缺点

  • 在一个复杂的类层次中,当系统必须从其中的许多类型创建新对象时,可以考虑原型。
  • 使用原型模式的缺点:对象的复制有时相当复杂。

5.《Head First 设计模式》实例的C++实现

1.创建怪物

你设计的游戏中,需要怪兽的特征能够随着场景的变换而演化。例如在海底世界,创建海怪;在沙漠中,创建沙蝎怪物;在天空中,创建鸟人怪。由于创建怪物的过程比较复杂,需要在特定的类中统一复制创建,达到解耦的目的。
C++设计模式笔记(10) - Prototype 原型模式_第3张图片

2.代码演示(仅做参考)

怪物 抽象基类

//Monster.h
//怪物 抽象基类

#ifndef PROTOTYPEPATTERN_MONSTER_H
#define PROTOTYPEPATTERN_MONSTER_H

#include 

class Monster {
public:
    Monster() = default;
    ~Monster() = default;
    Monster(std::string scene, std::string name);

    [[nodiscard]] const std::string &getScene() const;
    void setScene(const std::string &scene);

    [[nodiscard]] const std::string &getName() const;
    void setName(const std::string &name);

    Monster clone();		//克隆函数
private:
    std::string m_scene;    //场景
    std::string m_name; 	//名字
};

#endif //PROTOTYPEPATTERN_MONSTER_H
//Monster.cpp

#include "Monster.h"
Monster::Monster(std::string scene, std::string name) {
    this->m_scene = scene;
    this->m_name = name;
}

const std::string &Monster::getScene() const {
    return m_scene;
}

void Monster::setScene(const std::string &scene) {
    m_scene = scene;
}

const std::string &Monster::getName() const {
    return m_name;
}

void Monster::setName(const std::string &name) {
    m_name = name;
}

Monster Monster::clone() {
    Monster monster;
    monster.setScene(this->m_scene);
    monster.setName(this->m_name);
    return monster;
}

海怪 类

//SeaMonster.h
// 海怪 类

#ifndef PROTOTYPEPATTERN_SEAMONSTER_H
#define PROTOTYPEPATTERN_SEAMONSTER_H


#include "Monster.h"

class SeaMonster : public Monster{
public:
    SeaMonster(std::string scene, std::string name);
    SeaMonster(std::string name);
};

#endif //PROTOTYPEPATTERN_SEAMONSTER_H
//SeaMonster.cpp

#include "SeaMonster.h"

SeaMonster::SeaMonster(std::string scene, std::string name) : Monster(scene, name) {
}

SeaMonster::SeaMonster(std::string name) {
    Monster("Sea", name);
}

沙蝎 类

//Scorpion.h
//沙蝎 类
#ifndef PROTOTYPEPATTERN_SCORPION_H
#define PROTOTYPEPATTERN_SCORPION_H


#include "Monster.h"

class Scorpion : public Monster{
public:
    Scorpion(std::string scene, std::string name);
    Scorpion(std::string name);
};

#endif //PROTOTYPEPATTERN_SCORPION_H
//Scorpion.cpp

#include "Scorpion.h"

Scorpion::Scorpion(std::string scene, std::string name) : Monster(scene, name) {

}

Scorpion::Scorpion(std::string name) {
    Monster("sand", name);
}

鸟人 类

//Birdy.h
//鸟人 类

#ifndef PROTOTYPEPATTERN_BIRDY_H
#define PROTOTYPEPATTERN_BIRDY_H

#include "Monster.h"

class Birdy : public Monster{
public:
    Birdy(std::string scene, std::string name);
    Birdy(std::string name);
};

#endif //PROTOTYPEPATTERN_BIRDY_H
//Birdy.cpp

#include "Birdy.h"

Birdy::Birdy(std::string scene, std::string name) : Monster(scene, name) {
}

Birdy::Birdy(std::string name) {
    Monster("sky", name);
}

怪物注册 类

//MonsterRegistry.h
// 怪物注册 类

#ifndef PROTOTYPEPATTERN_MONSTERREGISTRY_H
#define PROTOTYPEPATTERN_MONSTERREGISTRY_H

#include 
#include 
#include "Monster.h"

class MonsterRegistry {
public:
    MonsterRegistry();
    ~MonsterRegistry();

    Monster getMonster(std::string scene);

private:
    std::unique_ptr<std::unordered_map<std::string, Monster*>> monsterDB;
};

#endif //PROTOTYPEPATTERN_MONSTERREGISTRY_H
//MonsterRegistry.cpp

#include "MonsterRegistry.h"
#include "SeaMonster.h"
#include "Scorpion.h"
#include "Birdy.h"

MonsterRegistry::MonsterRegistry() {
    monsterDB = std::make_unique<std::unordered_map<std::string, Monster*>>();
    monsterDB->insert({"sea", new Monster{"sea","Sea Monster"}});
    monsterDB->insert({"sand", new Monster{"sand","Sand Scorpion"}});
    monsterDB->insert({"sky", new Monster{"sky","Birdy"}});
}

Monster MonsterRegistry::getMonster(std::string scene) {
    return monsterDB->find(scene)->second->clone();
}

MonsterRegistry::~MonsterRegistry() {
    for(auto msdb : *monsterDB){
        delete msdb.second;
        msdb.second = nullptr;
    }
}

怪物生成 类

//MonsterMarker.h
//怪物生成 类

#ifndef PROTOTYPEPATTERN_MONSTERMARKER_H
#define PROTOTYPEPATTERN_MONSTERMARKER_H

#include 
#include "MonsterRegistry.h"

class MonsterMarker {
public:
    MonsterMarker();
    ~MonsterMarker() = default;

    void makeRandomMonster(std::string scen);

private:
    std::unique_ptr<MonsterRegistry> registry;
    std::default_random_engine random{47};

};

#endif //PROTOTYPEPATTERN_MONSTERMARKER_H
MonsterMarker.cpp

#include 
#include "MonsterMarker.h"

MonsterMarker::MonsterMarker() {
    registry = std::make_unique<MonsterRegistry>();
}

void MonsterMarker::makeRandomMonster(std::string scene) {
    std::uniform_int_distribution u{5, 9};
    int count = u(random);
    std::string name = "";

    for(int i = 0; i<count; i++){
        Monster monster = registry->getMonster(scene);
        name = monster.getName();
    }
    std::cout << "You wiil fight with " << count << " " << name << " in " << scene << "." << std::endl;
}

测试代码

//main.cpp
//测试代码
#include 
#include "MonsterMarker.h"

int main()
{
    std::unique_ptr<MonsterMarker> monsterMake = std::make_unique<MonsterMarker>();

    std::cout << "You're in sea." << std::endl;
    monsterMake->makeRandomMonster("sea");

    std::cout << "You're in sky." << std::endl;
    monsterMake->makeRandomMonster("sky");

    std::cout << "You're in sand." << std::endl;
    monsterMake->makeRandomMonster("sand");
}

测试结果:
C++设计模式笔记(10) - Prototype 原型模式_第4张图片


欢迎关注公众号:c_302888524
发送:“设计模式:可复用面向对象软件的基础” 获取电子书
在这里插入图片描述

你可能感兴趣的:(设计模式,c++)