问题描述

目前的任务是实现一个FPS类游戏的各种角色(友军、敌军、平民和狗、猫、鸭子等动物)以及他们的各种行为(攻击、游泳等)。

设计方案一

很简单,只要实现一个角色超类,将角色的各种行为放入超类中,其他具体角色都继承次角色超类就可以了。类图如下所示(由于不同的角色有不同的外观,所以display设定为抽象方法,由子类自己实现)。

现在想想,这个设计有什么潜在的问题?对了,游戏开发完成后,你在享受游戏的乐趣的同时可能会发现竟然有一只猫在游泳,还有一只鸭子在向友军攻击...。这些是有悖常理,绝对不允许出现的。也许会有人想到一种解决方案,就是在子类中覆盖父类中相应的方法。但是这样一来,如果系统需要加入新的角色,程序员必须跟踪并可能覆盖fight和swim方法,永无止境的噩梦。必须更改设计方案。

设计方案二

针对上一个方案出现的问题,首先将会变化的行为(fight和swim)抽出来,各自放入单独的接口fightAction和swimAction中,只有具有此类行为的角色才会实现相应的接口。设计图如下:

稍稍动动脑筋就会发现,这种设计方案其实超傻。如果有成千上万种角色,就意味着程序员要重复编写成千上万次同样的代码。完全消除了代码复用的优势,几乎可以荣登史上最傻方案榜了。毫不犹豫,淘汰,必须更改方案。

设计方案三

在上一篇文章”面向对象设计原则”中的第一个原则是“封装变化”,这个原则可以理解为:“找出应用程序中需要变化的部分,把它们独立出来,不要和那些不需要变化的代码混在一起,以便以后可以轻易的改动或扩充此部分而不至影响到其他部分。”基于此,把角色的行为从角色中抽离出来。

为了实现“封装变化”,首先建立两组类,其中一个关乎fight行为的,另一个是关乎swim行为的,各自实现各自的行为,并将该两组类完全脱离角色类。

以上一切工作都是为了使得程序更具有弹性,易于扩展。所以,当然不能让子类来实现设定行为的方法,必须放在父类中。

”面向对象设计原则”中的第三个原则是“针对接口编程,而不是针对实现编程”,注意,此处讲到的接口并不是特指某个C#或java的接口,而是泛指实现某个超类性(类或接口)的某个方法。在此设计方案中利用接口代表行为,fight行为用FightAction接口代表,swim行为用SwimAction接口代表,这样角色本身不会负责实现某个行为,而是由专门的“行为类”(实现行为接口的类)来负责。设计方案如下图所示:

父类Character中用performFight和performSwim方法代替了方案一和方案二中的fight和swim方法。在performFight方法和performSwim方法中调用fightAction和swimAction中的fight和swim方法实现角色的行为。而每一个角色子类的fightAction和swimAction成员是在角色本身实例化的时候指定的。利用此方案实现的系统,决不会出现具有攻击行为的鸭子和会游泳的猫,同时也保证了系统的可扩展性,有新的行为加入的时候(如fightWithKnife)只需要添加一个新的行为类即可以实现。程序员甚至可以在父类中添加一个setFightAction(FightAction fightAction)或setSwimAction(SwimAction swimAction)方法来实现每一个角色在运行的时候动态的改变行为(如用枪攻击改为用刀攻击)。

总结

以上陈述的“设计方案三”利用的既是策略模式,有心的你也许会发现,该方案同样遵循了”面向对象设计原则”中的第二个原则是“多用组合,少用继承”。每一个角色都具有一个fightAction和swimAction用于委托处理fight行为和swim行为,这就是组合。“组合”不同于“继承”之处在于角色的行为不是继承来的,而是由行为对象组合而来。

引用策略模式的官方定义:“策略模式定义了算法族,分别封装起来,让它们直之间可以互相替换,此模式让算法的变化独立于使用算法的客户”。不难发现,该模式主要适用于不同客户(角色)使用不同策略(行为),并且策略本身将来可能通过不同方式实现,需要对客户隐藏具体策略的实现细节,完全独立的情况。策略模式提供了一种替代继承的方法,既保持了继承的优点(代码复用),同时也比继承更加灵活(算法独立,可任意扩展)。该模式还避免了多重条件语句的出现,使系统更易于扩展和维护。

转载于:https://www.cnblogs.com/NeeoMeng/articles/1119250.html

