后端技术面试 38 讲
李智慧
同程艺龙交通首席架构师,前 Intel& 阿里架构师,《大型网站技术架构》作者
37373 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 46 讲
不定期加餐 (1讲)
后端技术面试 38 讲
15
15
1.0x
00:00/00:00
登录|注册

15丨软件设计的接口隔离原则:如何对类的调用者隐藏类的公有方法?

使用Iterable接口
使用接口隔离原则
使用接口隔离原则
使用接口隔离原则
不必要的耦合
增加使用难度
需要隐藏reBuild()方法
代码优化
实践中的应用
迭代器设计模式
TimedDoor
Modem类
解决方法
后果
不强迫用户依赖不需要的方法
缓存服务Client类的设计
思考题
优化设计的例子
接口隔离原则
问题描述
软件设计的接口隔离原则

该思维导图由 AI 生成,仅供参考

我在阿里巴巴工作期间,曾经负责开发一个统一缓存服务。这个服务要求能够根据远程配置中心的配置信息,在运行期动态更改缓存的配置,可能是将本地缓存更改为远程缓存,也可能是更改远程缓存服务器集群的 IP 地址列表,进而改变应用程序使用的缓存服务。
这就要求缓存服务的客户端 SDK 必须支持运行期配置更新,而配置更新又会直接影响缓存数据的操作,于是就设计出这样一个缓存服务 Client 类。
这个缓存服务 Client 类的方法主要包含两个部分:一部分是缓存服务方法,get()、put()、delete() 这些,这些方法是面向调用者的;另一部分是配置更新方法 reBuild(),这个方法主要是给远程配置中心调用的。
但是问题是,Cache 类的调用者如果看到 reBuild() 方法,并错误地调用了该方法,就可能导致 Cache 连接被错误重置,导致无法正常使用 Cache 服务。所以必须要将 reBuild() 方法向缓存服务的调用者隐藏,而只对远程配置中心的本地代理开放这个方法。
但是 reBuild() 方法是一个 public 方法,如何对类的调用者隐藏类的公有方法

接口隔离原则

我们可以使用接口隔离原则解决这个问题。接口隔离原则说:不应该强迫用户依赖他们不需要的方法
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

