IronMan之桥接

前言

前面的几个篇幅都是在讲"部件"的生产已经简简单单的使用,以后可能要对"部件"进行升级,不是不对它本身升级,是其它方式的升级,可以让它配备武器。有没有感觉"部件"是越来越强大了,事物的衍变都是有个过程的嘛,必须要越来越完善,这是"IronMan"设计的宗旨。

好了,废话不多说了,现在所要做的工作就是设计好这个"武器",以便在后面的篇幅中和"部件"很好的结合在一起。来看一下"武器"的定义:


1///<summary>2///武器3///</summary>4publicabstractclassWeapon5{6///<summary>7///***8///</summary>9publicabstractvoidAttack();10}11///<summary>12///激光武器13///</summary>14publicclassLaserWeapon:Weapon15{1617publicoverridevoidAttack()18{19//LaserAttack20}21}22///<summary>23///×××武器24///</summary>25publicclassMissileWeapon:Weapon26{2728publicoverridevoidAttack()29{30//MissileAttack31}32}


这样看起来好像没有什么不妥的,因为出于设计的全面性和以便于以后的扩展,所以要尽可能的想的全面。
"武器"的使用也是要受环境限制或影响的。在这里怎么表现出来呢?
先假设两种坏境的下武器使用,一种是水下,一种是太空中(真空状态)


1///<summary>2///水下的激光武器3///</summary>4publicclassUnderwaterLaserWeapon:LaserWeapon5{6publicoverridevoidAttack()7{8//逻辑处理9base.Attack();10//逻辑处理11}12}13///<summary>14///真空状态下激光武器15///</summary>16publicclassEmptyLaserWeapon:LaserWeapon17{18publicoverridevoidAttack()19{20//逻辑处理21base.Attack();22//逻辑处理23}24}25///<summary>26///水下的×××武器27///</summary>28publicclassUnderwaterMissileWeapon:MissileWeapon29{30publicoverridevoidAttack()31{32//逻辑处理33base.Attack();34//逻辑处理35}36}37///<summary>38///真空下的×××武器39///</summary>40publicclassEmptyMissileWeapon:MissileWeapon41{42publicoverridevoidAttack()43{44//逻辑处理45base.Attack();46//逻辑处理47}48}


看一下图1所示现在所有类型的结构图

整体的设计是没有大碍的,在增加一项"武器"类型时也是没有问题了,同样遵循着开闭原则。
如果是在添加一种坏境的时候也是遵循着开闭原则的,但是违背了类的单一职责原则,而且这样的设计继承关系太多,不易维护难以扩展,如果这个"武器"是多维的,而且是同时的向着多维前面变化的,那么这个"武器"的结构将会变的庞大无比。
现在应该是"桥接"大展身手的时候了,要在"武器"的两个(或者更多)变化的方向解耦,把强耦合变成弱联系。

实现

原来"武器"的结构不变,只需要在其中的一个维度中提取出抽象(实现类接口),然后"武器"(抽象类)引用从维度中提取出的抽象就好了。
我们来看一下结构:

1///<summary>2///环境3///</summary>4publicinterfaceIEnvironment5{6///<summary>7///环境抽象8///</summary>9voidEnvironmentJudge();10}11///<summary>12///水下环境的13///</summary>14publicclassUnderwater:IEnvironment15{1617publicvoidEnvironmentJudge()18{19Console.WriteLine("在水下的");20}21}22///<summary>23///真空环境下的24///</summary>25publicclassEmpty:IEnvironment26{2728publicvoidEnvironmentJudge()29{30Console.WriteLine("真空下的");31}32}


上面是环境维度的结构,下面来看"武器"类型维度的结构:


1///<summary>2///武器3///</summary>4publicabstractclassWeapon5{6protectedIEnvironmentEnvironment=null;7///<summary>8///***9///</summary>10publicabstractvoidAttack();11}12///<summary>13///激光武器14///</summary>15publicclassLaserWeapon:Weapon16{17publicLaserWeapon():this(newUnderwater()){}//默认使用环境为水下18publicLaserWeapon(IEnvironmentenvironment)19{20base.Environment=environment;21}22publicoverridevoidAttack()23{24//LaserAttack25base.Environment.EnvironmentJudge();26Console.WriteLine("激光武器");27}28}29///<summary>30///×××武器31///</summary>32publicclassMissileWeapon:Weapon33{34publicMissileWeapon():this(newUnderwater()){}35publicMissileWeapon(IEnvironmentenvironment)36{37base.Environment=environment;38}39publicoverridevoidAttack()40{41//MissileAttack42base.Environment.EnvironmentJudge();43Console.WriteLine("×××武器");44}45}


如图2的所示现在的对象结构:

类型都已经定义完成了,现在来看一下客户端调用代码:

1//Weaponweapon=newLaserWeapon();//这里已经默认的是水下坏境了2Weaponweapon=newMissileWeapon(newEmpty());3weapon.Attack();


结果如图3所示:

桥接模式就讲到这里.下一个篇幅将讲到怎么把"武器"安装到"部件"上使用的“装饰者模式”。