面向对象的六大原则之 接口隔离原则——ISP

ISP = Interface Segregation Principle

ISP的定义如下:

1、客户端不应该依赖他不需要的接口

2、一个类对另外一个类的依赖性应该是建立在最小的接口上

3、不应当将不同的接口合并在一起,形成一个臃肿的大接口,这是对接口的污染

4、使用多个专门的接口要比使用单一的总接口要好

ISP的几个使用原则

1、根据接口隔离原则拆分接口时,首先必须满足单一职责原则: 没有哪个设计可以十全十美的考虑到所有的设计原则,有些设计原则之间就可能出现冲突,就如同单一职责原则和接口隔离原则,一个考虑的是接口的职责的单一性,一个考虑的是方法设计的专业性(尽可能的少),必然是会出现冲突。在出现冲突时,尽量以单一职责为主,当然这也要考虑具体的情况。

2、提高高内聚: 提高接口,类,模块的处理能力,减少对外的交互。比如你给杀手提交了一个订单,要求他在一周之内杀一个人,一周后杀手完成了任务,这种不讲条件完成任务的表现就是高内聚。具体来说就是:要求在接口中尽量少公布public方法,接口是对外的承诺,承诺越少对系统的开发越有利,变更的风险就越小,也有利于降低成本。

3、定制服务: 单独为一个个体提供优良服务(只提供访问者需要的方法)。

4、接口设计要有限度: 根据经验判断

接口隔离原则和单一职责原则就是一个硬币的两面,他们说的其实是一回事。

只是接口隔离原则是站在服务调用者角度看问题,单一职责原则是站在服务提供者的角度看。

===========================================================================================

契约是怎么回事呢?

契约就是在说两件事,甲方在契约里说我不会多要,乙方会在契约里说我不会少给。

乙方的不会少给是比较容易做到的,因为当一个类实现一个接口的时候,他必须要实现接口里的所有方法。如果你不想实现所有的方法,你留下了抽象方法,那你这个类就是抽象类,不能被实例化,即你不是一个完整的服务提供者。所以说乙方不会少给,是强制性的。

甲方不会多要是软性的规定,他是个设计上的东西,需要我们用一些设计原则去约束和控制大家写代码。因为编译器是能检测出乙方是不是少给,没法检查出来甲方是不是多要了。

那么我怎么知道甲方有没有多要呢?很简单,就看传递给调用者接口类型里,有没有一直没有被调用到的函数成员,如果有,就说明传递进来的接口类型太大了(太胖了),换句话说 胖接口就是这个接口是由两个或两个以上本质不同的小一点接口合并起来的,把大接口传递进来,只能一部分接口被调用到,另一部分就多余出来了。

根据胖接口的产生原因不同,违反接口隔离原则可能带来的不好的后果基本上有两个:

1、第一种情况,设计的时候有问题,把太多的功能接口包含进来,那其中必然有一部分功能永远用不到,也就自然违反了接口隔离原则。

我们看一下实例:

场景介绍: 一对小情侣,一天女生给男生打电话,告诉他车被追尾了,哭的梨花带雨。小男生情商高,哄小女生说 不要紧,明天给你买辆坦克,就不怕追尾了。(前提是小女生不能开炮,只能开~~~~)

第一版的实现=》小女生只会开汽车,不会开别的

#region 车辆接口和实现

    interface IVehicle
    {
        void Run();
    }

    class Car : IVehicle
    {
        public void Run()
        {
            Console.WriteLine("Car is Running");
        }
    }
    class Truck : IVehicle
    {
        public void Run()
        {
            Console.WriteLine("Truck is Running");
        }
    }

    #endregion

驾驶员类:

class Driver
    {
        private IVehicle _vehicle;
        public Driver(IVehicle vehicle)
        {
            _vehicle = vehicle;
        }
        public void Drive()
        {
            _vehicle.Run();
        }
    }

