妹子開始抱怨起來
妹子的遊戲是個對戰類的遊戲,其中有一個玩家的概念,玩家能夠攻擊,這個業務正是妹子開始撓頭的起點程序員
產品經理:玩家有不少屬性,例如:身高,性別 blalalala ,玩家能夠攻擊其餘玩家。
YY妹子寫程序也是很利索,一天就把程序搞定了,並且還抽象出一個palyer的基類出來,堪稱高級程序員必備技能。算法
//玩家的基礎抽象類 abstract class Player { public string Name { get; set; } //. //. //. //玩家的攻擊 public abstract void Attack(); } //真實玩家 class PersonPlayer : Player { public override void Attack() { //to do something return; } }
產品經理:遊戲裏我須要增長機器人玩家來增長遊戲在線的人數,機器人屬性和真實玩家同樣,可是攻擊不太同樣
這個需求修改仍是難不住YY妹子,沒過幾天代碼改好了,增長了一個機器人玩家的類,用到了OO的繼承。在這裏爲玩家抽象類點贊編程
class RobotPlayer : Player { public override void Attack() { //修改攻擊內容等 to do something return; } }
產品經理:我要建立一批相似玩家的怪物,沒有真實玩家的那些屬性,可是和真實玩家同樣有攻擊行爲
這個時候YY妹子終於意識到攻擊是一種行爲了,須要抽象出接口來了。設計模式
//攻擊接口 interface IAttack { void Attack(); } //玩家的基礎抽象類 abstract class Player { //其餘屬性代碼省略一萬字 } //真實玩家 class PersonPlayer :Player, IAttack { public void Attack() { //to do something return; } } //機器人玩家 class RobotPlayer :Player, IAttack { public void Attack() { // to do something return; } } //怪物玩家 class MonsterPlayer : IAttack { public void Attack() { // to do something return; } }
到了這裏,咱們遇到了你們耳熟能詳的面向接口編程,沒錯,這個作法是對的。這也是設計的一大原則:程序依賴接口,不依賴具體實現。這裏要爲YY繼續點贊。順便說一下,在多數狀況下,不少同窗就到此爲止了
產品經理:我如今要設計玩家的攻擊方式了,目前有遠程攻擊,近程攻擊,貼身攻擊這三類,其餘需求 blalalalala。
聽說此刻YY妹子的內心是一萬頭羊駝飄過的狀態。此次要怎麼設計呢?這也是菜菜要說的重點部分。
如今咱們須要靜下心來思考一番了,爲何咱們使用了面向接口編程,遇到此次需求,程序仍是須要修改不少東西呢?架構
設計原則:找出應用中未來可能變化的地方,把他們獨立出來,不須要和那些不變的代碼混在一塊兒。
這樣的概念很簡單,確是每一個設計模式背後的靈魂所在。到目前爲止,設計中不斷在變的是Attack這個接口,更準確的應該是Attack這個行爲。面向接口這個概念沒有問題,是大多數人把語言層面和設計層面的接口含義沒搞明白,真正的面向接口編程更偏向於面向架構中行爲的編程,另一個角度也能夠看作是利用OO的多態原則。ide
說到這裏,咱們能夠更系統的給Attack行爲定義成一類行爲,而具體的行爲實現能夠描述爲一簇算法。想一想看,Attack行爲其實不止做用於player的類型,改日產品經理新加一個XX對象也具備攻擊行爲,理想的狀況是我只須要讓這個xx對象有Attack行爲便可,而不須要改動之前的任何代碼。你如今是否是對這個行爲的定義理解的更深入一些。spa
兩外一點,到目前爲止YY妹子的代碼中一直是以繼承的方式來實現行爲,這會有什麼問題呢?假如要想在程序運行時動態修改player的Attack行爲,會顯得力不從心了。設計
談到這裏又引入了其餘一個設計理念:通常狀況下,有一個可能比是一個更好。具體概念爲:多用組合,少用繼承。繼承一般狀況下適用於事物自己的一些特性,好比:玩家基類具備姓名這個屬性,繼承類徹底能夠繼承這個屬性,不會發生任何問題。而組合多用於行爲的設計方面,由於這個行爲類型,我可能會在多個事物中出現,用組合能實現更大的彈性設計。code
//攻擊行爲接口 interface IAttack { void Attack(); } class RemoteAttack : IAttack { public void Attack() { //遠程攻擊 } } class ShortAttack : IAttack { public void Attack() { //近程攻擊 } }
//玩家的基礎抽象類 abstract class Player { //其餘屬性代碼省略一萬字 } //真實玩家 class PersonPlayer : Player { //玩家能夠有攻擊的行爲 IAttack attack; public PersonPlayer(IAttack _attack) { attack = _attack; } public void Attack() { //調用行爲一簇算法的實現 attack.Attack(); return; } //玩家能夠運行時修改攻擊行爲 public void ChangeAttack(IAttack _attack) { attack = _attack; } }
接口是一種規範和約束,更高層的抽象更像是一類行爲,面向接口編程只是代碼層體現的一種格式體現而已,真正的面向接口設計更貼近面向行爲編程
添加關注,查看更精美版本,收穫更多精彩