下面是一个军事演习中各种作战工具补充燃料的场景,场景的燃料需要想后勤总部及时报告,现在公司拿到了这么一个进行燃料
分配的项目,交给你手上实现。
惯性思维分析:首先不管是什么工具都应该有个类型嘛,其次应该有个报告当前油耗状态的或者说燃料需求的方法嘛,嗯差不多
了,对于实现燃料请求够了,好我们先弄一个Vechicle的基类嘛(把类型名称放进去)可以减少一些公关属性的编写,好了可以来实现
这些功能,开始编码,于是有下面的代码:
public class Vehicle
public class Airplane : Vehicle
public class Car : Vehicle
public class FuelingStation
但是过了一会儿上面来通知了,现在增加了几个Track装甲车要加进去,简单在创建的Track类基础Vechicle类,然后你开始不得不
修改FuelingStation 中的AddFuelToTruck 方法,添加一个if else结构,其实也没什么,但是2个小时后勤总队给你拿了一份单子你傻了
尼玛,这么多种类,我的if/else要写几十上百个!这不是最要命的,最要命的是居然,居然还有用电池的,我靠!这么加啊,好吧也没什么可以重写弄个类就行了,但是你的FuelingStation 膨胀的让你无法忍受。
好了现在我们发现FuelingStation 这个类中的if/else判断有好多相似的地方,其实我们归结起来就是干一件事反馈出相应工具的燃料
需求状况。调用者根本不关心你内部的实现,他要的仅仅是报告最后一个状态而已。如果我们把这个提取为一个接口,那么我在访问的时候只需要调用接口中的这个方法,就能当前能源状态。我们让各个工具类实现这个接口会是怎样呢?
我们把代码修改一番:
public interface IFuelable
public class Airplane : Vehicle, IFuelable
public class Boat : Vehicle, IFuelable
好了,这个时候奇迹诞生了,我们的FuelingStation的实现,变成了这个月,
而且我可以肯定的说以后都这样了! 你新添加的工具只要实现我的IFuelable接口
我才不管你是干什么的呢!
这样一来我们就完成了一件事,很伟大的事情,只要是具有IFuelable特性的任何工具,直接集合里扔就是了,我保证给你
想要的结果,明天我走了,来了一个哥们,后勤总队说同学加一个坦克吧,OK直接加一个类就是,你别动我的代码基, 因为不
需要你懂,你自己该做的都在你自己的类里实现了。
public class FuelingStation
接口让我们的工作更简单。其实从整体上来说,这里涉及到了几个知识点:
第一当然是面向对象的第三个原则"依赖倒置"原则,即父类或者接口应该是能够提供所有子类共性的,不能因为父类是什么,所以我的子类就得怎么。
第二涉及到了多态,从IFuelable继承(实现)过来的 不同的实现类有不同的实现方法,从另一个角度看其实就是接口在不同的情况下有不同的状态。
第三设计到了代码的优化,细心得看,其实我就是为了避免使用过多的if/else或者swtich/case,避免长代码的出现
看到这里,ok啦,解释下,首先Sum是个扩张方法,传入的子类型是IEnumberable<TSource>其实就是一个泛型集合,然后函数的返回值有Many Much个数据类型,int,long,double,float反正是能求和的都有哦,我们知道Func是一个范函数及时我们所说的委托也可以认为是一个匿名函数,咋个想看个人了哈,我在这里把他看做是匿名函数了,也即是说我想用lamda表达式来完成这个Sum要求传递的那个函数参数,但是我不知道他那个sum到底实现到了哪一步,按理说应该是把我的集合来的值都计算完了再返回,不管先看它怎么实现的:
翻译API我们发现:
嗯这下我放心了,直接给他一个集合就是了,其实不用这么小心,比较人家Sum很明确就是求和嘛。
一句话完成几句话的工作的句子:
return vehiclesOnRoute.Sum(vehicle => vehicle.GetTotalAmountOfFuelNeededForVehicle());
也就是说我的新类:
public class FuelingStation
到了这一步可能程序有点令人看不懂了,没关系 ,看我下面的分解就明白了:
public class FuelingStation
我先定义了一个委托,这个委托使用Func范函数来规定他的签名(这个表述有点不准确,暂且这么说),然后再定义了这么一个与委托相对应的方法GetFuelNeed ,这些应该知道那一句lamda表达式干了什么工作了吧。