1 讨论会

话说有一个叫IGame的游戏公司,正在开发一款ARPG游戏(动作&角色扮演类游戏,如魔兽世界、梦幻西游这一类的游戏)。一般这类游戏都有一个基本的功能,就是打怪(玩家攻击怪物,借此获得经验、虚拟货币和虚拟装备),并且根据玩家角色所装备的武器不同,攻击效果也不同。这天,IGame公司的开发小组正在开会对打怪功能中的某一个功能点如何实现进行讨论,他们面前的大屏幕上是这样一份需求描述的ppt:

各个开发人员,面对这份需求,展开了热烈的讨论,下面我们看看讨论会上都发生了什么。

2 实习生小李的实现方式

在经过一番讨论后,项目组长Peter觉得有必要整理一下各方的意见,他首先询问小李的看法。小李是某学校计算机系大三学生,对游戏开发特别感兴趣,目前是IGame公司的一名实习生。经过短暂的思考,小李阐述了自己的意见:

“我认为,这个需求可以这么实现。HP当然是怪物的一个属性成员,而武器是角色的一个属性成员,类型可以使字符串,用于描述目前角色所装备的武器。角色类有一个攻击方法,以被攻击怪物为参数,当实施一次攻击时,攻击方法被调用,而这个方法首先判断当前角色装备了什么武器,然后据此对被攻击怪物的HP进行操作,以产生不同效果。”而在阐述完后,小李也飞快的在自己的电脑上写了一个Demo,来演示他的想法,Demo代码如下。

