• 4.接口隔离原则(Interface Segregation Principle)


    1.定义

          客户端不应该依赖它不需要的接口;

         一个类对另一个类的依赖应该建立在最小的接口上。

    2.定义解读

         定义包含三层含义:

    • 一个类对另一个类的依赖应该建立在最小的接口上;
    • 一个接口代表一个角色,不应该将不同的角色都交给一个接口,因为这样可能会形成一个臃肿的大接口;
    • 不应该强迫客户依赖它们从来不用的方法。

         接口隔离原则有点像单一职责原则,但是也有区别,在单一职责原则中,一个接口可能有多个方法,提供给多种不同的调用者所调用,但是它们始终完成同一种功能,因此它们符合单一职责原则,却不符合接口隔离原则,因为这个接口存在着多种角色,因此可以拆分成更多的子接口,以供不同的调用者所调用。比如说,项目中我们通常有一个Web服务管理的类,接口定义中,我们可能会将所有模块的数据调用方法都在接口中进行定义,因为它们都完成的是同一种功能:和服务器进行数据交互;但是对于具体的业务功能模块来说,其他模块的数据调用方法它们从来不会使用,因此不符合接口隔离原则。

    3.优点

         使用接口隔离原则,意在设计一个短而小的接口和类,符合我们常说的高内聚低耦合的设计思想,从而使得类具有很好的可读性、可扩展性和可维护性。

    4.问题提出

         类A通过接口I依赖类B,类C通过接口I依赖类D,如果接口I对于类A和类C来说不是最小接口,而类B和类D必须去实现它们不需要的方法。下面通过一个UML图来说明这种现象:

         在这里,我们定义了一个动物活动的接口IAnimal,里面有4个方法:飞行fly、行走walk、吃eat和工作work,然后分别用人类People和鸟类Bird实现了这个接口。中国人类ChinesePeople和鹦鹉类Parrot通过接口IAnimal分别依赖类People和类Bird。很明显,对于ChinesePeople来说,fly方法是多余的,因为人不会飞;对于Parrot类来说,work方法是多余的,因为鹦鹉不需要工作。接口IAnimal对于类ChinesePeople和类Parrot来说不是最小接口。

    5.解决方案

         将臃肿的接口IAnimal拆分为独立的几个接口,类ChinesePeople和类Parrot分别与它们需要的接口建立依赖关系,也就是采用接口隔离原则。修改后的UML图如下所示:

     

    6.示例

    import Foundation
    
    @objc protocol IAnimal
    {
        optional func walk();
        func eat();
    }
    
    protocol IPeople
    {
        func work();
    }
    
    protocol IBird
    {
        func fly();
    }
    
    class People: NSObject, IAnimal, IPeople
    {
        func walk()
        {
            print("People walk");
        }
        
        func eat()
        {
            print("People eat");
        }
        
        func work()
        {
            print("People work");
        }
    }
    
    class Bird: NSObject, IAnimal, IBird
    {
        func eat()
        {
            print("Bird eat");
        }
        
        func fly()
        {
            print("Bird Fly");
        }
    }
    
    class ChinesePeople
    {
        var chinesePeople: protocol<IAnimal, IPeople>?;
        
        func peopleWalk()
        {
            chinesePeople?.walk!();
        }
        
        func peopleEat()
        {
            chinesePeople?.eat();
        }
        
        func peopleWork()
        {
            chinesePeople?.work();
        }
    }
    
    class Parrot
    {
        var parrot: protocol<IAnimal, IBird>?;
        
        func parrotEat()
        {
            parrot?.eat();
        }
        
        func parrotFly()
        {
            parrot?.fly();
        }
    }
    
    let chinesePeople = ChinesePeople();
    chinesePeople.chinesePeople = People();
    chinesePeople.peopleEat();  //打印:People eat
    
    let parrot = Parrot();
    parrot.parrot = Bird();
    parrot.parrotEat();  //打印:Bird eat

         说明:从UML图可以看到,遵守接口隔离原则,会使代码量增加不少,源码中也是这样;实际上,IOS在定义协议的时候,可以设置方法为可选实现(optional)和必须实现(默认值),我们可以设置work方法和fly方法为可选实现的方法,这样在类People和类Bird中,这两个方法可以根据需要来决定是否实现。采用这种方式,功能上实现是没有问题,对于简单的接口来说,也便于维护和管理。但是,当方法随着业务需求的增加而不断增加的话,如果我们不应用接口隔离原则,那么就可能形成一个庞大臃肿的接口,这样的接口的可维护性和重用性是很差的。因此,我们应该尽量细化接口,本篇将一个接口变更为3个专用的接口所采用的就是接口隔离原则。在项目开发中,依赖几个专用的接口要比依赖一个综合的接口更加灵活。通过分散定义多个接口,可以预防外来变更的扩散,提高系统的灵活性和可维护性。

         虽然接口隔离原则很有意义,但在实际项目中,应该注意度的把握,接口设计的过大或过小都不好,应该根据实际情况多思考再进行设计。

  • 相关阅读:
    linux添加超级用户
    MongDB配置方法
    【bzoj5174】[Jsoi2013]哈利波特与死亡圣器 二分+树形dp
    【bzoj3560】DZY Loves Math V 欧拉函数
    【bzoj5157】[Tjoi2014]上升子序列 树状数组
    【uoj#317】[NOI2017]游戏 2-SAT
    【bzoj5146】有趣的概率 微积分
    【bzoj4695】最假女选手 线段树区间最值操作
    【bzoj4355】Play with sequence 线段树区间最值操作
    【loj2319】[NOIP2017]列队 Splay(卡过)
  • 原文地址:https://www.cnblogs.com/LeeGof/p/5704235.html
Copyright © 2020-2023  润新知