问题分析:假如我们需要开发一个同时支持PC和手机的坦克游戏,游戏在PC和手机上功能都一样,都有同样的类型,面临同样的功能需求变化,比如坦克可能有多种不同的型号:T50,T75,T90..对于其中的坦克设计,我们可能很容易设计出来一个Tank的抽象类,然后各种不同型号的Tank继承自该类,但是PC和手机上的图形绘制、声效、操作等实现完全不同...因此对于各种型号的坦克,都 要提供各种不同平台上的坦克实现;而这样的设计带来了很多问题:有很多重复代码,类的结构过于复杂,难以维护,最致命的是引入任何新的平台,比如TV上的Tank游戏,都会让整个类层次级结构复杂化
动机:思考上述问题的症结,事实上由于Tank类型的固有逻辑,使得Tank类型具有了两个变化的维度——一个变化的维度为“平台的变化”,一个变化的维度为“型号的变化”;如何应对这种“多维度的变化”?如何利用面向对象技术使得Tank类型可以轻松地沿着“平台”和“型号”两个方向变化,而不引入额外的复杂度
意图:将抽象部分和实现部分分离(将一个事物中多个维度的变化分离),使它们可以独立的变化 即将不同纬度的变化抽象出来,并子类化它们,用对象组合的方式实现应对其变化
可适用性:
- 你不希望在抽象和它的实现部分之间有一个固定的绑定关系。例如这种情况可能是因为,在程序运行时刻实现部分应可以被选择或者切换。
- 类的抽象以及它的实现都应该可以通过生成子类的方法加以扩充。这时B r i d g e 模式使你可以对不同的抽象接口和实现部分进行组合,并分别对它们进行扩充。
- 对一个抽象的实现部分的修改应对客户不产生影响,即客户的代码不必重新编译。
- (C + +)你想对客户完全隐藏抽象的实现部分。在C + +中,类的表示在类接口中是可见的。
- 有许多类要生成。这样一种类层次结构说明你必须将一个对象分解成两个部分。R u m b a u g h 称这种类层次结构为“嵌套的普化”(nested generalizations )。
- 你想在多个对象间共享实现(可能使用引用计数),但同时要求客户并不知道这一点。一个简单的例子便是C o p l i e n 的S t r i n g 类[ C o p 9 2 ],在这个类中多个对象可以共享同一个字符串表示(S t r i n g R e p )。
UML图解:
示例代码:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 /*** 7 * 没有使用桥接模式之前的设计实现代码 8 * ***/ 9 namespace Bridge 10 { 11 12 public abstract class Tank 13 { 14 public abstract void Run(); 15 public abstract void Shot(); 16 public abstract void Stop(); 17 } 18 19 public class T50 : Tank 20 { 21 22 public override void Run() 23 { 24 //.... 25 } 26 27 public override void Shot() 28 { 29 //.... 30 } 31 32 public override void Stop() 33 { 34 //.... 35 } 36 } 37 public class PCT50 : T50 38 { 39 public override void Run() 40 { 41 //.... 42 } 43 44 public override void Shot() 45 { 46 //.... 47 } 48 49 public override void Stop() 50 { 51 //.... 52 } 53 } 54 public class MobileT50 : T50 55 { 56 public override void Run() 57 { 58 //.... 59 } 60 61 public override void Shot() 62 { 63 //.... 64 } 65 66 public override void Stop() 67 { 68 //.... 69 } 70 } 71 public class TVT50 : T50 72 { 73 public override void Run() 74 { 75 //.... 76 } 77 78 public override void Shot() 79 { 80 //.... 81 } 82 83 public override void Stop() 84 { 85 //.... 86 } 87 } 88 89 90 91 public class T75 : Tank 92 { 93 94 public override void Run() 95 { 96 //.... 97 } 98 99 public override void Shot() 100 { 101 //.... 102 } 103 104 public override void Stop() 105 { 106 //.... 107 } 108 } 109 public class PCT75 : T75 110 { 111 public override void Run() 112 { 113 //.... 114 } 115 116 public override void Shot() 117 { 118 //.... 119 } 120 121 public override void Stop() 122 { 123 //.... 124 } 125 } 126 public class MobileT75 : T75 127 { 128 public override void Run() 129 { 130 //.... 131 } 132 133 public override void Shot() 134 { 135 //.... 136 } 137 138 public override void Stop() 139 { 140 //.... 141 } 142 } 143 public class TVT75 : T75 144 { 145 public override void Run() 146 { 147 //.... 148 } 149 150 public override void Shot() 151 { 152 //.... 153 } 154 155 public override void Stop() 156 { 157 //.... 158 } 159 } 160 161 public class T90 : Tank 162 { 163 164 public override void Run() 165 { 166 //.... 167 } 168 169 public override void Shot() 170 { 171 //.... 172 } 173 174 public override void Stop() 175 { 176 //.... 177 } 178 } 179 public class PCT90 : T90 180 { 181 public override void Run() 182 { 183 //.... 184 } 185 186 public override void Shot() 187 { 188 //.... 189 } 190 191 public override void Stop() 192 { 193 //.... 194 } 195 } 196 public class MobileT90 : T90 197 { 198 public override void Run() 199 { 200 //.... 201 } 202 203 public override void Shot() 204 { 205 //.... 206 } 207 208 public override void Stop() 209 { 210 //.... 211 } 212 } 213 public class TVT90 : T90 214 { 215 public override void Run() 216 { 217 //.... 218 } 219 220 public override void Shot() 221 { 222 //.... 223 } 224 225 public override void Stop() 226 { 227 //.... 228 } 229 } 230 231 /*** 232 * 实现的缺点:子类繁衍多,不能应对变化 233 * ***/ 234 }using System; 235 using System.Collections.Generic; 236 using System.Linq; 237 using System.Text; 238 239 /*** 240 * 使用Bridge模式后的代码实现 241 * ***/ 242 namespace Bridge 243 { 244 /// <summary> 245 /// 将不同平台坦克实现抽象出来(应对平台变化) 246 /// </summary> 247 public abstract class TankPlatformImplementation 248 { 249 public abstract void MoveTo(); 250 public abstract void Draw(); 251 public abstract void Stop(); 252 } 253 254 /// <summary> 255 /// PC平台的Tank 256 /// </summary> 257 public class PCTankImplementation:TankPlatformImplementation 258 { 259 260 public override void MoveTo() 261 { 262 //PC上的实现代码 263 } 264 265 public override void Draw() 266 { 267 //PC上的实现代码 268 } 269 270 public override void Stop() 271 { 272 //PC上的实现代码 273 } 274 } 275 276 /// <summary> 277 /// Mobile平台的Tank 278 /// </summary> 279 public class MobileTankImplementation:TankPlatformImplementation 280 { 281 282 public override void MoveTo() 283 { 284 // Mobile上的实现代码 285 } 286 287 public override void Draw() 288 { 289 // Mobile上的实现代码 290 } 291 292 public override void Stop() 293 { 294 // Mobile上的实现代码 295 } 296 } 297 298 /// <summary> 299 /// 坦克抽象类(应对坦克型号的变化) 300 /// </summary> 301 public abstract class Tank 302 { 303 TankPlatformImplementation tanklmp;//对象组合 304 public Tank( TankPlatformImplementation tanklmp) 305 { 306 this.tanklmp = tanklmp; 307 } 308 public abstract void Run(); 309 public abstract void Shot(); 310 public abstract void Stop(); 311 } 312 313 public class T50 : Tank 314 { 315 public T50(TankPlatformImplementation tanklmp) 316 : base(tanklmp) 317 { 318 319 } 320 321 public override void Run() 322 { 323 //.... 324 //using tanklmp do something... 325 //... 326 } 327 328 public override void Shot() 329 { 330 //.... 331 //using tanklmp do something... 332 //... 333 } 334 335 public override void Stop() 336 { 337 //.... 338 //using tanklmp do something... 339 //... 340 } 341 } 342 343 public class T75 : Tank 344 { 345 public T75(TankPlatformImplementation tanklmp) 346 : base(tanklmp) 347 { 348 349 } 350 351 public override void Run() 352 { 353 //.... 354 //using tanklmp do something... 355 //... 356 } 357 358 public override void Shot() 359 { 360 //.... 361 //using tanklmp do something... 362 //... 363 } 364 365 public override void Stop() 366 { 367 //.... 368 //using tanklmp do something... 369 //... 370 } 371 } 372 373 public class App 374 { 375 public static void Main() 376 { 377 //手机平台游戏 378 TankPlatformImplementation mobileTank=new MobileTankImplementation(); 379 Tank tank=new T50(mobileTank); 380 //tank.Shot(); 381 } 382 } 383 }
注:本示例代码是本人学习Webcast C#面向对象设计模式纵横谈系列讲座视频时,跟着李建忠老师一步一步的编写的,在此奉献出来,仅供大家参考