IronMan之组合

在上个篇幅中讲到怎么把“武器”装饰到“部件”上,这个篇幅呢,还是要讲到“武器”,不过呢是关于“武器”使用的。

本篇介绍"武器"的合理使用方式,不说废话,直接来看起初使用遇到的问题:

一起来看一下“武器”的定义:

1publicabstractclassWeaponUpgradeLevel12{3protectedList<WeaponUpgradeLevel1>weaponUpgrades=newList<WeaponUpgradeLevel1>();45publicList<WeaponUpgradeLevel1>WeaponUpgrades6{7get8{9returnweaponUpgrades;10}1112}13///<summary>14///判断是“部分”对象还是“整体”对象15///</summary>16publicboolIsSingle17{18get19{20if(weaponUpgrades.Count>0)21{22returnfalse;23}24else25{26returntrue;27}28}29}30///<summary>31///***32///</summary>33publicabstractvoidAttack();34///<summary>35///添加“部分”对象或者是“整体”对象到“整体”对象36///</summary>37///<paramname="weaponupgrade"></param>38///<returns></returns>39publicvirtualboolAdd(WeaponUpgradeLevel1weaponupgrade)40{41if(weaponupgrade!=null)42{43WeaponUpgrades.Add(weaponupgrade);44returntrue;45}46else{returnfalse;}4748}49///<summary>50///从“整体”对象中移除“部分”对象或者是“整体”对象51///</summary>52///<paramname="weaponupgrade"></param>53///<returns></returns>54publicvirtualboolRemove(WeaponUpgradeLevel1weaponupgrade)55{56if(weaponupgrade!=null)57{58if(WeaponUpgrades.Contains(weaponupgrade))59{60WeaponUpgrades.Remove(weaponupgrade);61returntrue;62}63else64{65returnfalse;66}67}68else{returnfalse;}69}70}71publicclassRocket:WeaponUpgradeLevel172{73privatestring_name="火箭炮";7475publicoverridevoidAttack()76{77Console.WriteLine("使用"+_name+"进行***");78}79}80publicclassRocketLevel1:WeaponUpgradeLevel181{82privatestring_name="火箭炮(EX.2X2)";//由四个火箭炮组成8384publicoverridevoidAttack()85{86Console.WriteLine("使用"+_name+"进行***");87}88}

上面定义了三种类型,WeaponUpgradeLevel1是“武器”的抽象,并且在其中定义了一些属性和方法,

用于表示实现了此“武器”抽象的类型是否是核心武器(部分)还是核心武器的外壳(整体),

并且也在后面实现了“武器”抽象,分别是Rocket核心武器(部分)和RocketLevel1核心武器的外壳(整体),这样的结构定义好了过后,我们来看一下子,怎么使用它们:

1WeaponUpgradeLevel1weaRocket1=newRocket();2WeaponUpgradeLevel1weaRocket2=newRocket();3WeaponUpgradeLevel1weaRocket3=newRocket();4WeaponUpgradeLevel1weaRocket4=newRocket();56WeaponUpgradeLevel1weaRocketlevel1=newRocketLevel1();7weaRocketlevel1.Add(weaRocket1);8weaRocketlevel1.Add(weaRocket2);9weaRocketlevel1.Add(weaRocket3);10weaRocketlevel1.Add(weaRocket4);

这时候 weaRocketlevel1示例是像图1这样的:

图1

图2

要是使用weaRocketlevel1,真正的目的不是使用它本身,而是使用它里面的小火箭炮(也就是weaRocket1……)。 如果想要使用里面的小火箭炮,并不是简简单单的遍历一下就可以了,从现在的情况来看,确实是很简单的遍历

,获取到每个火箭炮,并且使用它们, 但是如果这个"火箭炮(EX.2X2)"改成了"火箭炮(EX.8X8)"呢? 并且"火箭炮(EX.8X8)"是由 4个"火箭炮(EX.4X4)"组成,每个"火箭炮(EX.4X4)"是由4个"火箭炮(EX.2X2)"组成的。 在这样的情况下怎么办? 没错了,是使用递归来遍历,然后的情况就是如图3所示:

图3

这样来看,也确实没什么大问题,只是耦合度比较高。
使用设计模式可以在特定的情况下解耦,这里的情况比较适合Composite模式。

将对象组合成树形结构以表示“部分-整体”的层次结构。Composite模式使得用户对单个对象和组合

对象的使用具有一致性。

[GOF 《设计模式》]

根据设计的中心思想,看一下修改后的结构:

1publicabstractclassWeaponUpgradeLevel12{3protectedList<WeaponUpgradeLevel1>weaponUpgrades=newList<WeaponUpgradeLevel1>();45publicList<WeaponUpgradeLevel1>WeaponUpgrades6{7get8{9returnweaponUpgrades;10}1112}13///<summary>14///判断是“部分”对象还是“整体”对象。15///true为“部分”对象反之相对16///</summary>17publicboolIsSingle18{19get20{21if(weaponUpgrades.Count>0)22{23returnfalse;24}25else26{27returntrue;28}29}30}31///<summary>32///***33///</summary>34publicvirtualvoidAttack()35{36ActionAttack(this);37}38privatevoidActionAttack(WeaponUpgradeLevel1weaponupgrade)39{40if(weaponupgrade.IsSingle)41{42weaponupgrade.Attack();43}44else45{46foreach(WeaponUpgradeLevel1weaponinweaponupgrade.WeaponUpgrades)47{48ActionAttack(weapon);49}50}51}52///<summary>53///添加“部分”对象或者是“整体”对象到“整体”对象54///</summary>55///<paramname="weaponupgrade"></param>56///<returns></returns>57publicvirtualboolAdd(WeaponUpgradeLevel1weaponupgrade)58{59if(weaponupgrade!=null)60{61WeaponUpgrades.Add(weaponupgrade);62returntrue;63}64else{returnfalse;}6566}67///<summary>68///从“整体”对象中移除“部分”对象或者是“整体”对象69///</summary>70///<paramname="weaponupgrade"></param>71///<returns></returns>72publicvirtualboolRemove(WeaponUpgradeLevel1weaponupgrade)73{74if(weaponupgrade!=null)75{76if(WeaponUpgrades.Contains(weaponupgrade))77{78WeaponUpgrades.Remove(weaponupgrade);79returntrue;80}81else82{83returnfalse;84}85}86else{returnfalse;}87}88}89publicclassRocket:WeaponUpgradeLevel190{91privatestring_name="火箭炮";9293publicoverridevoidAttack()94{95Console.WriteLine("使用"+_name+"进行***");96}97}98publicclassRocketLevel1:WeaponUpgradeLevel199{100privatestring_name="火箭炮(EX.2X2)";//由四个火箭炮组成101102publicoverridevoidAttack()103{104base.Attack();105Console.WriteLine("使用"+_name+"进行***");106}107}

看一下现在的客户端怎么使用“火箭炮”:

1WeaponUpgradeLevel1weaRocket1=newRocket();2WeaponUpgradeLevel1weaRocket2=newRocket();3WeaponUpgradeLevel1weaRocket3=newRocket();4WeaponUpgradeLevel1weaRocket4=newRocket();5WeaponUpgradeLevel1weaRocketlevel1=newRocketLevel1();6weaRocketlevel1.Add(weaRocket1);7weaRocketlevel1.Add(weaRocket2);8weaRocketlevel1.Add(weaRocket3);9weaRocketlevel1.Add(weaRocket4);10weaRocketlevel1.Attack();

所示结果如图4

图4

根据设计模式的思想修改代码的区别是在“武器”抽象中把对“核心武器”的使用做了统一的使用。意思就不做阐述了可以自己理解理解。