1. 程式人生 > 實用技巧 >設計模式之面向介面程式設計

設計模式之面向介面程式設計

02第一次需求

玩家有很多屬性,例如:身高,性別 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; } }

01第二次需求遊戲裡要增加機器人玩家來增加線上的人數,屬性和真實玩家一樣,但是攻擊不太一樣產品狗

這個需求修改還是難不住YY妹子,沒過幾天程式碼改好了,增加了一個機器人玩家的類,用到了OO的繼承。在這裡為玩家抽象類點贊

class RobotPlayer : Player
    {
        public override void Attack()
        {
            
//修改攻擊內容等 to do something return; } }

02第三次需求我要建立一批怪物,沒有真實玩家的那些屬性,但是和真實玩家一樣有攻擊行為產品狗

這個時候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繼續點贊。順便說一下,在多數情況下,很多同學就到此為止了

01第四次需求我要設計玩家的攻擊方式了,目前有遠端攻擊,近程攻擊,貼身攻擊這三類,其他需求 blalalalala。產品狗

據說此刻YY妹子的心裡是一萬頭羊駝飄過的狀態。這次要怎麼設計呢?這也是菜菜要說的重點部分。

現在我們需要靜下心來思考一番了,為什麼我們使用了面向介面程式設計,遇到這次需求,程式還是需要修改很多東西呢?

設計原則:找出應用中將來可能變化的地方,把他們獨立出來,不需要和那些不變的程式碼混在一起。

這樣的概念很簡單,確是每個設計模式背後的靈魂所在。到目前為止,設計中不斷在變的是Attack這個介面,更準確的應該是Attack這個行為。面向介面這個概念沒有問題,是大多數人把語言層面和設計層面的介面含義沒搞明白,真正的面向介面程式設計更偏向於面向架構中行為的程式設計,另外一個角度也可以看做是利用OO的多型原則。

說到這裡,我們可以更系統的給Attack行為定義成一類行為,而具體的行為實現可以描述為一簇演算法。想想看,Attack行為其實不止作用於player的型別,改日產品經理新加一個XX物件也具有攻擊行為,理想的情況是我只需要讓這個xx物件有Attack行為即可,而不需要改動以前的任何程式碼。你現在是不是對這個行為的定義理解的更深刻一些。

另外一點,到目前為止YY妹子的程式碼中一直是以繼承的方式來實現行為,這會有什麼問題呢?假如要想在程式執行時動態修改player的Attack行為,會顯得力不從心了。

談到這裡又引入了其他一個設計理念:一般情況下,有一個可能比是一個更好。具體概念為:多用組合,少用繼承。繼承通常情況下適用於事物本身的一些特性,比如:玩家基類具有姓名這個屬性,繼承類完全可以繼承這個屬性,不會發生任何問題。而組合多用於行為的設計方面,因為這個行為型別,我可能會在多個事物中出現,用組合能實現更大的彈性設計

02面向行為程式設計(千言萬語不如10行程式碼)

封裝行為一簇

//攻擊行為介面
    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;
        }
    } 

寫在最後

介面是一種規範和約束,更高層的抽象更像是一類行為,面向介面程式設計只是程式碼層體現的一種格式體現而已,真正的面向介面設計更貼近面向行為程式設計

引用 跨平臺文章:

https://mp.weixin.qq.com/s/QSJb1rhfVIRBrpqMob7_GA