c/c++设计模式---策略模式

news/2024/10/5 23:20:33

一个具体范例的逐步重构

Fighter.h

#ifndef __RIGHTER__
#define __RIGHTER__////增加补充生命值道具(药品)
//enum ItemAddlife
//{
//    LF_BXD,  //补血丹
//    LF_DHD,  //大还丹
//    LF_SHD,  //守护丹
//};class ItemStrategy;  //类前向声明//战斗者父类
class Fighter
{
public:Fighter(int life, int magic, int attack) :m_life(life), m_magic(magic), m_attack(attack) {}virtual ~Fighter() {}public:/*void UseItem(ItemAddlife djtype) //吃药补充生命值{if (djtype == LF_BXD) //道具类型:补血丹{m_life += 200;//补充200点生命值//if (主角中毒)//{//    停止中毒状态,也就是主角吃药后不再中毒//}//if (主角处于狂暴状态)//{//    m_life += 400; //额外再补充400点生命值//    m_magic += 200; //魔法值也再补充200点//}}else if (djtype == LF_DHD) //道具类型:大还丹{m_life += 300;//补充300点生命值}else if (djtype == LF_SHD) //道具类型:守护丹{m_life += 500;//补充500点生命值}//.......其他的一些判断逻辑,略。。。。。。}*/public:void SetItemStrategy(ItemStrategy* strategy); //设置道具使用的策略void UseItem(); //使用道具int GetLife(); //获取人物生命值void SetLife(int life);  //设置人物生命值    protected:int m_life;int m_magic;int m_attack;ItemStrategy* itemstrategy = nullptr; //C++11中支持这样初始化
};//“战士”类,父类为Fighter
class F_Warrior :public Fighter
{
public:F_Warrior(int life, int magic, int attack) :Fighter(life, magic, attack) {}
};//“法师”类,父类为Fighter
class F_Mage :public Fighter
{
public:F_Mage(int life, int magic, int attack) :Fighter(life, magic, attack) {}
};#endif

Fighter.cpp

#include <iostream>
#include "Fighter.h"
#include "ItemStrategy.h"using namespace std;//设置道具使用的策略
void Fighter::SetItemStrategy(ItemStrategy* strategy)
{itemstrategy = strategy;
}//使用道具(吃药)
void Fighter::UseItem()
{itemstrategy->UseItem(this);
}//获取人物生命值
int Fighter::GetLife()
{return m_life;
}//设置人物生命值
void Fighter::SetLife(int life)
{m_life = life;
}

ItemStrategy.h

#ifndef _ITEMSTRATEGY__
#define _ITEMSTRATEGY__//道具策略类的父类
class ItemStrategy
{
public:virtual void UseItem(Fighter* mainobj) = 0;};//补血丹策略类
class ItemStrategy_BXD :public ItemStrategy
{
public:virtual void UseItem(Fighter* mainobj){mainobj->SetLife(mainobj->GetLife() + 200);  //补充200点生命值
    }
};//大还丹策略类
class ItemStrategy_DHD :public ItemStrategy
{
public:virtual void UseItem(Fighter* mainobj){mainobj->SetLife(mainobj->GetLife() + 300);  //补充300点生命值
#include <iostream>
#include "Fighter.h"
#include "ItemStrategy.h"#ifdef _DEBUG   //只在Debug(调试)模式下
#ifndef DEBUG_NEW
#define DEBUG_NEW new(_NORMAL_BLOCK,__FILE__,__LINE__) //重新定义new运算符
#define new DEBUG_NEW
#endif
#endif//#include <boost/type_index.hpp>
using namespace std;
//#pragma warning(disable : 4996) namespace _nmsp1
{    }int main()
{
/*Fighter* prole_war = new F_Warrior(1000, 0, 200); //这里没有采用工厂模式,如果主角很多,可以考虑采用工厂模式创建对象prole_war->UseItem(LF_DHD);delete prole_war;     *///创建主角Fighter* prole_war = new F_Warrior(1000, 0, 200);//吃一颗大还丹ItemStrategy* strategy = new ItemStrategy_DHD(); //创建大还丹策略prole_war->SetItemStrategy(strategy); //主角设置大还丹策略,准备吃大还丹prole_war->UseItem(); //主角吃大还丹//再吃一颗补血丹ItemStrategy* strategy2 = new ItemStrategy_BXD(); //创建补血丹策略prole_war->SetItemStrategy(strategy2);//主角设置补血丹策略,准备吃补血丹prole_war->UseItem(); //主角吃补血丹
delete strategy;delete strategy2;delete prole_war;return 0;
}
}

 

    }
};//守护丹策略类
class ItemStrategy_SHD :public ItemStrategy
{
public:virtual void UseItem(Fighter* mainobj){mainobj->SetLife(mainobj->GetLife() + 500);  //补充500点生命值
    }
};#endif

