先来描述一下问题吧,游戏中的物品原来只有一个属性加成:攻击,防御,获得经验加成,金币加成,等等。现在要增加一个属性,这个属性可以为之前的属性之一。

  这个属性加成涉及到类里的三个属性,value,type,grow_value,在战斗,角色属性预览,还有物品的详细信息里面都有使用到,type表示的是这个加成的类型,value表示这个加成的值,grow_value表示这个加成的成长值。现在加了一个属性,之前的计算方法就都不能用了,而且变量名字也得改,在添加后应该变成,value1,type1,grow_value1,value2,type2,grow_value2,之前所有计算的地方都需要修改,UI显示部分也需要修改。而且这些改动很多,很无脑,很繁杂。(也许有好的修改方法,知道的请在评论里面提示一下。)

  上头就把这个任务给了我,然后告诉我应该这么改,就没了。我改了几个地方发现异常蛋疼,于是就想着有什么好的解决办法。学了1年多的函数式编程,现在终于被我用上了。

  可以把新的属性加成看成是一个新的物品,这个物品只有3个属性value,type,grow_value,我们现在需要的是一个原来的物品附加一个新的物品,这样原来计算的方法都可以使用了,我们要做的只是再计算一次。并不是所有的物品都有两个属性,只是新加的一些物品才会有两种属性,所以再计算的时候判断一下这个物品是否有附加的物品就好了。下面用代码简单地描述一下各个类的修改,我使用的是AS3,类似JS,可以把函数作为一个对象来使用,支持闭包和匿名函数(lambda)。

  第一步在原来的类里面添加三个附加的属性,以及一个attachItem

  

private var _attachType:int;

private var _attachValue:int;

private var _attachGrowValue:int;

private var _attachEquipment:EquipmentData = null;

//三个属性设置为只写
public function set attachType(value:int):void
{
_attachType = value;
} public function set attachValue(value:int):void
{
_attachValue = value;
} public function set attachGrowValue(value:int):void
{
_attachGrowValue = value;
} //附加对象设置为只读
public function get attachEquipment():EquipmentData
{
if(_attachType && _attachValue && _attachGrowValue)
{
_attachEquipment = new EquipmentData();
_attachEquipment.value = _attachValue;
_attachEquipment.valueType = _attachType;
_attachEquipment.growValue = _attachGrowValue;
} return _attachEquipment;
}

  新加的三个属性只在读表的时候用到。另外在使用这个类作为数据,并将这个类的数据进行加工后提供给外部的类中添加两个方法和一个属性。

public class CEquipment
{
private var _preCardXmlData:EquipmentData;
public function CEquipment()
{ } /**
* 当需要计算本装备的属性加成时将需要的计算设置为函数传入
* @param func
*
*/
public function handleProp(func:Function):void
{
func();
handleAttachEquip(func);
} /**
* 仅针对附加属性执行的操作
* @param func
*
*/
public function handleAttachEquip(func:Function):void
{
if((_cCardXmlData as EquipmentXmlData).attachEquipment)
{
_preCardXmlData = _cCardXmlData;
_cCardXmlData = (_cCardXmlData as EquipmentData).attachEquipment;
func();
_cCardXmlData = _preCardXmlData;
}
func = null;
} public function get valueType():int
{
//使用_cCardXmlData 的type各种计算
} public function get value():int
{
//使用_cCardXmlData 的value各种计算
} public function get valueShow():String
{
//使用_cCardXmlData 的value和grow_value各种计算
}

说明一下第一个函数handleProp按照注释说的,可以这样修改原来调用那3个属性计算的方法。比如原来是:

