Head First设计模式读书笔记——策略模式

问题描述

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

设计方案一

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


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

设计方案二

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


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

设计方案三

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

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

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

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


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

总结

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

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

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

centos+bond+bridge+docker(ssh容器)固定ip实现测试环境(一)

硬件:R730交换机:H3C Switch S5120-28P-SI系统:centos7#nmtuihttp://568273240.blog.51cto.com/802.3ad为LACP模式交换机部分:# systemctl restart network可以多重启几遍试下。http://568273240.blog.51cto.com/注意:…

简单线性回归算法

为什么80%的码农都做不了架构师?>>> /*** 简单线性回归算法* param array y轴数据* param array x轴数据* returns array(slope,intercept,r2)*/ function linearRegression(y, x) {var lr {};var n y.length;var sum_x 0;var sum_y 0;var sum_xy …

模拟BS服务器

一、模拟BS服务器分析 二、BS模拟服务器代码实现 图片都是单独请求,后台单独线程,这边是通过构造方法传入的Runable接口的实现类匿名对象创建线程; 创建本地输入流读取到网络输出流传过来的信息再放到网络输出流中返回; 转载于:ht…

不要62

题目 试题描述杭州人称那些傻乎乎粘嗒嗒的人为 62(音:laoer)。杭州交通管理局经常会扩充一些的士车牌照,新近出来一个好消息,以后上牌照,不再含有不吉利的数字了,这样一来,就可以消除…

CentOS 7 下的 Firewall

CentOS 7 默认实用的用Firewalld作为防火墙,摒弃了原先的iptables。但是内核还是使用iptable作为管理参考文档https://access.redhat.com/documentation/zh-CN/Red_Hat_Enterprise_Linux/7/html/Security_Guide/sec-Using_Firewalls.htmlhttp://www.myhome.net.tw/2…

POJ 1091(数论)

题目大意是给定两个整数n和m&#xff0c;求出长度为n1满足条件的数列data的个数&#xff0c;数列的要求下&#xff1a;1&#xff09;1<data[i]<m,for1<i<n2)data[n1]m;3&#xff09;这个n1个数满足&#xff1a;存在x1,x2,...,xn,xn1,满足x1*data[1]x2*data[2]...x(…

没有动任何配置文件,今天就出现了修改的JSP内容在页面不体现。依然是老的页面内容...

2019独角兽企业重金招聘Python工程师标准>>> 现象&#xff1a; 没有动任何配置文件&#xff0c;今天就出现了修改的JSP内容在页面不体现。依然是老的页面内容 问题分析: 既然可以用过&#xff0c;所以系统应该是检测文件更新的&#xff0c;之所以不重新编译JSP&…

PWA

转载于:https://www.cnblogs.com/QianDingwei/p/11359160.html

Windows XP SP3?转自作者: 孤单的鸽子,  出处:天极yesky, 责任编辑: 袁绍龙

经过测试和检查之后&#xff0c;我们认为&#xff0c;SP3并未为Windows XP系统引入任何新的功能&#xff0c;它仅仅是一款安全升级和BUG修正补丁程序集……原文&#xff1a;http://winsystem.ctocio.com.cn/windowsxp/321/7492821.shtml目前&#xff0c;互联网上围绕Windows XP…

创建表头固定,表体可滚动的GridView(转)

本方法只需要设置一个GridView的宽度&#xff0c;其它宽度不需要设置。测试环境&#xff1a;IE6&#xff0c;Firefox通过。 C# <% Page Language"C#" AutoEventWireup"true" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional/…

3G与4G到底有何区别?

对每一个手机用户来说&#xff0c;3G和4G都是手机术语词典中最神秘的词汇&#xff0c;然而在任何卖手机和平板电脑的地方你都能发现它们的身影。当你想买一部手机的时候&#xff0c;通常不清楚该选择哪一种&#xff0c;但有一点要明确——不要随便追求高的数字。这篇文章将帮助…

海尔5D净水洗热水器引领中国制造未来

在过去的一段时间里&#xff0c;智能家居与物联网相继成为热潮&#xff0c;云计算与大数据开始被应用于不同领域的情况下&#xff0c;越来越多的智能家居产品也开始走入普通消费者生活之中……在这些独特的产业创新风起云涌的情况下&#xff0c;越来越多的行业开始推动着中国制…

Lambda表达式——注重过程的编程思想

一、使用匿名内部类的匿名对象创建线程和Lambda表达式写法 Lambda表达式写法不用去定义一个Runable接口的实现类&#xff1b; 二、方法入参是一个接口或者接口的实现类 三、对某个类的一些对象实例进行排序 其中&#xff0c;数组创建时候使用的是静态初始化&#xff0c;里面存放…

[转] STL中map用法详解

一&#xff0e;Map概述 Map是STL的一个关联容器&#xff0c;它提供一对一&#xff08;其中第一个可以称为关键字&#xff0c;每个关键字只能在map中出现一次&#xff0c;第二个可能称为该关键字的值&#xff09;的数据处理能力&#xff0c;由于这个特性&#xff0c;它…

HDU 1874 畅通工程续

畅通工程续 Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 9566 Accepted Submission(s): 3200 Problem Description某省自从实行了很多年的畅通工程计划后&#xff0c;终于修建了很多路。不过路多了也不好&am…

转换流

一、编码和解码 二、编码带来的问题 三、转换流InputStreamReader和OutputStreamWriter编码和解码的原理 看懂的字符变成看不懂的字节编码 和 把看不懂的字节编码变成看懂的字符&#xff1b; 字节和字符转换的桥梁&#xff0c;不写默认utf-8&#xff08;国际规定&#xff09;&a…

序列化流

一、对象的序列化和反系列化 二、对象的序列化流ObjectOutputStream 标记型接口&#xff1a; 使用序列化流ObjectOutputStream将对象写入到文件中进行序列化&#xff1a; 执行过后的文件&#xff1a; 二进制字节存储&#xff0c;无法直接查看&#xff1b; 三、对象的反序列化流…

Asp.Net中虚拟文件系统的使用

具体实现步骤如下&#xff1a;一、开发web用户控件这一步和以前的开发没有区别。1、首先新建一个web应用程序(需要VS2005 sp1支持)2、然后在里面开发几个web用户控件3、在ascx文件上右键-〉属性-〉生成操作选择嵌入的资源4、生成dll就可以了(dll的名字为&#xff1a;Test.Contr…

打印流

一、打印流输出数据到文件 全路径&#xff0c;没有操作系统没有E盘&#xff0c;异常&#xff1b; 二、打印流修改打印输出路径 会生成一个记录的文件&#xff1a; 可用来记录一些操作日志&#xff1b; 转载于:https://www.cnblogs.com/wmqiang/p/11374696.html

乘法表

&#xfeff;&#xfeff;叙述性说明 法表或许将会扎根于我们一生的记忆,如今让我们重温那些温暖的记忆,请编程输出九九乘法表. 如今要求你输出它的格式与寻常的 不同啊! 是那种反过来的三角形啦&#xff0c;详细例如以下图&#xff1a; 每两个式子之前用一个空格 隔开。。。 输…