package com.wangxing.game.test1;
/*** 怪物类* @author Administrator**/
public class GuaiWu {//怪物名称private String guaiwu_name;//怪物生命值private int guaiwu_hp;public String getGuaiwu_name() {return guaiwu_name;}public void setGuaiwu_name(String guaiwu_name) {this.guaiwu_name = guaiwu_name;}public int getGuaiwu_hp() {return guaiwu_hp;}public void setGuaiwu_hp(int guaiwu_hp) {this.guaiwu_hp = guaiwu_hp;}
}package com.wangxing.game.test1;
/*** 角色类* @author Administrator**/
public class JueSe {//武器变量private  String  wuqi;//通过构造方法设置武器数据值public  JueSe(String wq){this.wuqi=wq;}/*** 角色的攻击方法* @param gw*/public  void  gongji(GuaiWu gw){//判断怪物是否死亡,如果已经死亡,则无序继续攻击if(gw.getGuaiwu_hp()<=0){System.out.println("怪物-"+gw.getGuaiwu_name()+"-已经死亡!");return;}//根据角色装配的武器不同,对怪物产生不同的效果//木剑攻击效果if(this.wuqi.equals("木剑")){//得到当前怪物的生命值int dangqianhp=gw.getGuaiwu_hp();//对当前生命值减20int lessafterhp=dangqianhp-20;//重新将损失以后的生命值赋值给怪物gw.setGuaiwu_hp(lessafterhp);//继续判断怪物是否死亡if(gw.getGuaiwu_hp()<=0){System.out.println("怪物-"+gw.getGuaiwu_name()+"-已经死亡!");return;}else{System.out.println("怪物-"+gw.getGuaiwu_name()+"-损失20hp,还剩"+gw.getGuaiwu_hp()+"hp!");}}//铁剑攻击效果if(this.wuqi.equals("铁剑")){//得到当前怪物的生命值int dangqianhp=gw.getGuaiwu_hp();//对当前生命值减50int lessafterhp=dangqianhp-50;//重新将损失以后的生命值赋值给怪物gw.setGuaiwu_hp(lessafterhp);//继续判断怪物是否死亡   if(gw.getGuaiwu_hp()<=0){System.out.println("怪物-"+gw.getGuaiwu_name()+"-已经死亡!");return;}else{System.out.println("怪物-"+gw.getGuaiwu_name()+"-损失50hp,还剩"+gw.getGuaiwu_hp()+"hp!");}        }//魔剑攻击效果if(this.wuqi.equals("魔剑")){//得到当前怪物的生命值int dangqianhp=gw.getGuaiwu_hp();//对当前生命值减100/暴击200int random=((int)(Math.random()*10))+1;int lesshp=0;if(random>5){System.out.println("产生暴击!!!");lesshp=200;}else{lesshp=100;}int lessafterhp=dangqianhp-lesshp;//重新将损失以后的生命值赋值给怪物gw.setGuaiwu_hp(lessafterhp);//继续判断怪物是否死亡 if(gw.getGuaiwu_hp()<=0){System.out.println("怪物-"+gw.getGuaiwu_name()+"-已经死亡!");return;}else{System.out.println("怪物-"+gw.getGuaiwu_name()+"-损失"+lesshp+"hp,还剩"+gw.getGuaiwu_hp()+"hp!");}    }}
}//测试类
package com.wangxing.game.test1;
public class TestMain {public static void main(String[] args) {//创建怪物对象GuaiWu  gw1=new GuaiWu();gw1.setGuaiwu_name("巡山小妖");gw1.setGuaiwu_hp(1000);//创建角色对象JueSe  js1=new JueSe("木剑");JueSe  js2=new JueSe("铁剑");JueSe  js3=new JueSe("魔剑");while(gw1.getGuaiwu_hp()>0){//角色攻击怪物js3.gongji(gw1);}}
}

3 架构师的建议

小李阐述完自己的想法并演示了Demo后,项目组长Peter首先肯定了小李的思考能力、编程能力以及初步的面向对象分析与设计的思想,并承认小李的程序正确完成了需求中的功能。但同时,Peter也指出小李的设计存在一些问题,他请小于讲一下自己的看法。

小于是一名有五年软件架构经验的架构师,对软件架构、设计模式和面向对象思想有较深入的认识。他向Peter点了点头,发表了自己的看法:

“小李的思考能力是不错的,有着基本的面向对象分析设计能力,并且程序正确完成了所需要的功能。不过,这里我想从架构角度,简要说一下我认为这个设计中存在的问题。

首先,小李设计的角色类的攻击方法很长,并且方法中有一个冗长的if…else结构,且每个分支的代码的业务逻辑很相似,只是很少的地方不同。

再者,我认为这个设计比较大的一个问题是,违反了O【Open】C【Close】P原则。在这个设计中,如果以后我们增加一个新的武器,如倚天剑,每次攻击损失500HP,那么,我们就要打开角色类,修改攻击方法。而我们的代码应该是对修改关闭的,当有新武器加入的时候,应该使用扩展完成,避免修改已有代码。

一般来说,当一个方法里面出现冗长的if…else或switch…case结构,且每个分支代码业务相似时,往往预示这里应该引入多态性来解决问题。而这里,如果把不同武器攻击看成一个策略,那么引入策略模式(Strategy Pattern)是明智的选择。

最后说一个小的问题,被攻击后,减HP、死亡判断等都是怪物的职责【高内聚】,这里放在角色中有些不当。”

小于边说,边画了一幅UML类图,用于直观表示他的思想

Peter让小李按照小于的设计重构Demo,小李看了看小于的设计图,很快完成。相关代码如下:

package com.wangxing.game.test2;
/*** 怪物类* @author Administrator**/
public class GuaiWu {//怪物名称private  String  guaiwu_name;//怪物生命值private  int  guaiwu_hp;public String getGuaiwu_name() {return guaiwu_name;}public void setGuaiwu_name(String guaiwu_name) {this.guaiwu_name = guaiwu_name;}public int getGuaiwu_hp() {return guaiwu_hp;}public void setGuaiwu_hp(int guaiwu_hp) {this.guaiwu_hp = guaiwu_hp;}/*** 怪物掉血* @param lesshp*/public void notify(int lesshp){//判断怪物是否死亡if(this.guaiwu_hp<=0){System.out.println("怪物-"+this.guaiwu_name+"-已经死亡!");return;}//设置怪物掉血this.guaiwu_hp=this.guaiwu_hp-lesshp;//判断怪物是否死亡if(this.guaiwu_hp<=0){System.out.println("怪物-"+this.guaiwu_name+"-已经死亡!");return;}else{System.out.println("怪物-"+this.guaiwu_name+"-损失"+lesshp+"hp,还剩"+this.guaiwu_hp+"hp!!!");}}
}package com.wangxing.game.test2;
/*** 武器接口* @author Administrator**/
public interface AttackStrategyInterface {//攻击怪物方法void AttackTarget(GuaiWu gw);
}package com.wangxing.game.test2;
/*** 角色类* @author Administrator**/
public class JueSe {//定义角色装配的武器public  AttackStrategyInterface  weapon;/*** 角色的攻击方法* @param gw*/public  void  Attack(GuaiWu gw){weapon.AttackTarget(gw);}
}package com.wangxing.game.test2;
/*** 木剑* @author Administrator**/
public class IronSword implements AttackStrategyInterface{@Overridepublic void AttackTarget(GuaiWu gw) {gw.notify(20);}
}package com.wangxing.game.test2;
/*** 铁剑* @author Administrator**/
public class WoodSword implements AttackStrategyInterface{@Overridepublic void AttackTarget(GuaiWu gw) {gw.notify(50);}
}package com.wangxing.game.test2;
/*** 魔剑* @author Administrator**/
public class MagicSword implements AttackStrategyInterface{@Overridepublic void AttackTarget(GuaiWu gw) {int random=((int)(Math.random()*10))+1;int lesshp=(random>5)?200:100;if(lesshp==200){System.out.println("产生暴击!!!");}gw.notify(lesshp);}
}//测试
package com.wangxing.game.test2;
public class TestMain {public static void main(String[] args) {GuaiWu  gw=new GuaiWu();gw.setGuaiwu_name("银角大王");gw.setGuaiwu_hp(10000);JueSe js1=new JueSe();//js1.weapon=new IronSword();//js1.weapon=new WoodSword();//js1.weapon=new MagicSword();js1.weapon=new YiTianJian();while(gw.getGuaiwu_hp()>0){js1.Attack(gw);}}
}

Tip:OCP原则,即开放关闭原则,指设计应该对扩展开放,对修改关闭。

Tip:策略模式,英文名Strategy Pattern,指定义算法族,分别封装起来,让他们之间可以相互替换,此模式使得算法的变化独立于客户。

15.IGame游戏公司的故事相关推荐

