乐趣区

关于后端:你的面向接口编程一定对吗

妹子开始埋怨起来

业务背景

妹子的游戏是个对战类的游戏,其中有一个玩家的概念,玩家能够攻打,这个业务正是妹子开始挠头的终点

第一次需要

产品经理:玩家有很多属性,例如:身高,性别 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 的多态准则。

说到这里,咱们能够更零碎的给 Attack 行为定义成一类行为,而具体的行为实现能够形容为一簇算法。想想看,Attack 行为其实不止作用于 player 的类型,改日产品经理新加一个 XX 对象也具备攻击行为,现实的状况是我只须要让这个 xx 对象有 Attack 行为即可,而不须要改变以前的任何代码。你当初是不是对这个行为的定义了解的更粗浅一些。

两外一点,到目前为止 YY 妹子的代码中始终是以继承的形式来实现行为,这会有什么问题呢?如果要想在程序运行时动静批改 player 的 Attack 行为,会显得力不从心了。

谈到这里又引入了其余一个设计理念:个别状况下, 有一个可能比是一个更好。 具体概念为:多用组合,少用继承。继承通常状况下实用于事物自身的一些个性,比方:玩家基类具备姓名这个属性,继承类齐全能够继承这个属性,不会产生任何问题。而组合多用于行为的设计方面,因为这个行为类型,我可能会在多个事物中呈现,用组合能实现更大的弹性设计。

面向行为编程(一言半语不如 10 行.Net Core 代码)

封装行为一簇
 // 攻击行为接口
    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;}
    }   

写在最初

接口是一种标准和束缚,更高层的形象更像是一类行为,面向接口编程只是代码层体现的一种格局体现而已,真正的面向接口设计更贴近面向行为编程


增加关注,查看更精美版本,播种更多精彩

退出移动版