myproject.cpp

 

#include <iostream>
#include "Fighter.h"
#include "ItemStrategy.h"#ifdef _DEBUG   //只在Debug(调试)模式下
#ifndef DEBUG_NEW
#define DEBUG_NEW new(_NORMAL_BLOCK,__FILE__,__LINE__) //重新定义new运算符
#define new DEBUG_NEW
#endif
#endif//#include <boost/type_index.hpp>
using namespace std;
//#pragma warning(disable : 4996) namespace _nmsp1
{    }int main()
{/*Fighter* prole_war = new F_Warrior(1000, 0, 200); //这里没有采用工厂模式,如果主角很多,可以考虑采用工厂模式创建对象prole_war->UseItem(LF_DHD);delete prole_war;     *///创建主角Fighter* prole_war = new F_Warrior(1000, 0, 200);//吃一颗大还丹ItemStrategy* strategy = new ItemStrategy_DHD(); //创建大还丹策略prole_war->SetItemStrategy(strategy); //主角设置大还丹策略,准备吃大还丹prole_war->UseItem(); //主角吃大还丹//再吃一颗补血丹ItemStrategy* strategy2 = new ItemStrategy_BXD(); //创建补血丹策略prole_war->SetItemStrategy(strategy2);//主角设置补血丹策略,准备吃补血丹prole_war->UseItem(); //主角吃补血丹delete strategy;delete strategy2;delete prole_war;return 0;}
 策略(Strategy)模式
    //(1)一个具体实现范例的逐步重构
    //补血道具(药品):
      //a:补血丹:补充200点生命值
      //b:大还丹:补充300点生命值
      //c:守护丹:补充500点生命值
    //Fighter,F_Warrior,F_Mage
    //策略  设计模式的定义:定义一系列算法(策略类),将每个算法封装起来,让它们可以相互替换。换句话说,策略模式通常把一系列算法
       // 封装到一系列具体策略类中来作为抽象策略类的子类,然后根据实际需要使用这些子类。
    //策略类中的三种角色
    //a)Context(环境类):该类中维持着一个对抽象策略类的指针或引用。这里指Fighter类。
    //b)Stategy(抽象策略类):定义所支持的算法的公共接口,是所有策略类的父类。这里指ItemStrategy类。
    //c)ConcreteStrategy(具体策略类):抽象策略类的子类,实现抽象策略类中声明的接口。这里指ItemStrategy_BXD、ItemStrategy_DHD、ItemStrategy_SHD。
    //策略类的优点:
    //a)以扩展的方式支持对未来的变化,符合开闭原则。
      //遇到大量不稳定的if条件分支 或者switch分支,就要优先考虑是否可以通过策略模式来解决。策略模式是if,switch条件分支的杀手。
    //b)算法可以被复用。
    //c)策略模式可以看成是类继承的一种替代方案。通过为环境类对象指定不同的策略,就可以改变环境类对象的行为。
    //策略类的缺点:
    //a)导致引入许多新策略类;
    //b)使用策略时,调用者(main主函数)必须熟知所有策略类的功能并根据实际需要自行决定使用哪个策略类。
 
#include <iostream>
#include "Fighter.h"
#include "ItemStrategy.h"#ifdef _DEBUG   //只在Debug(调试)模式下
#ifndef DEBUG_NEW
#define DEBUG_NEW new(_NORMAL_BLOCK,__FILE__,__LINE__) //重新定义new运算符
#define new DEBUG_NEW
#endif
#endif//#include <boost/type_index.hpp>
using namespace std;
//#pragma warning(disable : 4996) namespace _nmsp1
{    class M_Undead //亡灵类怪物
    {public:void getinfo(){cout << "这是一只亡灵类怪物" << endl;}//......其他代码略
    };class M_Element //元素类怪物
    {public:void getinfo(){cout << "这是一只元素类怪物" << endl;}//......其他代码略
    };class M_Mechanic //机械类怪物
    {public:void getinfo(){cout << "这是一只机械类怪物" << endl;}//......其他代码略
    };//战士主角class F_Warrior{public:void attack_enemy_undead(M_Undead* pobj) //攻击亡灵类怪物
        {//进行攻击处理......pobj->getinfo(); //可以调用亡灵类怪物相关的成员函数
        }public:void attack_enemy_element(M_Element* pobj) //攻击元素类怪物
        {//进行攻击处理......pobj->getinfo(); //可以调用元素类怪物相关的成员函数
        }//其他代码略......
    };
}
namespace _nmsp2
{class Monster //作为所有怪物类的父类(抽象层)
    {public:virtual void getinfo() = 0; //纯虚函数virtual ~Monster() {} //做父类时析构函数应该为虚函数
    };class M_Undead :public Monster//亡灵类怪物
    {public:virtual void getinfo(){cout << "这是一只亡灵类怪物" << endl;}//......其他代码略
    };class M_Element :public Monster//元素类怪物
    {public:virtual void getinfo(){cout << "这是一只元素类怪物" << endl;}//......其他代码略
    };class M_Mechanic :public Monster//机械类怪物
    {public:virtual void getinfo(){cout << "这是一只机械类怪物" << endl;}//......其他代码略
    };//战士主角class F_Warrior{public:void attack_enemy(Monster* pobj) //攻击怪物
        {//进行攻击处理......pobj->getinfo(); //可以调用怪物相关的成员函数
        }//其他代码略......
    };
}int main()
{_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);//程序退出时检测内存泄漏并显示到“输出”窗口//第4章 策略(Strategy)模式//(1)一个具体实现范例的逐步重构//补血道具(药品)://a:补血丹:补充200点生命值//b:大还丹:补充300点生命值//c:守护丹:补充500点生命值//Fighter,F_Warrior,F_Mage//策略  设计模式的定义:定义一系列算法(策略类),将每个算法封装起来,让它们可以相互替换。换句话说,策略模式通常把一系列算法// 封装到一系列具体策略类中来作为抽象策略类的子类,然后根据实际需要使用这些子类。//策略类中的三种角色//a)Context(环境类):该类中维持着一个对抽象策略类的指针或引用。这里指Fighter类。//b)Stategy(抽象策略类):定义所支持的算法的公共接口,是所有策略类的父类。这里指ItemStrategy类。//c)ConcreteStrategy(具体策略类):抽象策略类的子类,实现抽象策略类中声明的接口。这里指ItemStrategy_BXD、ItemStrategy_DHD、ItemStrategy_SHD。//策略类的优点://a)以扩展的方式支持对未来的变化,符合开闭原则。//遇到大量不稳定的if条件分支 或者switch分支,就要优先考虑是否可以通过策略模式来解决。策略模式是if,switch条件分支的杀手。//b)算法可以被复用。//c)策略模式可以看成是类继承的一种替代方案。通过为环境类对象指定不同的策略,就可以改变环境类对象的行为。//策略类的缺点://a)导致引入许多新策略类;//b)使用策略时,调用者(main主函数)必须熟知所有策略类的功能并根据实际需要自行决定使用哪个策略类。//(2)依赖倒置原则:Dependency Inversion Principle,简称DIP//是面向独享设计的主要实现方法,同时 也是实现开闭原则的重要实现途径。//解释:高层组件不应该依赖于低层(具体实现类),两者都应该依赖于抽象层。//范例:工厂模式时,亡灵类M_Undead,元素类M_Element,机械类M_Mechanic。/*Fighter* prole_war = new F_Warrior(1000, 0, 200); //这里没有采用工厂模式,如果主角很多,可以考虑采用工厂模式创建对象prole_war->UseItem(LF_DHD);delete prole_war;     *//*//创建主角Fighter* prole_war = new F_Warrior(1000, 0, 200);//吃一颗大还丹ItemStrategy* strategy = new ItemStrategy_DHD(); //创建大还丹策略prole_war->SetItemStrategy(strategy); //主角设置大还丹策略,准备吃大还丹prole_war->UseItem(); //主角吃大还丹//再吃一颗补血丹ItemStrategy* strategy2 = new ItemStrategy_BXD(); //创建补血丹策略prole_war->SetItemStrategy(strategy2);//主角设置补血丹策略,准备吃补血丹prole_war->UseItem(); //主角吃补血丹delete strategy;delete strategy2;delete prole_war;*//*_nmsp1::M_Undead* pobjud = new _nmsp1::M_Undead();_nmsp1::F_Warrior* pobjwar = new _nmsp1::F_Warrior();pobjwar->attack_enemy_undead(pobjud); //攻击一只亡灵类怪物_nmsp1::M_Element* pobjelm = new _nmsp1::M_Element();pobjwar->attack_enemy_element(pobjelm); //攻击一只元素类怪物//资源释放delete pobjwar;delete pobjud;delete pobjelm;*/_nmsp2::Monster* pobjud = new _nmsp2::M_Undead();_nmsp2::F_Warrior* pobjwar = new _nmsp2::F_Warrior();pobjwar->attack_enemy(pobjud); //攻击一只亡灵类怪物
_nmsp2::Monster* pobjelm = new _nmsp2::M_Element();pobjwar->attack_enemy(pobjelm); //攻击一只元素类怪物//资源释放delete pobjwar;delete pobjud;delete pobjelm;return 0;
}

     

 

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hjln.cn/news/43122.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