  1. 依赖注入那些事儿【1】 之 IGame游戏公司的故事

    1.1 讨论会 话说有一个叫IGame的游戏公司,正在开发一款ARPG游戏(动作&角色扮演类游戏,如魔兽世界.梦幻西游这一类的游戏).一般这类游戏都有一个基本的功能,就是打怪(玩家攻击怪物,借 ...

  2. Game游戏公司的故事

    一.讨论会   有一个Game的游戏公司,正准备开发一款ARPG游戏(动作&角色扮演类游戏,如魔兽世界.梦幻西游这一类游戏).这类游戏都有一个基本功能,就是打怪(玩家通过攻击怪物,借此获得经验 ...

  3. 如何在三个月内创立一家估值200亿的游戏公司?

    很长一段时间,游戏公司一直是土豪的代名词,据说某游戏公司给一位主策的年终奖是一套价值千万的房子(真实案例),有越来越多创业者投身到游戏领域中来,抱着"做一年然后套现卖掉"的想法开始 ...

  4. 故事向|在3A游戏公司工作多年的3D建模师自述,制作3A大作经验心得(上)

    今天给大家带来一篇教程,感谢charleshuang715同学的翻译. 来自艺夺蒙特利尔工作室的Charlotte Delannoy 将分享她在制作古墓丽影系列里关于贴图以及材质优化方面的经验,以及给 ...

  5. 回顾社交游戏公司Zynga创业史

    原帖: http://gamerboom.com/archives/44239 作者:Dean Takahashi 在短短的5年时间里,Zynga便在电子游戏领域里掀起了巨大的热潮.即将迎来重要的IP ...

  6. 游戏公司岗位大揭秘!各职位工作都有什么特点?

    相信很多人都爱玩游戏,也在游戏世界中得到很多乐趣.既然那么多人爱玩游戏,那么在以游戏谋生的人一定不在少数.那么你了解游戏公司的各个职位的工作情况吗?这些职位的工作内容都是什么? 我们先来看一下游戏开发 ...

  7. 顶尖游戏公司介绍---暴雪

    暴雪公司主页 http://www.blizzard.com/ 1991       Silicon & Synapse公司成立,同时发展RPM游戏 * 成立后Allen Adham为公司总裁 ...

  8. 在某游戏公司面试游戏运营的感受

    本人不才在一家知名游戏公司面试过,首先介绍下这家公司,是一家小游戏,网页游戏,手游都做的一家公司,由于我面试的是页游运营,这边主要介绍下当下他们家的产品,arpg类型游戏,竞技类,FPS类型,还有其他 ...

  9. 国产游戏版号时隔8个月重启 游戏公司董事长喜极而泣

    4月12日消息,昨日晚间,国家新闻出版署公布<2022年4月份国产网络游戏审批信息>,共计45款游戏获批.这是自2021年7月以来,国家新闻出版署公布的首批游戏版号. 45款游戏获批 游戏 ...

最新文章

  1. im即时通讯源码_IM消息ID技术专题(六):深度解密滴滴的高性能ID生成器(Tinyid)
  2. 天津发票版本文件服务器端口,天津市增值税发票综合服务平台网址
  3. 关于JAP FetchType.LAZY(hibernate实现)的理解
  4. Non-zero CodeForces - 1300A
  5. Qt实现多屏幕多分辨率自适应
  6. 附录-SpringFactoriesLoader
  7. Shiro学习笔记四(Shiro集成WEB)
  8. 微信小程序开发--【Hello World 及代码结构】(二)
  9. 5. 视图——Django
  10. php 调用redis中lpush的方法
  11. C#通过WebBrowser对网页截图
  12. Java 订单管理系统
  13. 速成实用硬笔字——最常用高频汉字前100
  14. Linux 之旅 8:初识 BASH
  15. 说一说关于破解支付宝AR红包的事
  16. Windows10系统自带输入法如何切换全角/半角字符
  17. 关于正则表达式中的 lookahead
  18. Android 发送彩信
  19. 微信网页开发(6)--图像接口
  20. 双向可控硅实现单相交流电机正反转(硬开通加缓冲吸收,无过零)

热门文章

  1. 蓝桥杯——罗马数字转换器
  2. Python Cannot open E:\Python36\Scripts\pip-script.py
  3. Windows下的扩展文件名
  4. C++ 几种智能指针的简单实现
  5. Hololens环境搭建
  6. 《Linux操作系统-基础笔记》第6章 编译调试工具(GCC、GDB)
  7. win7左上角白杠一直闪_win10换win7
  8. 计算机制作不同数据数据图表,数据图表与分析.doc
  9. iOS开发 - 使用IJKPlayer时,关于需求要边下边播的缓存功能,退回来后播放缓存不再耗流量
  10. 使用二维码识别技术的好处_二维码门禁你知道支持多少种识别方式