程序设计模式 —— 策略模式
或许你听了之后会以为是一种策略选择方式,事实上
“策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化。”
敬告:在阅读的文章时,请不要因为字多而跳着看,准确的说,希望你能慢慢阅读。
它有什么用?
很多人喜欢在学某个新东西之前先了解他到底有什么用,其实这样也不是很好。
它可以让你的子类实现细节行为上的不同,也许我这样说有一点不理解,我用图片来进行表示就好了。
我们现在要实现一款简单的 RPG 游戏,分别有 Knife(匕首者) Sworder (剑士) 两名玩家。
1.Knife 获得 Action 子类 Kinfe 的行为
2.Sowrder 获得 Action 子类 Sowrder 的行为
如何实现?
具体实现非常简单。你可以参考到任何一本 设计模式的书籍都可以找到关于“策略模式”的具体实现。
这里我们用C++语言实现:
1 class Action //动作 抽象基类 2 { 3 public: 4 Action() 5 { 6 7 }; 8 virtual void attack()=0; //纯虚函数,不同的子类必须实现动作的具体代码 9 virtual ~Action() 10 { 11 12 }; 13 };
然后我们现在需要派生几个 子类,表示不同的行为,注意注意,这里写的是职业的动作行为类,而不是职业类!只是代表这个职业的行为而已。
职业实现
职业:匕首刺杀者(暗杀者) 的具体动作行为类
1 class KnifeBeavior : public Action 2 { 3 // 匕首暗杀者 的攻击行为类 4 public: 5 virtual void attack () //实际上当然不止这一个行为,有很多,比如跑,躲闪,防御等等 6 { 7 // 用匕首 刺杀!! 具体代码 8 cout << "[KnifeBeavior] Knife attack!!!!!!!!!!!" << endl; 9 }; 10 virtual ~KnifeBeavior() 11 { 12 13 }; 14 KnifeBeavior() 15 { 16 17 }; 18 };
职业:单手剑士者(剑士) 的具体动作行为类
1 class SwordBeavior : public Action 2 { 3 //单手剑士者 攻击行为类 4 public: 5 virtual void attack() 6 { 7 // 用剑 斩杀!!!! 具体代码 8 cout << "[SwordBeavior] Sword attack!!!!!!!!!!!" << endl; 9 }; 10 SwordBeavior() 11 { 12 13 }; 14 virtual ~SwordBeavior() 15 { 16 17 }; 18 };
很好,我们就暂且只做这么两个职业的行为类。如果你想制作更多,你可以自己加入N个。
玩家实现
那么,我们现在要来实现玩家了!
首先我们要定义一个抽象的 实体类 ,这样的话我们就可以不需要管理具体而直接使用。他是一个基类,这里没有定义什么纯虚函数,只是方便举例。
1 class Entity 2 { 3 /* 4 注意: 5 这是实体类,准确的说,你不知道这个到底是什么,可能是人,也有可能是 怪兽 6 这个实体类并不是很抽象,这只是仅仅为了写例子,请勿直接用于您的项目代码之间。 7 */ 8 public: 9 Action *action; //动作类,用于存放不同的动作,详情看下面 10 int HP; //实体的HP 11 string EntityId; //实体的ID 12 13 void setHP(int HP) //设置HP 14 { 15 this->HP = HP; 16 }; 17 void setEntityId(string & EntityId)//设置实体的ID 18 { 19 this->EntityId = EntityId; 20 }; 21 /*主要看看这里下面的方法*/ 22 void setAction(Action * behaver)//给本类 赋值一个行为 23 { 24 if(this->action != NULL)delete action;//释放掉原来的 25 this->action = behaver; 26 }; 27 virtual ~Entity()//记得到时候释放 28 { 29 delete action; 30 }; 31 virtual void attack() //实体攻击! 32 { 33 //这样的话,我们就不需要知道具体动作类是什么,反正调用就对了 34 Entity::action->attack(); 35 }; 36 Entity(){ 37 this->action = NULL; //初始化 38 } 39 };
现在,我们分别来实现 Knife 和 Sworder 类。
1 /*这是一个 “匕首刺杀者 职业” 的一个类 */ 2 class Knife : public Entity 3 { 4 public: 5 Knife() 6 { 7 cout << "Knife !!!" << endl; 8 //实例化一个 匕首刺杀者 的行为给 本类(Knife) 9 Entity::setAction(new KnifeBeavior());//调用父类的方法 10 }; 11 virtual ~Knife(){}; 12 }; 13 14 /*这是一个 “单手剑士者 职业” 的一个类 */ 15 class Sworder : public Entity 16 { 17 public: 18 Sworder() 19 { 20 cout << "Sworder !!!" << endl; 21 //实例化一个 单手剑士 的行为给 本类(Sworder) 22 Entity::setAction(new SwordBeavior());//调用父类的方法 23 }; 24 virtual ~Sworder(){}; 25 };
很好,基本上都差不多了。不过......
“故事情节:你作为 Pattern Art Online (VR)的高级玩家,实际上也是一名响当当的 安全专家,于是你入侵了 Pattern Art Online (VR)的游戏服务器,并且加入了如下代码”
1 //这是一个作弊者,职业为 “未知职业” 2 class UnKnow : public Entity 3 { 4 public: 5 //这个预先开始的时候 是没有任何职业的 6 UnKnow() 7 { 8 cout << "UnKnow, System admin !!!" << endl; 9 }; 10 virtual ~UnKnow(){}; 11 };
“你暗暗自喜,虽然看起来这个类什么用都没有,但是你以后就会发现。。。”
实际上你将会发现,使用策略模式之后,复用原先的代码将是多么的简单。
嗯,是时候改开始游戏了
”现在,你作为 Pattern Art Online (VR) 的高级玩家,你需要开战了,在你无比强大的剑术下你经过层层迷宫以及各种小BOSS,虽然MP已经不多了,但是你依然坚持作战。
于是你勇敢的推开了 BOSS 终极大门,进入了 BOSS 房间。”
“----Game AI: BOSS 房间闯入者入侵,反抗机制启动----”
1 #include "Strategy.h" 2 3 int main(int argc, char const *argv[]) 4 { 5 /*游戏开始*/ 6 /*你作为 Pattern Art Online 的高级玩家,现在正在寻找 第99层的BOSS ....*/ 7 cout << "Find Boss!!!" << endl;//发现Boss 卧槽 8 /*朋友们 快来帮助我,赶快上线啊!*/ 9 10 /* ---朋友边嗦方便面边穿衣服边打开微博边打开博客园边登录--- */ 11 12 /*创建一个 匕首刺杀者 职业*/ 13 Entity *knife = new Knife(); 14 /* 用匕首刺杀吧!!!哈哈哈哈~~~~*/ 15 knife->attack(); 16 /*与此同时,你的朋友 剑士 来了*/ 17 Entity *sworder = new Sworder(); 18 /*用 你的锋利的剑刺杀吧~~~~~ Ex 咖喱棒!!!!*/ 19 sworder->attack(); 20 /*什么?对方还没死?*/ 21 /* 没办法,看起来只能使用杀手锏了。。。*/ 22 /*好,接下来我们的作弊者出现了!*/ 23 Entity *unKnower = new UnKnow(); //你只需要创建一个子类,无需其他操作,即可实现很多 24 /*我们先 给作弊者 转变职业,变成“匕首刺杀者”*/ 25 unKnower->setAction(new KnifeBeavior()); //这里将是代码复用 26 /*刺杀吧!*/ 27 unKnower->attack(); 28 /*现在,切换战术,作弊天术:“转变职业!”。立即成为 “剑士职业”*/ 29 unKnower->setAction(new SwordBeavior()); //这里将是代码复用 30 /*拿出你的剑,给它最后一击!!!!! 绝望吧!*/ 31 unKnower->attack(); 32 /*哈哈哈哈哈哈哈哈哈哈哈哈!!!!*/ 33 cout << "Boss died! Your win! " << endl; 34 /* ---成功通关--- */ 35 cout << "Ah hhhhhhhhhhhhhh~~~" << endl; 36 /* ---房间结束,游戏结束--- */ 37 38 cin.get(); //这一行无视 39 40 delete knife; 41 delete sworder; 42 delete unKnower; 43 return 0; 44 }
输出:
“随着 成功通关的声音出现,你松了一口气,看起来,我真是太厉害了,但是游戏管理员似乎发现了你使用了 unkonw... 并且提交了一份起诉表送到了北京市最高人民法院”
“今晚,你欢快的庆祝了之后,累了该休息的时候,门铃响了。。。 外面传来了一声:'开门开门!!!查水表!!' ”。
就这样结束了?
"随着法院的判定,你成功的获得了 五个月的牢房游 和 免费的衣物 和 五年内禁止接触互联网的决定"
"第二天,报纸上写上头条:《天才黑客少年(少女/猥琐大叔/老爷/青年)入侵 Pattern Art Online (VR)游戏篡改服务端代码被判》"
当然重点不在于你的死活,而是在于我们的策略模式到底怎么样。看起来是不错的样子?也许你完全理解了?不理解建议回头去了解了解代码。
下面重复一遍:”策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化。“
我们的各种不同的行为就是 算法,我们将算法都封装了,然后可以给任何需要用的人去用。
这是百度百科的UML图:
最后
如果你会状态模式,你可能会发现他们的相似点,具体可以看看我的博客,建议加以区分。
同时没事就巩固一下概念,或者自己写一个。
但是要注意的一点,不是说有了这个模式,就必须要加进去使用,程序会更棒。
设计模式要与你的程序相互和谐,不能写个 “HelloWorld” 程序都用到了设计模式。
总的一句话,设计模式不是规则,而是你随时可以改变的模式。这也是很多设计模式书籍强调的一点。
不论对你是否有帮助,还是谢谢您的耐心查看。如有错误之处,还望指教。
转载于:https://www.cnblogs.com/suwings/p/5925618.html
程序设计模式 —— 策略模式相关推荐
- 李建忠设计模式——策略模式Strategy
目录 1.策略模式定义 1.动机 2.模式定义 3.结构 2.实现例子 1.问题描述 2.代码实现 3.要点总结 4.参考 1.策略模式定义 1.动机 软件构建过程中,某些对象使用的算法可能多种多样, ...
- 设计模式-策略模式(Strategy)-Java
设计模式-策略模式(Strategy)-Java 目录 文章目录 1.前言 2.示例案例-电影票打折方案 3.策略模式概述 3.1.策略模式定义 3.2.策略模式结构 3.3.策略模式结构图中角色 3 ...
- Python设计模式-策略模式
Python设计模式-策略模式 代码基于3.5.2,代码如下; #coding:utf-8 #策略模式class sendInterface():def send(self,value):raise ...
- 关于设计模式——策略模式-Strategy Pattern
文章目录 1 策略模式 1.1 模拟鸭子 1.2 设计原则 1.3 整合行为 1.4 模拟鸭子代码的代码 1.5 动态设定行为 1.6 重新查看整体 1.7 继承和组合 1.8 总结 1.9 优劣期间 ...
- [设计模式] ------ 策略模式
策略模式 它定义了算法家族,分别封装起来,让他们直接可以互相替换,此模式让算法的变化,不会影响到使用算法的客户 其实很简单,可能很多人都用到了,只不过还不知道这就是策略模式而已. 比如定义一个接口A, ...
- java 策略模式 促销_java设计模式——策略模式
一. 定义与类型 定义:针对一组算法,将每一种算法都封装到具有共同接口的独立的类中,从而是它们可以相互替换.策略模式的最大特点是使得算法可以在不影响客户端的情况下发生变化,从而改变不同的功能.当代码中 ...
- 并行程序设计模式--Master-Worker模式
#Copy from http://www.cnblogs.com/Leo_wl/p/5319735.html Master-Worker模式 并行程序设计模式–Master-Worker模式 简介 ...
- Springboot 使用设计模式- 策略模式
前言 直白点,什么场景我们需要使用到设计模式- 策略模式. 在平常的springboot项目里面做CRUD,我们的习惯性基本是 一个mapper,一个service,一个serviceImpl. 但是 ...
- 15. 星际争霸之php设计模式--策略模式
题记 ============================================================================== 本php设计模式专辑来源于博客(jy ...
最新文章
- python字典添加主键_python 字典相关操作
- jenkins 命令行 CLI jenkins-cli.jar
- mysql数据传输完整性_mysql – 处理数据库完整性
- 2017年网易校招题 买苹果
- 独立磁盘冗余阵列:RAID
- 微信小程序 | 实现活动报名登记
- 云计算机是什么技术,什么是云计算技术?
- 使用Tensorflow2.0实现roi-Align和FPN
- gnuradio3.8.2的安装步骤
- 在短视频源码开发中,移动端音视频加密、防盗播实现方案
- 谈谈成功,你离成功有多远?施瓦辛格励志演讲分享(配中文翻译)
- 3dMax模型数据转cesium Gltf模型
- EPP-常见问题总结
- Thinkpad 笔记本电源状态指示灯
- zuul+SpringSession的session不一致问题
- ofo 破解 android ios 版 (类似 wifi 万*能*钥*匙 )
- 关键帧提取——RCC提取关键帧(1)
- 实战中icon 的使用
- argparse简化版图片教程
- BDD测试框架Spock概要
热门文章
- IDEA 打包 spark 程序 并在远程 hadoop HA 上运行测试
- Android加密工具类,Android AES加密工具类分享
- 皮秒 纳秒 微秒 毫秒 秒 ps、ns、us、ms、s 时间单位之间的换算
- 错误MSB4025:无法加载项目文件。根级别的数据无效。第1行,第1位。
- 已经一点经纬度和距离,计算另一点的经纬度
- Python环境下OpenCV视频流的多线程处理方式
- 25人赛跑问题-得出前三名
- python称号_Python成为2018年度编程语言,遥遥领先于其他语言
- 组网胖模式_胖瘦AP组网优劣对比
- scrapy爬取京东笔记本电脑数据并进行简单处理和分析