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

640?wx_fmt=gif

菜菜哥,出大事啦

640?wx_fmt=png640?wx_fmt=jpeg

怎么了,你和男票分手了?很正常,谁让你男票是产经经理呢

640?wx_fmt=png640?wx_fmt=jpeg

不是啦,是我做的一个小游戏,需求又变了,程序我快改不动了

640?wx_fmt=png640?wx_fmt=jpeg

说来让我欢乐一下?

640?wx_fmt=png640?wx_fmt=jpeg

菜菜哥,咱两还能不能好好相处了

640?wx_fmt=png640?wx_fmt=jpeg

玩笑 玩笑,show  time

640?wx_fmt=png640?wx_fmt=jpeg640?wx_fmt=png

妹子开始抱怨起来

640?wx_fmt=png01业务背景

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

02第一次需求


玩家有很多属性,例如:身高,性别 blalalala ,玩家可以攻击其他玩家。产品狗

YY妹子写程序也是很利索,一天就把程序搞定了,而且还抽象出一个palyer的基类出来,堪称高级程序员必备技能

//玩家的基础抽象类
   abstract class Player
    {
        public string Name { getset; }
        //.
        //.
        //.

        //玩家的攻击
       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 :PlayerIAttack
    {
        public  void Attack()
        
{
            //to do something 
            return;
        }
    }
    //机器人玩家
    class RobotPlayer :PlayerIAttack
    {
        public  void Attack()
        
{
            // to do something 
            return;
        }
    }
    //怪物玩家
    class MonsterPlayer : IAttack
    {
        public  void Attack()
        
{
            // to do something 
            return;
        }
    }


640?wx_fmt=png

到了这里,我们遇到了大家耳熟能详的面向接口编程,没错,这个做法是对的。这也是设计的一大原则:程序依赖接口,不依赖具体实现。这里要为YY继续点赞。顺便说一下,在多数情况下,很多同学就到此为止了

640?wx_fmt=png01第四次需求我要设计玩家的攻击方式了,目前有远程攻击,近程攻击,贴身攻击这三类,其他需求 blalalalala。产品狗

据说此刻YY妹子的心里是一万头羊驼飘过的状态。这次要怎么设计呢?这也是菜菜要说的重点部分。

现在我们需要静下心来思考一番了,为什么我们使用了面向接口编程,遇到这次需求,程序还是需要修改很多东西呢?


640?wx_fmt=png

设计原则:找出应用中将来可能变化的地方,把他们独立出来,不需要和那些不变的代码混在一起。

640?wx_fmt=png


这样的概念很简单,确是每个设计模式背后的灵魂所在。到目前为止,设计中不断在变的是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;
        }
    }   


写在最后

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


640?wx_fmt=png


640?wx_fmt=gif

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

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

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

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

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

互联网之路,菜菜与君一同成长

长按识别二维码关注

640?wx_fmt=jpeg

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/316872.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Codeforces:779(div2)

前言 solve 4 rnk247 占了罚时的便宜。 CF不占罚时便宜就会被罚时占便宜 感觉这场似乎都是性质题,一眼看出性质就秒了,看不出就很难做出来了。 C似乎卡了很多人。但我做起来还好。 D2做不出来有些懊恼。 E是妙题。 题目 A 水题,保证male…

我们为什么要搞长沙.NET技术社区(4)

我们为什么要搞长沙.NET技术社区(4)邹溪源,2019年3月7日Ps:文中的.NET 包括且不限定于传统.NET Framework技术和.NET Core技术。1. 楔子昨天(2019年3月6日)晚餐时间,有幸得到长沙技术圈资深.NET开发者出生…

P1290 欧几里德的游戏

P1290 欧几里德的游戏 题意: 给定两个正整数 M 和 N,从 Stan 开始,从其中较大的一个数,减去较小的数的正整数倍,当然,得到的数不能小于 0。然后是 Ollie进行同样的操作,直到一个人得到0&#…

C#机器学习之判断日报是否合格

原文作者:心莱科技肖鑫简单来说机器学习的核心步骤在于“获取学习数据;选择机器算法;定型模型;评估模型,预测模型结果”,下面本人就以判断日报内容是否合格为例为大家简单的阐述一下C#的机器学习。第一步&a…

SignalR2结合ujtopo实现拓扑图动态变化

上一篇文章基于jTopo的拓扑图设计工具库ujtopo,介绍了拓扑设计工具,这一篇我们使用SignalR2结合ujtopo实现拓扑图的动态变化。仅仅作为演示,之前的文章SignalR2简易数据看板演示,用一个小的示例演示了SignalR作为数据看板的用法&a…

Ocelot 入门Demo系列(01-Ocelot极简单Demo及负载均衡的配置)

来源:https://www.cnblogs.com/7tiny/p/10493805.html【前言】Ocelot是一个用.NET Core实现并且开源的API网关,它功能强大,包括了:路由、请求聚合、服务发现、认证、鉴权、限流熔断、并内置了负载均衡器与Service Fabric、Butterf…

博弈论(基础概念+例题)

