GOF之桥接模式
引入問(wèn)題:
假如我們需要開(kāi)發(fā)一個(gè)同事支持PC和手機(jī)的坦克游戲,游戲在PC和手機(jī)上功能都一樣,都有同樣的類(lèi)型,面臨同樣的功能需求變化,比如坦克可能有多種不同的型號(hào):T50,T75,T90...
但是PC和手機(jī)上的圖形繪制、聲效、操作等實(shí)現(xiàn)完全不同...因此對(duì)于各種型號(hào)的坦克,都要提供不同平臺(tái)上的坦克實(shí)現(xiàn)。
動(dòng)機(jī)(Motivation)
思考上述問(wèn)題的癥結(jié):事實(shí)上由于Tank類(lèi)型的固有邏輯,使得Tank類(lèi)型具有了兩個(gè)變化的維度---一個(gè)變化的維度為“平臺(tái)的變化”,一個(gè)變化的維度為“型號(hào)的變化”。
如何應(yīng)對(duì)這種“多維度的變化”?如何利用面向?qū)ο蠹夹g(shù)來(lái)使得Tank類(lèi)型可以輕松地沿著“平臺(tái)”和“型號(hào)”兩個(gè)方向變化,而不引入額外的復(fù)雜度?
意圖(Intent)
將抽象部分與實(shí)現(xiàn)部分分離,使它們都可以獨(dú)立的變化。
結(jié)構(gòu)(Structure)
代碼實(shí)現(xiàn):
1 一種維度的變化 2 public abstract class TankPlatformImplementation 3 { 4 public abstract void MoveTo(); 5 public abstract void DrawTank(); 6 public abstract void DoShot(); 7 } 8 9 public class PCTankImplementation : TankPlatformImplementation 10 { 11 12 public override void MoveTo() 13 { 14 Console.WriteLine("PC端移動(dòng)"); 15 } 16 17 public override void DrawTank() 18 { 19 Console.WriteLine("PC端畫(huà)坦克"); 20 } 21 22 public override void DoShot() 23 { 24 Console.WriteLine("PC端攻擊"); 25 } 26 } 27 28 public class MobileTankImplementation : TankPlatformImplementation 29 { 30 31 public override void MoveTo() 32 { 33 Console.WriteLine("移動(dòng)端移動(dòng)"); 34 } 35 36 public override void DrawTank() 37 { 38 Console.WriteLine("移動(dòng)端畫(huà)坦克"); 39 } 40 41 public override void DoShot() 42 { 43 Console.WriteLine("移動(dòng)端攻擊"); 44 } 45 } 1 另一種維度的變化 2 public abstract class Tank 3 { 4 protected TankPlatformImplementation tpimp; 5 public abstract void Run(); 6 public abstract void Stop(); 7 } 8 9 public class T50 : Tank 10 { 11 public T50(TankPlatformImplementation tpimp) 12 { 13 this.tpimp = tpimp; 14 } 15 public void MoveTo() 16 { 17 Console.Write("T50的"); 18 tpimp.MoveTo(); 19 } 20 public void DoShot() 21 { 22 Console.Write("T50的"); 23 tpimp.DoShot(); 24 } 25 public void DrawTank() 26 { 27 Console.Write("T50的"); 28 tpimp.DrawTank(); 29 } 30 31 32 public override void Run() 33 { 34 Console.WriteLine("T50跑"); 35 } 36 37 public override void Stop() 38 { 39 Console.WriteLine("T50停"); 40 } 41 } 42 public class T75 : Tank 43 { 44 public T75(TankPlatformImplementation tpimp) 45 { 46 this.tpimp = tpimp; 47 } 48 public void MoveTo() 49 { 50 Console.Write("T75的"); 51 tpimp.MoveTo(); 52 } 53 public void DoShot() 54 { 55 Console.Write("T75的"); 56 tpimp.DoShot(); 57 } 58 public void DrawTank() 59 { 60 Console.Write("T75的"); 61 tpimp.DrawTank(); 62 } 63 64 public override void Run() 65 { 66 Console.WriteLine("T75跑"); 67 } 68 69 public override void Stop() 70 { 71 Console.WriteLine("T75停"); 72 } 73 } 74 public class T90 : Tank 75 { 76 public T90(TankPlatformImplementation tpimp) 77 { 78 this.tpimp = tpimp; 79 } 80 public void MoveTo() 81 { 82 Console.Write("T90的"); 83 tpimp.MoveTo(); 84 } 85 public void DoShot() 86 { 87 Console.Write("T90的"); 88 tpimp.DoShot(); 89 } 90 public void DrawTank() 91 { 92 Console.Write("T90的"); 93 tpimp.DrawTank(); 94 } 95 96 public override void Run() 97 { 98 Console.WriteLine("T90跑"); 99 } 100 101 public override void Stop() 102 { 103 Console.WriteLine("T90停"); 104 } 105 } 1 主函數(shù)的調(diào)用 2 static void Main(string[] args) 3 { 4 T75 tank = new T75(new MobileTankImplementation()); 5 tank.DrawTank(); 6 tank.DoShot(); 7 tank.MoveTo(); 8 tank.Run(); 9 tank.Stop(); 10 Console.ReadKey(); 11 }Bridge模式的幾個(gè)要點(diǎn):
Bridge模式使用“對(duì)象間的組合關(guān)系”解耦了抽象和實(shí)現(xiàn)之間固有的綁定關(guān)系,使得抽象(Tank的型號(hào))和實(shí)現(xiàn)(不同的平臺(tái))可以沿著各自的維度來(lái)變化。
所謂抽象和實(shí)現(xiàn)沿著各自的維度的變化,即“子類(lèi)化”它們,比如不同的Tank型號(hào)子類(lèi),和不同的平臺(tái)子類(lèi)。得到各個(gè)子類(lèi)之后,便可以任意組合它們,從而獲得 不同平臺(tái)上的不同型號(hào)。
Bridge模式有時(shí)候類(lèi)似于多繼承方案,但是多繼承方案往往違背單一職責(zé)原則(即一個(gè)類(lèi)只有一個(gè)變化的原因),復(fù)用性較差。Bridge模式是比多繼承方案更好的解決方法。
Bridge模式的應(yīng)用一般在“兩個(gè)非常強(qiáng)的變化維度”,有時(shí)候即使有兩個(gè)變化的維度,但是某個(gè)方向的變化維度并不劇烈--換言之兩個(gè)變化不會(huì)導(dǎo)致縱橫交錯(cuò)的結(jié)果,并不一定要使用Bridge模式。
?
轉(zhuǎn)載于:https://www.cnblogs.com/pushudepu/p/6037796.html
總結(jié)
- 上一篇: MyEclipse 中自动安插作者、注释
- 下一篇: DSP using MATLAB 示例E