程序设计模式——策略模式

Suwings Suwings     2022-08-07     639

关键词:

或许你听了之后会以为是一种策略选择方式,事实上

“策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化。”

  敬告:在阅读的文章时,请不要因为字多而跳着看,准确的说,希望你能慢慢阅读。

它有什么用?


 很多人喜欢在学某个新东西之前先了解他到底有什么用,其实这样也不是很好。

它可以让你的子类实现细节行为上的不同,也许我这样说有一点不理解,我用图片来进行表示就好了。

我们现在要实现一款简单的 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” 程序都用到了设计模式。

总的一句话,设计模式不是规则,而是你随时可以改变的模式。这也是很多设计模式书籍强调的一点。

 

不论对你是否有帮助,还是谢谢您的耐心查看。如有错误之处,还望指教。

 

设计模式---策略模式(代码片段)

策略模式为什么使用策略模式?策略模式包含角色策略模式的类图排序案例策略模式的优点策略模式的缺点适用场景源码分析策略模式的典型应用JavaComparator中的策略模式参考文章为什么使用策略模式?实现某一个功能有多条途径&#... 查看详情

设计模式——策略模式

一、策略模式案例一二、策略模式案例二:实现表单验证普通的表单验证功能实现:使用策略模式实现: 查看详情

设计模式——策略模式

一、策略模式案例一二、策略模式案例二:实现表单验证普通的表单验证功能实现:使用策略模式实现: 查看详情

设计模式——策略模式

一、策略模式案例一二、策略模式案例二:实现表单验证普通的表单验证功能实现:使用策略模式实现: 查看详情

设计模式之策略模式

  软件工程师都会学习设计模式,设计模式可以说是前人智慧与经验的结晶,虽然不是哪里都用得到,但是在合适的地方使用合适的设计模式,能够带来巨大的收益。我通过学习《headfirst设计模式》,逐渐掌握这些设计方法,... 查看详情

设计模式-策略模式

策略模式(strategypattern)策略模式(strategypattern):策略模式定义了算法族,分别封装起来,让它们之间可以相互替换,此模式让算法的变化独立于使用算法的客户。策略模式是针对一组算法,将每个算法封装到具有公共接口的独立的... 查看详情

设计模式之策略模式

策略模式属于对象行为型的设计模式定义:封装了一些列算法,它们之前可以相互替换,此模式使得算法的改变,不会影响到使用它们的客户端  策略模式有以下3个角色组成抽象策略类:所有策略类的父类,为所支持的... 查看详情

设计模式笔记-策略模式(代码片段)

设计模式笔记-策略模式文章目录设计模式笔记-策略模式1.策略模式2.常见写法3.常见框架中的策略模式1.策略模式策略模式(Strategy),定义了一组算法,将每个算法都封装起来,并且使它们之间可以互换,在使... 查看详情

设计模式——策略模式

  策略模式是指对一系列的算法定义,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化。最典型的就是客户打折算法的设计,不同等级的用户打折的力度也不一样,所以... 查看详情

设计模式(十四)——策略模式

设计模式(十四)——策略模式一、策略模式简介1、策略模式简介    策略模式定义了算法家族,分别封装起来,让不同算法之间可以互相替换,使算法的变化不会影响到使用算法的客户。    策略... 查看详情

java设计模式---策略模式(案例解析)

策略模式一、概念1、理解策略模式策略模式是一种行为型模式,它将对象和行为分开,将行为定义为一个行为接口和具体行为的实现。策略模式最大的特点是行为的变化,行为之间可以相互替换。每个if判断都可以理解为就是一... 查看详情

《javascript设计模式与开发实践》——策略模式

策略模式的定义是:定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换。 (1)使用策略模式计算奖金经过思考,我们想到了更好的办法——使用策略模式来重构代码。策略模式指的是定义一系列的算法... 查看详情

设计模式--策略模式

策略模式是指对一系列的算法定义,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化。策略模式的优点有:策略模式提供了管理相关的算法族的办法、策略模式提供了可以... 查看详情

设计模式1.策略设计模式

策略设计模式的定义:策略设计模式是把每一个算法封装到具有共同接口的独立类中,具体算法之间可以相互替换或者变化,这种变化不会影响客户端。关键词:【算法封装】【共同接口】【自由替换】策略设计模式的代码:1pu... 查看详情

设计模式之策略模式

策略模式定义,先看看维基上如何定义的:Thestrategypattern(alsoknownasthepolicypattern)isabehaviouralsoftwaredesignpatternthatenablesselectinganalgorithmatruntime.翻译如下:策略模式(又名代理模式)是一种行为软件设计模式在运行的过程中能动态的更... 查看详情

设计模式之策略模式

策略模式在策略模式(StrategyPattern)中,一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的context对象。策略对... 查看详情

设计模式之-策略模式

1、策略模式定义:将一系列算法封装起来,为了以后可以互相替换使用,由策略类和context组成,context接受用户信息,然后将请求委托给策略类(现实生活中,我们要去一个城市,交通方式就有:飞机、高铁、开车、大巴等,这... 查看详情

设计模式策略模式

  1、什么是策略模式?  策略模式,又叫算法簇模式,就是定义了不同的算法簇,并且之间可以互相替换,此模式算法的变化独立于使用算法的客户。2、策略模式有什么好处?  策略模式的好处在于你可以动态改变... 查看详情