接口隔离原则在软件设计中扮演着重要角色,其核心理念是避免用户依赖不需要的方法。本文通过实际案例和优化设计的例子深入探讨了接口隔离原则的应用。首先,通过开发统一缓存服务的例子,阐述了如何通过接口隔离原则隐藏类的公有方法,避免用户错误调用导致系统异常。其次,通过Modem类和Door类的例子,说明了接口隔离原则如何解决方法之间的耦合问题,提高了系统的灵活性和可维护性。最后,文章还提到了接口隔离原则在迭代器设计模式中的具体应用场景。通过这些实例,读者可以深入理解接口隔禆原则的重要性和实际应用方法。文章以实例为线索,生动地阐释了接口隔离原则的实际应用,对于软件设计人员具有一定的借鉴意义。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《后端技术面试 38 讲》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(20)

  • 最新
  • 精选
  • lordrobert
    慧哥,请教下,接口隔离原则,和上一节说的单一职责原则是否有点“冲突”。需要进行接口隔离的类,感觉必然是有多个引起变化的原因,如果这样,单一职责运用下,设计成两个类,就不需要接口隔离了。既然有这两个原则,问题出在哪里?

    作者回复: 是冲突的。 但是文中举的几个例子,都很难实现单一职责原则,因为类的几组方法(也就是几个职责)之间强耦合,难以拆分。 原则是指导我们设计的,但是设计的时候又必须面对现实的困难做出权衡选择,所以就会有“冲突”的感觉。 后面组件设计原则一篇,这种“冲突”感更加强烈。 这也是有时候称软件设计为“艺术”的原因,因为软件设计师并不能机械地遵循什么原则、方法就能设计出好的软件,软件设计是软件设计师在理想与现实、现在与未来、审美与实用、代价与收益各种冲突中权衡、妥协、选择的产物。 软件设计是一个非常依赖人的直觉的工作,技术学习与实践的过程就是不断培养、优化自己直觉的过程。

    2021-04-06
    2
    19
  • 任鑫
    设计一个类大致和现实中设计一个职能部门差不多,需要考虑两方面需求:         (一)是优化资源调度、使用效率,提高效率,减少重复劳动。         (二)是便于对外提供功能服务,使功能的使用者能够清晰明确的使用到自己所需的功能,而不必纠缠其他不必要的功能。         为了满足第一条,软件设计上要注意代码的“高内聚”,就是将关联密切的功能放在一个类里面,以提高重用性;现实世界中,政府部门和企业内部需要将功能类似的组织合并,具体可以参照建国以来国务院下属部委的调整,当然这些调整的原因是多方面的,但其中有一些部门的合并确实考虑到了第一条,例如卫生健康委员会的设立和农业农村部的设立。         为了满足第二条,我们国家设置了“一个单位,两块牌子”的机构,例如今年频频亮剑的“中纪委国家监委”;在软件设计上,功能的调用者不直接通过依赖实现类的方式完成功能调用,而是依赖功能清晰,调用明确的接口,而多个功能接口可以由一个功能内聚的类提供实现。

    作者回复: 🐂

    2020-01-22
    9
  • 旅途
    老师 Iterable 为什么是属于接口隔离原则这个没太理解 能再详细讲一下吗

    作者回复: 每种数据容器实现类的内部都是不同的,但是它们都可以通过Iterable遍历,Client无需关注容器类的实现就能用统一的方式遍历容器。而Iterable接口也看不到容器类的内部实现,所以是一种接口隔离。

    2020-01-29
    6
  • 美美
    想起了,宝玉所说的道,术和器的概念 感觉"道"就是面向对象的的几个特性,封装,继承和多态 "术"就是以道为根基,为理论依据 发展而来的 各种模式, 用来解决软件开发中中的各种违背软件设计原则的方法. 所有的变换皆是"道"而引起的,没有道,就没有术比如少了多态这个道,各种设计模式将会减少大半甚至消亡.

    作者回复: 👍

    2020-01-03
    5
  • 旅途
    问一下老师 最后的小结 如果使用者 调用CacheManageable这个接口的reBuild 不还是被访问到了吗

    作者回复: CacheManageable这个接口不对使用者开放,所以无法访问。

    2020-01-29
    3
    1
  • alex
    老师能加个代码么?自动锁门那块
    2019-12-25
    8
  • 不记年
    接口隔离和单一职责是一体两面的,一个面向调用者,一个面向实现者
    2020-02-01
    6
  • 编程爱好者
    多思多想,代码设计里面有很多细节,建筑领域设计师与施工人员跟架构师跟码工有很多相似的工作内容,李老师在架构领域真的内功深厚,如果从哲学角度再进行一步抽象,那就是大师了
    2020-10-19
    2
  • escray
    接口隔离原则看上去比较简单,但是比较依赖 Java 语言 interface 多重继承的特性。 试着写一下 TimerDoor 的代码,适配器模式: class DoorTimerAdapter implements TimerClient { Door door; Timer timer; int timeout; public DoorTimerAdapter(Door door, Timer timer, int timeout) { this.door = door; this.timer = timer; this.timeout = timeout; timer.register(timeout, this); } public void timeout() { door.lock(); } } 多重继承: class Timer { public Timer() { } void register(int timeout, TimerClient client) { } } interface TimerClient { public void timeout(); } class Door { public Door() { } void lock() { } void unlock() { } boolean isDoorOpen() { return false; } } class TimedDoor extends Door implements TimerClient { private int timeout; private Timer timer; public TimedDoor() { this.timer = new Timer(); this.timeout = 10; timer.register(timeout, this); } public void timeout() { lock(); } } 不知道写的对不对,抛砖引玉。 两次都把 timer.register() 写在了构造函数里面,有点别扭。
    2020-09-25
    1
    2
  • 虢國技醬
    感觉go中的无侵入式的接口方式在这方面更显得自然和简单
    2020-01-21
    2
收起评论
显示
设置
留言
20
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部