Java (MyBatis-Plus 项目)

前沿 MyBatis-Plus 在使用这个时候的它通过提供简洁、强大的 API 和注解支持,简化了常见的数据库操作。以下是关于 MyBatis-Plus 中注解的解释和示例,理解和使用1. 实体类注解 @TableName:用于指定数据库表的名称。 @TableId:用于指定主键字段。 @TableField:用于指定非主…

【触想智能】工业显示器的分类与应用领域分析

工业显示器作为智能制造的一种重要设备之一,已经被广泛应用于各种工业领域。根据应用场景和特定需求,工业显示器分为很多不同的种类,本文将从这些分类及其应用领域进行分析。一、工业显示器分类1、工业液晶显示器:工业液晶显示器是目前最常见的一种工业显示器,它采用液晶技…

《DX12龙书》-第一个例程出现的报错:error: 应用程序请求的操作依赖于已缺失或不匹配的 SDK 组件;C2102问题

《DX12龙书》-第一个例程出现的报错 问题1:C2102问题 问题2:error: 应用程序请求的操作依赖于已缺失或不匹配的 SDK 组件《DX12龙书》|《Introduction to 3D Game Programming with DirectX 12》|《DirectX12 3D游戏开发实践》 个人电脑环境Window11;Visual Studio 2022出现…