服务调用方:

   var driver = new Driver(new Car());//开汽车
            driver = new Driver(new Truck());//开卡车
            driver.Drive();

            //这时候你会发现,如果小女生想要开坦克的话,目前是满足不了的
            //因为Driver构造参数传递的是IVehicle接口,不是ITank接口
            //如果想要满足小女生开坦克上街的愿望,就必须改造Driver,传递ITank接口,请看下一个例子

            Console.ReadKey();

第二版的实现=》小女生能开坦克,但是却不能开汽车了

 class Driver
    {
        private ITank _tank;
        public Driver(ITank tank)
        {
            _tank = tank;
        }
        public void Drive()
        {
            _tank.Run();
        }
    }
   var driver = new Driver(new HeavyTank());//开坦克
            driver.Drive();

            // 这时候你会发现, 小女生能开坦克上街了,但是你又会发现,小女生现在只会开坦克了,不会开车了
            // 问题出现在哪里呢?
            // 我们把一个胖接口(ITank)传递进来,这个胖接口中有一个我们永远用不到的功能,就是fire。
            // 所以现在这个设计是违反了接口隔离原则
            // 具体改造请看下一个例子

            Console.ReadKey();

第三版的实现=》符合接口隔离原则,小女生能开坦克,也能开汽车了。

#region 车辆接口和实现

    interface IVehicle
    {
        void Run();
    }

    class Car : IVehicle
    {
        public void Run()
        {
            Console.WriteLine("Car is Running");
        }
    }
    class Truck : IVehicle
    {
        public void Run()
        {
            Console.WriteLine("Truck is Running");
        }
    }

    #endregion
interface IWeapon
    {
        void Fire();
    }
  interface ITank:IVehicle,IWeapon
    {
    }
    class LightTank : ITank
    {
        public void Fire()
        {
            Console.WriteLine("Boom!");
        }

        public void Run()
        {
            Console.WriteLine("Ka Ka Ka!");
        }
    }

    class HeavyTank : ITank
    {
        public void Fire()
        {
            Console.WriteLine("Boom!!!!!!!!");
        }

        public void Run()
        {
            Console.WriteLine("Ka!!! Ka!!!! Ka!!!!!!");
        }
    }

驾驶员类:

  class Driver
    {
        private IVehicle _vehicle;
        public Driver(IVehicle vehicle)
        {
            _vehicle = vehicle;
        }
        public void Drive()
        {
            _vehicle.Run();
        }
    }

服务调用方:

      //接口隔离的原则是 服务的调用方不会都要
            //本例子中服务的调用方的需求很简单,这是要求会run,不要求fire
            //因此原先的ITank接口中自己包含的fire和run就符合胖接口的规则,他提供了多余的接口给调用方
            //因此把ITank接口隔离开是对的
            var driver = new Driver(new HeavyTank());//开坦克
            driver.Drive();
            driver = new Driver(new Car());//开汽车
            driver.Drive();

            Console.ReadKey();

第二种情况明天继续,哇哈哈~~~~~~~~~~

原文地址:https://www.cnblogs.com/schangxiang/p/11223694.html

时间: 2024-11-05 12:11:47

面向对象的六大原则之 接口隔离原则——ISP的相关文章

面向对象原则之一 接口隔离原则

原文:面向对象原则之一 接口隔离原则 前言 面向对象有人分为五大原则,分别为单一职责原则.开放封闭原则.依赖倒置原则.接口隔离原则.里氏替换原则. 也有人分为六大原则,分别为单一职责原则.开放封闭原则.依赖倒置原则.接口隔离原则.里氏替换原则.迪米特法则. 现在我们来介绍接口隔离原则 接口隔离原则 1)概念 客户端不应该依赖它不需要的接口.一个类对另一个类的依赖应该建立在最小的接口上. 怎么理解呢?通俗一点就是说接口尽量细分,把不需要的方法尽量写在2个不同的接口上. 假如我有一个接口Interf

设计原则之接口隔离原则

segregate   v.隔离 se 蛇  gre green格林  gate门 蛇被格林用门隔离了. 设计原则之接口隔离原则 动机:         客户不应该被强制实现他们不用的方法.应该用多个小的接口代替庞大功能全的接口. 结论:        该原则在代码设计的时候就要考虑.可以使用适配器模式将胖接口隔离. Bad Example:    缺点:         1.如果新增一个robot机器人工人,那么eat方法就是多余的了. // interface segregation pri

