设计模式-02 设计模式-接口隔离原则案例分析

1.定义

接口隔离原则(Interface Segregation Principle,简称 ISP)是设计模式中的一个原则,它规定客户端不应该依赖它不使用的方法。

换句话说,接口应该被细分为更小的、更具体的接口,以便客户端只依赖于它们需要的方法。

bash 复制代码
										(客户端)
                                           |
                                           V
                   (公共行为)            (特定行为)         (特定行为)
                    +------------+         +-------------+        +-------------+
                    |  I公共接口  |         | I特定接口1 |        | I特定接口2 |
                    +------------+         +-------------+        +-------------+
                              |               |              |
                              V               V              V
                           +-------+     +---------+     +---------+
                           | 客户端1 |     | 客户端2 |     | 客户端3 |
                           +-------+     +---------+     +---------+
2.内涵

接口应该被细分的足够少,接口与接口直接不应该有依赖,ISP 的目的是提高代码的灵活性、可维护性和可测试性。总结起来,ISP原则的好处和缺点如下。

ISP 的好处

  • 提高代码的灵活性
  • 提高代码的可维护性
  • 提高代码的可测试性
  • 减少耦合
  • 提高代码的可重用性

ISP 的缺点

  • 可能导致更多的接口
  • 可能增加代码的复杂性
3.案例对比

例如,以机器类的定义为例,假如一个机器可以打印机,复印机,发传真机,如果不加以深入思考,我们可能如下第一种方式定义。

bad 设计

cpp 复制代码
//
// Created by Administrator on 2024/5/1.
//
#include <iostream>
using namespace std;
struct Document;
struct IMachine{
    virtual void print(Document& doc) = 0;
    virtual void scan(Document& doc) = 0;
    virtual void fax(Document& doc) = 0;

};
// 接口分离原则

// 发现 MFP  只需要 print 功能即可
// 其他接口到底怎么处理比较好?
struct MFP:IMachine{
    void print(Document &doc) override {
        // ok
    }

    void scan(Document &doc) override {

    }

    void fax(Document &doc) override {

    }
};

// 发现scanner 只需要 scan 功能
// 其他接口到底怎么处理比较好?
struct Scanner:IMachine{
    void print(Document &doc) override {
        // do what?
    }

    void scan(Document &doc) override {
        // ok
    }

    void fax(Document &doc) override {
        // do what?
    }
};

如果后面的传真机怎么定义?,除了fax 函数外,其他函数的功能并不是fax 需要的。

好的设计

cpp 复制代码
#include <iostream>
using namespace std;
struct Document;


// 接口分离
struct IPrinter{
    virtual void print(Document& doc) =0 ;
};

struct IScanner {
    virtual void scan(Document& doc)=0 ;
};

struct IFax{
    virtual void fax(Document& doc)=0 ;
};

struct IMachine:IPrinter,IScanner {

};

struct Machine:IMachine{
    IPrinter& printer;
    IScanner& scanner;
    Machine(IPrinter &printer, IScanner &scanner):printer(printer),scanner(scanner){

    }

    void print(Document &doc) override {
        printer.print(doc);
    }

    void scan(Document &doc) override {
        scanner.scan(doc);
    }
};

这种设计,我们可以任意进行组合,组合出不同特性的子类,自由度更高。

4.注意事项

在实际开发中应用接口隔离原则(ISP)时,需要注意以下几点:

  • 识别公共行为。第一步是识别客户端共享的公共行为。这些行为可以被抽象到一个公共接口中。
  • 细化接口。对于任何不属于公共行为的方法,都应该将其细化到一个单独的接口中。
  • 考虑可扩展性。在设计接口时,考虑未来的可扩展性。避免将不相关的功能包含在同一个接口中。
  • 使用依赖注入。依赖注入是一种技术,它允许客户端只依赖于它们需要的接口。这有助于实现松耦合和可测试性。
  • 避免使用继承。继承是一种实现代码重用的强大机制,但它也可能导致违反 ISP。如果可能的话,优先使用组合而不是继承。
5.最佳实践

注意的具体示例:

  • 避免创建上帝接口。上帝接口是一个包含大量方法的大型接口。客户端通常只使用其中一小部分方法,但仍然必须实现所有方法。这违反了 ISP,并可能导致不必要的代码和维护开销。
  • 避免使用可选方法。可选方法允许客户端选择性地实现接口中的某些方法。这可能导致代码混乱和不可预测的行为。如果可能的话,避免使用可选方法,而是创建单独的接口来表示可选的行为。
  • 考虑未来需求。在设计接口时,考虑未来的需求。避免将不相关的功能包含在同一个接口中,因为这可能会限制接口的未来可扩展性。
6.总结

应用 ISP 时,权衡其优点和缺点非常重要。ISP 可以提高代码的灵活性、可维护性和可测试性,但它也可能导致更多的接口和增加代码的复杂性。

总体而言,ISP 是一个有用的设计原则,它可以帮助提高代码的质量。通过遵循上述准则,开发人员可以有效地应用 ISP,从而获得其好处,同时避免其潜在的缺点。

相关推荐
alibli3 小时前
一文学会设计模式之创建型模式及最佳实现
c++·设计模式
1024肥宅4 小时前
前端常用模式:提升代码质量的四大核心模式
前端·javascript·设计模式
郝学胜-神的一滴9 小时前
设计模式依赖于多态特性
java·开发语言·c++·python·程序人生·设计模式·软件工程
帅次9 小时前
系统分析师:软件需求工程的软件需求概述、需求获取、需求分析
设计模式·重构·软件工程·团队开发·软件构建·需求分析·规格说明书
EXtreme3510 小时前
【数据结构】算法艺术:如何用两个栈(LIFO)优雅地模拟队列(FIFO)?
c语言·数据结构·算法·设计模式·栈与队列·摊还分析·算法艺术
1024肥宅1 天前
JavaScript常用设计模式完整指南
前端·javascript·设计模式
特立独行的猫a1 天前
C++观察者模式设计及实现:玩转设计模式的发布-订阅机制
c++·观察者模式·设计模式
better_liang1 天前
每日Java面试场景题知识点之-单例模式
java·单例模式·设计模式·面试·企业级开发
sg_knight1 天前
什么是设计模式?为什么 Python 也需要设计模式
开发语言·python·设计模式
koping_wu1 天前
【设计模式】设计模式原则、单例模式、工厂模式、模板模式、策略模式
单例模式·设计模式·策略模式