一、组合代替继承
(多用组合,少用继承)
1、继承
最近在做一个类杀戮之塔的unity游戏Demo,然后因为个人水平有限,导致游戏里类继承层次过深,同一属性由多个不同的平行对象持有等问题。如下面的类图:
然后这带来的问题是:
(1)修改代码麻烦:一旦继承链中的一个对象出现修改,由于它的“承上启下”作用,就不得对关联到的类也做出修改(违反开闭原则);
(2)数据更新困难:如果继承链的某一层需要对外交互,而交互数据在另一条继承链上,那么就会出现像小学试卷里的"连连看"题目一样的关系线,而且因为是继承关系,如果两个继承链需要用到同一份数据,那么你就不得不合并两条链(再次继承或者组合)或者让代码中存在两份数据源;
(3)可读性差:有时候我想在代码里找一个数据都得把几个文件翻来覆去看半天(这还是我写的代码)。
2、组合
修正上面继承带来的问题采用的方法是——组合。
把上面的对象的所有功能都抽离出来,按功能变成一个个组件,而原本的对象就变成一个总控,一个挂钩,当我们的对象需要哪个功能时,就把哪个组件挂载上去,即插即用。这样做除了解决上面的问题,还能得到下面的好处:
(1)职责分离:原本一个庞大的继承类分离成了多个彼此无耦合的组件,再也不需要为了一根香蕉而去买下整个森林了(继承税)。
(2)交互便利:因为有了“总控”的概念,所以当出现对象间的数据交互时,我不需要去翻查交互对象的所在的继承结点是否有该数据,和总控对接,只需要关心它是否持有某组件即可。
基于组合思想下的交互模式:外部事件由总控调用分发,组件之间也通过总控传递数据。
二、状态代替标记
战斗对象需要有一个方式来表示他身上的各种增减益Buff,那么可以怎么处理呢?
1、标记
第一种方式,我们采用“标记”的方式来实现
class CWarrior(object):
def __init__(self):
self.m_BuffDict = {
} #维护一个buff字典
def QueryBuff(self, sBuffName):
if sBuffName in self.m_BuffDict:
return self.m_BuffDict[sBuffName]
return 0
def AddBuff(self, sBuffName, iValue):
self.m_BuffDict[sBuffName] = iValue
def RemoveBuff(self, sBuffName):
if sBuffName in self.m_BuffDict:
del self.m_BuffDict[sBuffName]
初步看起来还不错,但当你的战斗对象需要根据buff做出行为反应的时候,就很难受了。比如说,设想一下下面这个场景:
战斗对象A向战斗对象B释放了一个技能,根据B身上的buff触发各类行为:
1、流血(Bleeding):受到伤害时额外扣除100点生命值
2、感电(Electric):收到雷属性伤害时额外扣除200点生命值
3、