      switch(cEquipment.valueType)
{
case CardConst.ATTACK:
_cEquipmentAttackMin += cEquipment.value;
_cEquipmentAttackMax += cEquipment.value;
break;
case CardConst.DEFENSE:
_cEquipmentDefenseMin += cEquipment.value;
_cEquipmentDefenseMax += cEquipment.value;
break;
case CardConst.MINATTACKMILLI:
_equipmentAttackMinMilli += cEquipment.value / 1000;
break;
case CardConst.MAXATTACKMILLI:
_equipmentAttackMaxMilli += cEquipment.value / 1000;
break;
case CardConst.MINDEFENSEMILLI:
_equipmentDefenseMinMilli += cEquipment.value / 1000;
break;
case CardConst.MAXDEFENSEMILLI:
_equipmentDefenseMaxMilli += cEquipment.value / 1000;
break;
}

只要这样处理就好:

        cEquipment.handleProp(function():void{
switch(cEquipment.valueType)
{
case CardConst.ATTACK:
_cEquipmentAttackMin += cEquipment.value;
_cEquipmentAttackMax += cEquipment.value;
break;
case CardConst.DEFENSE:
_cEquipmentDefenseMin += cEquipment.value;
_cEquipmentDefenseMax += cEquipment.value;
break;
case CardConst.MINATTACKMILLI:
_equipmentAttackMinMilli += cEquipment.value / 1000;
break;
case CardConst.MAXATTACKMILLI:
_equipmentAttackMaxMilli += cEquipment.value / 1000;
break;
case CardConst.MINDEFENSEMILLI:
_equipmentDefenseMinMilli += cEquipment.value / 1000;
break;
case CardConst.MAXDEFENSEMILLI:
_equipmentDefenseMaxMilli += cEquipment.value / 1000;
break;
}
});

下面说明一下原理,将原来的计算过程作为一个函数传入CEquipment类中,在handleProp中立刻进行调用,这样就计算完成了第一个属性。然后handleProp将函数传给了handlerAttachEquip函数,这个函数判断物品是否有附加的物品,如果有,则保存原来的物品数据,暂时将物品的数据替换为附加的物品数据,然后再调用传入的计算函数,这时候计算所使用的值就是附加物品的值。当计算完毕后,又将物品的数据还原。感觉就像变魔术一样。

 在UI使用上,只需要将UI的代码作为函数传到handlerAttachEquip函数中就好了,如果有第二个属性则显示第二个属性,否则就不显示。

可惜我这个做法得不到上面的认同,写完后,上面说看不懂,而且说我的代码看了他想死。。

还好我们经过漫长的讨论后,他说这次就算了,下次不能再使用这个方法。

今天发布在这里感慨一下,希望各位使用新技术的不要气馁,美好的时代会来临的。

使用闭包和lambda解决问题与常规方式解决问题的对比。的更多相关文章

  1. 如何设计一门语言(七)——闭包、lambda和interface

    人们都很喜欢讨论闭包这个概念.其实这个概念对于写代码来讲一点用都没有,写代码只需要掌握好lambda表达式和class+interface的语义就行了.基本上只有在写编译器和虚拟机的时候才需要管什么是 ...

  2. 闭包、lambda和interface

    闭包.lambda和interface 人们都很喜欢讨论闭包这个概念.其实这个概念对于写代码来讲一点用都没有,写代码只需要掌握好lambda表达式和class+interface的语义就行了.基本上只 ...

  3. C++:几种callable实现方式的性能对比

    C++中几种callable实现方式的性能对比 前言 C++中想实现一个callable的对象,通常有四种方式: std::function:最common的方式,一般会配合std::bind使用. ...

  4. ArrayList和LinkedList的几种循环遍历方式及性能对比分析(转)

    主要介绍ArrayList和LinkedList这两种list的五种循环遍历方式,各种方式的性能测试对比,根据ArrayList和LinkedList的源码实现分析性能结果,总结结论. 通过本文你可以 ...

  5. ArrayList和LinkedList的几种循环遍历方式及性能对比分析

    最新最准确内容建议直接访问原文:ArrayList和LinkedList的几种循环遍历方式及性能对比分析 主要介绍ArrayList和LinkedList这两种list的五种循环遍历方式,各种方式的性 ...