设计模式原则之接口隔离原则

在讲接口隔离原则之前,我们先明确一下我们的主角,什么是接口,接口分为两种: 一种是实例接口 (Object Interface),在 Java 中声明一个类,然后用 new 关键字产生的一个实例,它是对一个类型的事 物描述,这是一种接口,比如你定义个 Person 这个类,然后使用 Person zhangSan = new Person()产生了 一个实例,这个实例要遵从的标准就是 Person 这个类,Person 类就是 zhangSan 的接口,看不懂?不要紧, 那是让 Java 语言浸

深入理解JavaScript系列(21):SOLID五大原则之接口隔离原则ISP(转载)

深入理解JavaScript系列(21):SOLID五大原则之接口隔离原则ISP 前言 本章我们要讲解的是S.O.L.I.D五大原则JavaScript语言实现的第4篇,接口隔离原则ISP(The Interface Segregation Principle). 英文原文:http://freshbrewedcode.com/derekgreer/2012/01/08/solid-javascript-the-interface-segregation-principle/注:这篇文章作者写得

设计模式六大原则之接口隔离原则

一.概念: 接口隔离原则有两种定义: 1.Clients should not be forced to depend upon interfaces that they don't use. (客户端不应该强行依赖它不需要的接口) 2.The dependency of one class to another one should depend on the smallest possible interface. (类间的依赖关系应该建立在最小的接口上) 客户端不应该依赖它不需要的接口.接

面向对象设计原则之接口隔离原则

接口隔离原则定义如下: 接口隔离原则(Interface  Segregation Principle, ISP):使用多个专门的接口,而不使用单一的总接口,即客户端不应该依赖那些它不需要的接口. 根据接口隔离原则,当一个接口太大时,我们需要将它分割成一些更细小的接口,使用该接口的客户端仅需知道与之相关的方法即可.每一个接口应该承担一种相对独立的角色,不干不该干的事,该干的事都要干.这里的“接口”往往有两种不同的含义:一种是指一个类型所具有的方法特征的集合,仅仅是一种逻辑上的抽象:另外一种是指某

设计模式之禅--六大设计原则之接口隔离原则

设计模式就是让我们更方便的解决问题. 这里分享一个故事.我有一个朋友,嗯没错就是一个朋友,参加一个软件比赛,一个同学写服务器上的代码,三天两头更新,丝毫不考虑写客户端的人的感受,简直不能再牛.如果Java的更新有这么一次,没有考虑在不影响以前代码的基础上做修改,得有多少程序员吐血身亡. 接口隔离原则的定义: 建立单一接口,不要建立臃肿放大的接口.接口尽量细化,同时接口中的方法尽量少. 这不是单一职责原则,单一职责要求的是类和接口的职责单一,注重的是职责,这是业务逻辑上的划分,而借口隔离原则要求接

迪米特原则与接口隔离原则

强调组件的封装性和信息隐藏的功能. 封装的越好,模块间的耦合越小: 隐藏的越好,组件的可用性越好. 在类的结构设计上,每一个类都应当尽量降低成员的访问权限 http://blog.csdn.net/wangjunkg/article/details/3762132 四.接口隔离原则 全称:“Interface Segregation Principle” 说明:使用多个专一功能的接口比使用一个的总接口总要好.从一个客户类的角度来讲:一个类对另外一个类的依赖性应当是建立在最小接口上的.过于臃肿的接

深入理解JavaScript系列(21):S.O.L.I.D五大原则之接口隔离原则ISP

前言 本章我们要讲解的是S.O.L.I.D五大原则JavaScript语言实现的第4篇,接口隔离原则ISP(The Interface Segregation Principle). 英文原文:http://freshbrewedcode.com/derekgreer/2012/01/08/solid-javascript-the-interface-segregation-principle/ 注:这篇文章作者写得比较绕口,所以大叔理解得也比较郁闷,凑合着看吧,别深陷进去了 接口隔离原则的描述