Unity Text Mesh 穿透问题

0. 问题 在 3D 场景中使用 TextMesh 的时候,字体无法被遮挡,永远在最上层。虽然目前在场景中可以直接使用 TextMeshPro,但是实际开发的时候总会有各种各样的情况,可能是兼容老项目,也可能是想保持项目足够简单,不想引入 TextMeshPro。这里就只记录如何解决这一问题的方案…

Windows 允许空密码远程桌面

Windows 允许空密码远程桌面 开启远程修改策略 输入命令 secpol.msc 本地策略 -> 安全选项 -> 帐户:使用空密码的本地帐户只允许进行控制台登录本文来自博客园,作者:VipSoft 转载请注明原文链接:https://www.cnblogs.com/vipsoft/p/18241796

Redis之持久化

Redis持久化Redis 是内存数据库,如果不将内存中的数据库状态保存到磁盘,那么一旦服务器进程退出,服务器中的数据库状态也会消失。所以 Redis 提供了持久化功能!RDB(Redis DataBase)在指定的时间间隔内将内存中的数据集快照写入磁盘,也就是Snapshot快照,它恢复时是将快照文件…

MySql JOIN

MySql JOIN 背景 最近在做一些项目时需要对数据库进行简单的 select ,由于之前一直在做 HTML + JS + CSS 所有对数据库不是很了解,现在从 0 开始学习,每天学习一点,做个理解总结。有理解偏差欢迎留言指正。 简介 JOIN 用于根据两个或多个表之间关系,查询数据inner join 内…

presto 查询调度流程 (Coordinator Scheduler)

based on tag: 0.287 presto的 scheduler 是 SqlQueryScheduler 这个类控制的, 这个class主要是负责调度物理执行计划。调度具体的每个SqlStageExecution. 这个Stage可以当成Fragment的一个概念他会先把所有的stage创建一个schedule计划。一共有两种schedule计划,一个是all-at…