  6. ArrayList和LinkedList的几种循环遍历方式及性能对比分析(转载)

    原文地址: http://www.trinea.cn/android/arraylist-linkedlist-loop-performance/ 原文地址: http://www.trinea.cn ...

  7. HashMap循环遍历方式及其性能对比(zhuan)

    http://www.trinea.cn/android/hashmap-loop-performance/ ********************************************* ...

  8. ArrayList和LinkedList遍历方式及性能对比分析

    ArrayList和LinkedList的几种循环遍历方式及性能对比分析 主要介绍ArrayList和LinkedList这两种list的五种循环遍历方式,各种方式的性能测试对比,根据ArrayLis ...

  9. HashMap循环遍历方式及其性能对比

    主要介绍HashMap的四种循环遍历方式,各种方式的性能测试对比,根据HashMap的源码实现分析性能结果,总结结论.   1. Map的四种遍历方式 下面只是简单介绍各种遍历示例(以HashMap为 ...

随机推荐

  1. Js arguments.callee();函数自己调用自己

    1.阶乘的时候,函数一般要用到递归算法,所以函数内部一定会调用自身 //递归,阶乘 function sum(num){ ) { ; } else{ ); //自己调用自己,递归 } } alert( ...

  2. 如何把某个网站的SSL Server certificate链导入到ABAP Netweaver系统里

    我们在用ABAP代码消费外网的url时会遇到一些异常,比如ICM_HTTP_SSL_PEER_CERT_UNTRUSTED,这是因为请求的url所在的网站的SSL Server certificate ...

  3. vsftpd 启动 vsftpd:500 OOPS: bad bool value in config file for: guest_enable

    不然启动时会涌现毛病,举个例子 guest_enable=YES  后面出现空格,就会出现 为 vsftpd 启动 vsftpd:500 OOPS: bad bool value in config ...

  4. 问题 B: C++习题 对象数组输入与输出

    题目描述 建立一个对象数组,内放n(n<10)个学生的数据(学号.成绩),用指针指向数组首元素,输出第奇数(1,3,5,7)个学生的数据. 输入 n和n个学生的学号.成绩 输出 奇数学生的数据 ...

  5. 使用QT开发GoogleMap瓦片显示和下载工具(1)——QT开发环境准备

    由于是第一次使用qt,光是QT的安装和调试就费了好大功夫,汗一个,下面记录下过程和遇到的问题的解决方法吧. 下载QT 直接Google搜索“QT”,进入官网http://qt-project.org/ ...

  6. Advanced Memory Allocation 内存分配进阶[转]

    May 01, 2003  By Gianluca Insolvibile  in Embedded Software Call some useful fuctions of the GNU C l ...

  7. cudaMalloc和cudaMallocPitch

    原文链接 偶有兴趣测试了一下题目中提到的这两个函数,为了满足对齐访问数据,咱们平时可能会用到cudamallocPitch,以为它会带来更高的效率.呵呵,这里给出一段测试程序,大家可以在自己的机器上跑 ...

  8. 绕不开的this

    犹豫两秒要不要整理this,从红皮书上看了半天,没搞懂哎(弱爆了) 什么是this?this是在执行上下文创建时期创建的一个执行过程中不可改变的变量.执行上下文是指js引擎会将代码执行前需要的变量th ...

  9. XML 对xml文件的crud的增加 create操作 增加元素 增加属性

    把创建的节点挂到上一节点的最后 找到参考节点,使用insertBefore方法进行插入位置 xml添加属性使用setAttribute方法

  10. P3366 最小生成树【模板+Kruscal讲解】

    此题数组大小非常重要 算法过程: 现将全部边按照权值(由小到大)排序. 按顺序(同上)考虑每条边,只要这条边和之前已选择的边不构成圈,就保留这条边,否则放弃这条边. 具体算法 成功选择(n-1)条边后 ...