Head First设计模式读书笔记——策略模式相关推荐

  1. [设计模式学习笔记] -- 策略模式

    策略模式 定义了算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的客户. 举一个简单的例子来描述策略模式. 设计一款冷兵器时代士兵打仗的游戏,游戏内部设计要使用OO技术. ...

  2. 设计模式读书笔记-----模板方法模式

    首先我们先来看两个例子:冲咖啡和泡茶.冲咖啡和泡茶的基本流程如下: 所以用代码来创建如下: 咖啡:Caffee.java public class Coffee {void prepareRecipe ...

  3. 设计模式读书笔记-单件模式

    单件模式- 确保一个类只有一个实例,全局只有一个入口点. 类如下: public class Singleton { private static Singleton uniqueInstance; ...

  4. 设计模式读书笔记-----代理模式

    在我们实际生活中代理情况无处不在!你在淘宝上面买东西,你使用支付宝平台支付,卖家请物流公司发货.你请朋友帮你拿包裹,在这个过程汇总支付宝.物流公司.你朋友都扮演者"第三者"的角色在 ...

  5. 设计模式读书笔记-----备忘录模式

    个人比较喜欢玩单机游戏,什么仙剑.古剑.鬼泣.使命召唤.三国无双等等一系列的游戏我都玩过(现在期待凡人修仙传),对于这些游戏除了剧情好.场面大.爽快之外,还可以随时存档,等到下次想玩了又可以从刚开始的 ...

  6. Java-马士兵设计模式学习笔记-策略模式-模拟Comparable接口

    一.情况 1.目标:要在专门用于排序数据的DataSorter.java中实现对所有A类,B类,C类,D类等等的排序 2.初步想法:DataSorter.java的代码如下 public class ...

  7. 设计模式学习笔记——策略(Strategy)模式

    设计模式学习笔记--策略(Strategy)模式 @(设计模式)[设计模式, 策略模式, Stategy] 设计模式学习笔记策略Strategy模式 基本介绍 策略案例 类图 实现代码 Hand类 S ...

  8. 设计模式读书笔记-----工厂方法模式

    一.问题 在前一章<设计模式读书笔记-----简单工厂模式>中通过披萨的实例介绍了简单工厂模式.在披萨实例中,如果我想根据地域的不同生产出不同口味的披萨,如纽约口味披萨,芝加哥口味披萨.如 ...

  9. 大话设计模式读书笔记

    主题 概要 设计模式 大话设计模式读书笔记 编辑 时间 新建 20170423 序号 参考资料 1 大话设计模式 重新看了一遍设计模式,除了一些已经特别熟悉的模式,都自己敲了一遍代码,有些豁然开朗的感 ...

最新文章

  1. 程序连接不上mysql数据库文件_数据库问题(程序连接mysql错误)
  2. SAP MM 物料主数据里某字段看不到就是屏幕格式设置导致的?
  3. 开关电源反馈环路设计matlab,开关电源控制环路设计(初级篇).pdf
  4. AMD:“全民四核”大作战
  5. (6) Hibernate的集合映射
  6. ES报错:Connection reset by peer 解决经历
  7. _WIN32_WCE有什么用
  8. httpserver
  9. 立冬节气主题海报你知道怎么做了么?灵感给你,学起来!
  10. 网络测试工具 - QCheck
  11. nodejs+express 初学(一)
  12. ElasticSearch 状态查询Cat接口
  13. API多帐户跨平台MT4跟单系统如何选择服务器?
  14. 11月8日 课程设计幸运抽奖系统
  15. Greasy Fork 视频网页全屏脚本
  16. win10安装小爱同学 UWP
  17. 舱机器人尾巴毛茸茸_『新奇玩意』毛茸茸的机器人不仅可撸,还会摇尾巴
  18. Java版Spring Cloud B2B2C o2o鸿鹄云商平台--概述
  19. 缓存路由关联的两个生命周期activated和deactivated
  20. 国学大师林语堂献宝:英文学习八要诀

热门文章

  1. SpringBoot入门详解源码分析
  2. 数据结构-队列之链式队列
  3. springboot + redis
  4. 钽电容极性 钽电容极性判断图解
  5. AngularStrap -- Popovers
  6. apache beam_Apache Beam ML模型部署
  7. 康美药业财务造假给股民造成的损失,股民该怎么办?
  8. php 终止程序的方法——return、exit()、die()
  9. Live Migrate 操作 - 每天5分钟玩转 OpenStack(42)
  10. linux 算法函数,数据结构——算法之(012)( linux C 全部字符串操作函数实现)...