搞定设计模式之接口隔离原则一篇文章就够了!!!

Posted 南淮北安

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了搞定设计模式之接口隔离原则一篇文章就够了!!!相关的知识,希望对你有一定的参考价值。

一、定义

客户端不应该被迫依赖于它不使用的方法

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

接口隔离原则(Interface Segregation Principle,ISP)要求程序员尽量将臃肿庞大的接口拆分成更小的和更具体的接口,让接口中只包含客户感兴趣的方法。

接口隔离是为了高内聚、低耦合。在实际的业务开发中,通常会先定义好需要开发的接口,并由各个服务类实现。

但如果没有经过考虑和设计,就很可能造成一个接口中包括众多的接口方法,而这些接口并不一定在每一个类中都需要实现。这样的接口很难维护,也不易于扩展,每一次修改验证都有潜在的风险

在具体应用接口隔离原则时,应该根据以下几个规则衡量:
(1)接口尽量小,但是要有限度。一个接口只服务于一个子模块或业务逻辑。
(2)为依赖接口的类定制服务。只提供调用者需要的方法,屏蔽不需要的方法。
(3)了解环境,拒绝盲从。每个项目或产品都有选定的环境因素,环境不同,接口拆分的标准就不同,要深入了解业务逻辑。
(4)提高内聚,减少对外交互。让接口用最少的方法完成最多的事情。

二、示例

《王者荣耀》里有很多英雄,可以分为射手、战士、刺客等,每个英雄有三种技能。

这些技能该如何定义,让每个英雄实现相应的技能效果呢?接下来就分别使用两种不同的方式实现,来体现设计原则的应用。

首先定义一个技能接口,实现的英雄都需要实现这个接口,进而实现自己的技能。

public interface ISkill {
    // 射箭
    void doArchery();
    // 隐袭
    void doInvisble();
    // 沉默
    void doSilent();
    // 眩晕
    void doVertigo();
}

这里提供了四个技能的接口,包括射箭、隐袭、沉默、眩晕,每个英雄都实现这个接口。

接下来实现两个英雄:后羿和廉颇。

当然,这里为了说明问题进行了简化,英雄技能只有三个,与真实游戏中有所差别。

英雄后裔:在英雄后羿的类中,实现了三个技能,最后一个眩晕的技能是不需要实现的。

public class HeroHouYi implements ISkill{

    @Override
    public void doArchery() {
        System.out.println("后羿的灼日之矢");
    }

    @Override
    public void doInvisble() {
        System.out.println("后羿的隐身技能");
    }

    @Override
    public void doSilent() {
        System.out.println("后羿的沉默技能");
    }

    @Override
    public void doVertigo() {
    //    无此技能的实现
    }
}

英雄廉颇:在英雄廉颇的类中,同样只实现了三个技能,有一个射箭的技能没有实现。

public class HeroLianpo implements ISkill {

    @Override
    public void doArchery() {
        //    无此技能的实现
    }

    @Override
    public void doInvisble() {
        System.out.println("廉颇的隐身技能");
    }

    @Override
    public void doSilent() {
        System.out.println("廉颇的沉默技能");
    }

    @Override
    public void doVertigo() {
        System.out.println("廉颇的眩晕技能");
    }
}

每个英雄的实现类里都有一个和自己无关的接口实现类,非常不符合设计模式,也不易于维护。

因为不仅无法控制外部的调用,还需要维护对应的文档,来说明这个接口不需要实现。

如果有更多这样的接口,就会变得非常麻烦。

三、问题改进

按照接口隔离原则的约定,应该在确保合理的情况下,把接口细分。保证一个松散的结构,也就是把技能拆分出来,每个英雄都可以按需继承实现。

接下来分别定义四个技能接口,包括射箭(ISkillArchery)、隐身(ISkillInvisible)、沉默(ISkillSilent)、眩晕(ISkillVertigo),如下所示。

public interface ISkillArchery {
    // 射箭
    void doArchery();
}
public interface ISkillInvisble {
    // 隐袭
    void doInvisble();
}
public interface ISkillSilent {
    // 沉默
    void doSilent();
}
public interface ISkillVertigo {
    // 眩晕
    void doVertigo();
}

有了四个技能细分的接口,英雄的类就可以自由地组合了。

英雄后羿的实现:

public class HeroHouYi implements ISkillArchery, ISkillArchery, ISkillSilent{

    @Override
    public void doArchery() {
        System.out.println("后羿的灼日之矢");
    }

    @Override
    public void doInvisble() {
        System.out.println("后羿的隐身技能");
    }

    @Override
    public void doSilent() {
        System.out.println("后羿的沉默技能");
    }
}

英雄廉颇的实现:

public class HeroLianpo implements ISkillArchery, ISkillSilent, ISkillVertigo {
    @Override
    public void doInvisble() {
        System.out.println("廉颇的隐身技能");
    }

    @Override
    public void doSilent() {
        System.out.println("廉颇的沉默技能");
    }

    @Override
    public void doVertigo() {
        System.out.println("廉颇的眩晕技能");
    }
}

现在可以看到这两个英雄的类都按需实现了自己需要的技能接口。

这样的实现方式就可以避免一些本身不属于自己的技能还需要不断地用文档的方式进行维护,同时提高了代码的可靠性,在别人接手或者修改时,可以降低开发成本和维护风险。

以上是关于搞定设计模式之接口隔离原则一篇文章就够了!!!的主要内容,如果未能解决你的问题,请参考以下文章

搞定开闭原则的设计模式一篇文章就够了!!!

搞定设计模式之迪米特法则一篇文章就够了!!!

搞定设计模式之工厂模式一篇文章就够了!!!

搞定里式替换原则的设计模式一篇文章就够了!!!

搞定单一职责的设计模式一篇文章就够了!!!

搞定 WeakHashMap 的工作原理一篇文章就够了!!!