博弈论(b站视频) 文章目录一些概念以Nim游戏为例Nim游戏介绍定义 必败/必胜局面必败/必胜局面的判定引理Nim游戏判定引理的等价命题有向图游戏对判定引理的数学描述-Sg函数有向图游戏的和题目:[有向图游戏][有向图游戏的和][构造/转化类]一些概念 以Nim游戏为例 Ni…

.NET Core 3.0 linux 部署小贴士

dotnet core 3.0 目前还是测试版,在linux下安装 sdk 需要有一些注意事项1.下载urlhttps://dotnet.microsoft.com/download/thank-you/dotnet-sdk-3.0.100-preview-009812-linux-x64-binaries2.安装指令mkdir -p $HOME/dotnet && tar zxf dotnet-sdk-3.0.100…

PuppeteerSharp: 更友好的 Headless Chrome C# API

前端就有了对 headless 浏览器的需求,最多的应用场景有两个UI 自动化测试:摆脱手工浏览点击页面确认功能模式爬虫:解决页面内容异步加载等问题也就有了很多杰出的实现,前端经常使用的莫过于 PhantomJS 和 selenium-webdriver&…

中国.NET:东莞+长沙.NET俱乐部现场花絮及合肥、苏州、上海等地活动预

《传承有序》与微软技术的发展历程相似,微软俱乐部的发展经历着沉沉浮浮,曾经随着微软走向封闭与固执,.NET社区年轻一代的声音被忽略,.NET社区后继无人。社区的沉默是可怕的,很多社区沉寂消亡。但是在2018年&#xff0…

【AcWing 235. 魔法珠

【AcWing 235. 魔法珠 题意: 有n堆魔法珠,第i堆有ai个,两个人轮流进行以下操作: 当轮到某人操作时,如果每堆中魔法珠的数量均为 1,那么他就输了。 问谁赢谁输 题解: 经典博弈论问题 注意本…

Abp vNext 切换MySql数据库

Abp vNext是Abp的下一代版本,目前还在经一步完善,代码已经全部重写了,好的东西保留了下来,去除了很多笨重的东西,从官宣来看,Abp vNext主要是为了以后微服务架构而诞生的。从源码来看,Abp vNext…

采用.NET CORE的全异步模式打造一款免费的内网穿透工具--NSmartProxy

什么是NSmartProxy?NSmartProxy是一款免费的内网穿透工具。特点跨平台,客户端和服务端均可运行在MacOS,Linux,Windows系统上;使用方便,配置简单;多端映射,一个NSmart Proxy客户端可以…

Acwing 236. 格鲁吉亚和鲍勃(博弈论妙题)

Acwing 236. 格鲁吉亚和鲍勃 题意: 一排网格,将网格从左到右依次编号 1,2,3,…,并将 N 个西洋棋棋子放在不同的网格上,如下图所示: 两个人轮流移动棋子 每次玩家选择一个棋子,并将其向左移动…

.NET Core 跨平台 串口通讯 ,Windows/Linux 串口通讯

1,前言开发环境:在 Visual Studio 2017,.NET Core 2.x串口通讯用于设备之间,传递数据,物联网设备中广泛使用串口方式连接通讯,物联网通讯协议 :Modbus 协议 ASCII、RTU、TCP模式是应用层的协议&…

Game of Cards Gym - 102822G

Game of Cards Gym - 102822G 题意: 小兔子和小马喜欢玩奇怪的纸牌游戏。现在,他们正在玩一种叫做0123游戏的纸牌游戏。桌子上有几张牌。其中c0标记为0,c1标记为1,c2标记为2,c3标记为3。小兔子和小马轮流玩游戏&…

开源组件ExcelReport 3.x.x 使用手册(为.netcore而来

ExcelReport转眼已经开源4年了,期间有很长时间也停止了对它的维护。18年年末有人联系到我,说“兄弟,ExcelReport不错,但什么时候支持.netcore呢?”。我寥寥的回了几句搪塞的话,也没当回事。后来这兄弟又来问…

《.NET Core 和前后端那些事儿》技术交流活动纪实

长沙.NET技术社区.NET Core和前后端那些事儿技术交流纪实2019年3月10日,下午,在位于沁园春御院的长沙市互联网活动基地,在长沙市.NET技术社区的组织下,长沙市.NET技术圈第一次纯粹的技术沙龙在这里召开。这次活动总共参加人数超过…

10个小技巧助您写出高性能的ASP.NET Core代码

今天这篇文章我们来聊一聊如何提升并优化ASP.NET Core应用程序的性能,本文的大部分内容来自翻译,当然中间穿插着自己的理解,希望对大家有所帮助!话不多说开始今天的主题吧!我们都知道性能是公共网站取得成功的关键因素…

CF 1529D Kavi on Pairing Duty

CF 1529D Kavi on Pairing Duty 题意&#xff1a; 有2 * n个点&#xff0c;现在要求两个点连成线段&#xff0c;每个连法都可以得到n个线段&#xff0c;合法的连接方式为&#xff1a;连接的n个线段&#xff0c;任意两个线段要么长度相等&#xff0c;要么有包含关系 n<1e6 …