前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >程序员过关斩将--你的面向接口编程一定对吗?

程序员过关斩将--你的面向接口编程一定对吗?

作者头像
架构师修行之路
发布2019-07-23 16:24:15
2810
发布2019-07-23 16:24:15
举报
文章被收录于专栏:架构师架构师架构师

01

业务背景

妹子的游戏是个对战类的游戏,其中有一个玩家的概念,玩家可以攻击,这个业务正是妹子开始挠头的起点

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;
        }
    }   

写在最后

接口是一种规范和约束,更高层的抽象更像是一类行为,面向接口编程只是代码层体现的一种格式体现而已,真正的面向接口设计更贴近面向行为编程

程序员修神之路--高并发下为什么更喜欢进程内缓存

程序员修神之路--高并发优雅的做限流(有福利)

程序员过关斩将--快速迁移10亿级数据

程序员修神之路--分布式缓存的一条明路(附代码)

程序员修仙之路--把用户访问记录优化到极致

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-03-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 架构师修行之路 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档