一直想寻找一种方式来表达C#中接口带给编程人员,尤其是写公共代码块,或者说写架构代码的编码人员是多么的富有诱惑力。
      下面是一个军事演习中各种作战工具补充燃料的场景,场景的燃料需要想后勤总部及时报告,现在公司拿到了这么一个进行燃料
分配的项目,交给你手上实现。
       惯性思维分析:首先不管是什么工具都应该有个类型嘛,其次应该有个报告当前油耗状态的或者说燃料需求的方法嘛,嗯差不多
了,对于实现燃料请求够了,好我们先弄一个Vechicle的基类嘛(把类型名称放进去)可以减少一些公关属性的编写,好了可以来实现
这些功能,开始编码,于是有下面的代码:

    public class Vehicle
   {
        protected String VehicleName { get; private set; }
   }

    public class Airplane : Vehicle
   {
       public int AmountOfFuelNeededToFillLeftFuelTank()
       {
           return 3;
       }
       public int AmountOfFuelNeededToFillRightFuelTank()
       {
           return 4;
       }
   }


   public class Boat : Vehicle
   {
       public int AmountOfFuelNeededToFillFrontFuelTank()
       {
           return 8;
       }
       public int AmountOfFuelNeededToFillRearFuelTank()
       {
           return 10;
       }
   }

    public class Car : Vehicle
   {
       public int AmountOfFuelNeededToFillTank()
       {
           return 12;
       }
   }

    public class FuelingStation
   {
       public int AddFuelToTruck(List<Vehicle> vehiclesOnRoute)
       {
           var amountOfFuelToLoadOnTruck = 0;
           foreach (var vehicle in vehiclesOnRoute)
           {
               if (vehicle is Car)
               {
                   amountOfFuelToLoadOnTruck += ((Car) vehicle)
                       .AmountOfFuelNeededToFillTank();
               }
               else if (vehicle is Airplane)
               {
                   amountOfFuelToLoadOnTruck += ((Airplane) vehicle).
                       AmountOfFuelNeededToFillLeftFuelTank();
                   amountOfFuelToLoadOnTruck += ((Airplane) vehicle).
                       AmountOfFuelNeededToFillRightFuelTank();
               }
               else if (vehicle is Boat)
               {
                   amountOfFuelToLoadOnTruck += ((Boat) vehicle).
                       AmountOfFuelNeededToFillFrontFuelTank();
                   amountOfFuelToLoadOnTruck += ((Boat) vehicle).
                       AmountOfFuelNeededToFillRearFuelTank();
               }
           }
           return amountOfFuelToLoadOnTruck;
       }
   }
      不错,基本代码实现完成,可以测试了,提交过去,OK。
      但是过了一会儿上面来通知了,现在增加了几个Track装甲车要加进去,简单在创建的Track类基础Vechicle类,然后你开始不得不
修改FuelingStation 中的AddFuelToTruck 方法,添加一个if else结构,其实也没什么,但是2个小时后勤总队给你拿了一份单子你傻了
尼玛,这么多种类,我的if/else要写几十上百个!这不是最要命的,最要命的是居然,居然还有用电池的,我靠!这么加啊,好吧也没什么可以重写弄个类就行了,但是你的FuelingStation  膨胀的让你无法忍受。
       好了现在我们发现FuelingStation   这个类中的if/else判断有好多相似的地方,其实我们归结起来就是干一件事反馈出相应工具的燃料
需求状况。调用者根本不关心你内部的实现,他要的仅仅是报告最后一个状态而已。如果我们把这个提取为一个接口,那么我在访问的时候只需要调用接口中的这个方法,就能当前能源状态。我们让各个工具类实现这个接口会是怎样呢?
     我们把代码修改一番:    

   public class Vehicle
   {
       protected String VehicleName { get; private set; }
   }

    public interface IFuelable
   {
       int GetTotalAmountOfFuelNeededForVehicle();
   }

   public class Airplane : Vehicle, IFuelable
   {
       public int GetTotalAmountOfFuelNeededForVehicle()
       {
           return AmountOfFuelNeededToFillLeftFuelTank() +
           AmountOfFuelNeededToFillRightFuelTank();
       }
       private int AmountOfFuelNeededToFillRightFuelTank()
       {
           return 80;
       }
       private int AmountOfFuelNeededToFillLeftFuelTank()
       {
          return 80;
       }
   }

    public class Boat : Vehicle, IFuelable
   {
       private  int AmountOfFuelNeededToFillFrontFuelTank()
       {
           return 8;
       }
       private int AmountOfFuelNeededToFillRearFuelTank()
       {
           return 10;
       }
       public int GetTotalAmountOfFuelNeededForVehicle()
       {
           return AmountOfFuelNeededToFillFrontFuelTank() +
           AmountOfFuelNeededToFillRearFuelTank();
       }
   }

   public class Car : Vehicle, IFuelable
   {
       public int GetTotalAmountOfFuelNeededForVehicle()
       {
           return AmountOfFuelNeededToFillTank();
       }
       private int AmountOfFuelNeededToFillTank()
       {
           return 12;
       }
   }

      好了,这个时候奇迹诞生了,我们的FuelingStation的实现,变成了这个月,
而且我可以肯定的说以后都这样了! 你新添加的工具只要实现我的IFuelable接口
我才不管你是干什么的呢!
       这样一来我们就完成了一件事,很伟大的事情,只要是具有IFuelable特性的任何工具,直接集合里扔就是了,我保证给你
想要的结果,明天我走了,来了一个哥们,后勤总队说同学加一个坦克吧,OK直接加一个类就是,你别动我的代码基, 因为不
需要你懂,你自己该做的都在你自己的类里实现了。

  public class FuelingStation
   {
       public int AddFuelToTruck(List<IFuelable> vehiclesOnRoute)
       {
           var amountOfFuelToLoadOnTruck = 0;
           foreach (var vehicle in vehiclesOnRoute)
           {
               amountOfFuelToLoadOnTruck +=
               vehicle.GetTotalAmountOfFuelNeededForVehicle();
           }
           return amountOfFuelToLoadOnTruck;
       }
   }

       接口让我们的工作更简单。其实从整体上来说,这里涉及到了几个知识点:
       第一当然是面向对象的第三个原则"依赖倒置"原则,即父类或者接口应该是能够提供所有子类共性的,不能因为父类是什么,所以我的子类就得怎么。
      第二涉及到了多态,从IFuelable继承(实现)过来的 不同的实现类有不同的实现方法,从另一个角度看其实就是接口在不同的情况下有不同的状态。
      第三设计到了代码的优化,细心得看,其实我就是为了避免使用过多的if/else或者swtich/case,避免长代码的出现
     2014年2月24日14:02:00突然看到了上面那行熟悉的foreach确实不想用这玩意,回顾这篇博客我看了一个东西,List,集合想到了IEnumerable,这不是关键,关键是List<IFuelable>我们在抽象一下看看IEnumerable<IFuelable>,这玩意不是有很多的扩展方法吗?既然是个集合求和、排序、比大小还要自己做,微软也太对不起人了嘛。于是我VS干了件事就是让他对下我传输传输对应的那块内存去做中对应的元数据的HandleType,哈哈,故弄玄虚,装了下怪,其实就是找了下智能感应的提示。      
灵活应用接口让你释放你的工作_接口 扩展
      看到这里,ok啦,解释下,首先Sum是个扩张方法,传入的子类型是IEnumberable<TSource>其实就是一个泛型集合,然后函数的返回值有Many Much个数据类型,int,long,double,float反正是能求和的都有哦,我们知道Func是一个范函数及时我们所说的委托也可以认为是一个匿名函数,咋个想看个人了哈,我在这里把他看做是匿名函数了,也即是说我想用lamda表达式来完成这个Sum要求传递的那个函数参数,但是我不知道他那个sum到底实现到了哪一步,按理说应该是把我的集合来的值都计算完了再返回,不管先看它怎么实现的:
      翻译API我们发现:
灵活应用接口让你释放你的工作_接口 扩展 _02
        嗯这下我放心了,直接给他一个集合就是了,其实不用这么小心,比较人家Sum很明确就是求和嘛。
       一句话完成几句话的工作的句子:
      return vehiclesOnRoute.Sum(vehicle => vehicle.GetTotalAmountOfFuelNeededForVehicle());
也就是说我的新类:
       public class FuelingStation
       {
            public int AddFuelToTruck(List<IFuelable> vehiclesOnRoute)
           {
                 return vehiclesOnRoute.Sum(vehicle => vehicle.GetTotalAmountOfFuelNeededForVehicle());
           }
       }
O(∩_∩)O哈哈~,如何巴适,OK。
到了这一步可能程序有点令人看不懂了,没关系 ,看我下面的分解就明白了:

    public class FuelingStation
   {
       private Func<IFuelable, int> _myCalcuHander;
       public int AddFuelToTruck(List<IFuelable> vehiclesOnRoute)
       {
           _myCalcuHander = GetFuelNeed;
           return vehiclesOnRoute.Sum(_myCalcuHander);
       }
       private int GetFuelNeed(IFuelable fuelable)
       {
           return fuelable.GetTotalAmountOfFuelNeededForVehicle();
       }
   }
    我先定义了一个委托,这个委托使用Func范函数来规定他的签名(这个表述有点不准确,暂且这么说),然后再定义了这么一个与委托相对应的方法GetFuelNeed ,这些应该知道那一句lamda表达式干了什么工作了吧。