SHOW ME THE CODE - 面向对象设计系列
- 1 SHOW ME THE CODE - 面向对象基本概念
- 2 SHOW ME THE CODE - 面向对象程序设计之 - 单一职责原则(SRP)
- 3 SHOW ME THE CODE - 面向对象程序设计之 - 开闭原则(OCP)
- 4 SHOW ME THE CODE - 面向对象程序设计之 - 里氏替换原则(LSP)
- 5 SHOW ME THE CODE - 面向对象程序设计之 - 接口隔离原则(ISP)
你的新手机有预装软件吗?
手机已经是生活必须品
再开始今天的主题之前我们先来看一个我们现实生活中大家都曾经遇到过的场景。当今社会手机已经成为了人们日常生活的必备品,除了很小的小朋友可能没有手机,其余的人基本上都拥有属于自已的手机。
新手机开箱,能装多少是多少
很多人都购买过新手机,有些人换机的频率还很高。当我们购买了一部新手机,按下电源键开机,并进行了基本的初始化设置后,首次进入手机的桌面,我想问一问大家的感受是什么?大家是否发现除了手机系统自带的系统必备的一些系统软件之外,很多的应用已经安装到了你的手机里,这些应用我们称之为预装应用。
比如说抖音、淘宝、支付宝、大众点评、头条、携程、QQ、微信、腾讯视频、优酷视频、拼多多、百度地图、哔哩哔哩等等,根据不同的手机厂商,预装的软件会有所不同。而且当我们打开手机应用商店,稍不留神就会下装安装一大堆“推荐安装”的应用。
我不需要的,请不要给我
当我买了一个新手机,第一件事情就是把一些用不上的APP卸载了,比如说:抖音,头条,携程,优酷视频,以及一些系统自带的很多用不上的其它应用。
之所以这么做,就是新手机预装了我不想要,且不需要,且让人反感的应用。为了手机,我被迫安装了不需要的东西,为了解决这个问题,我需要花额外的时间来卸载这些应用。
而今天我们要谈的“接口隔离原则(ISP)”,和手机的例子有相似之处,那就是我不需要的,请不要给我,否则我会很难受。
接口隔离原则
接口隔离原则的定义
接口隔离原则(Interface Segregation Principle,ISP)是面向对象设计中的一个原则,由罗伯特·C·马丁(Robert C. Martin),江湖人称:Uncle Bob, 鲍勃大叔,在他的著作《敏捷软件开发:原则、模式与实践》(Agile Software Development: Principles, Patterns, and Practices)中提出。
该原则的定义是:客户端不应该依赖于它不需要的接口。
怎么理解“接口”
我们可以把接口比作剧本中的角色,而该角色在剧中由哪个演员来扮演则想当于接口的由哪个具体的类来实现。所以,一个接口应该简单的代表一个角色,而不是多个角色。
怎么理解接口隔离
接口隔离原则主要是为了防止设计出大而全的单一接口,这种接口通常包含了不同客户端所需的所有方法。
当我们进行设计接口时,应该将其设计得尽可能精简,只包含客户端需要的方法,而不应该强迫客户端去依赖于它们不需要的方法。接口隔离原则强调了接口的单一性和独立性,以减少类之间的耦合度,提高系统的灵活性、可维护性和可扩展性。
SHOW ME THE CODE
A Bad Example: All in One Interface
我们定义了一个用户管理的接口:UserManagement,里面包含用户创建更新操作,用户组操作,找回密码操作,我们的接口实现类:UserManagementService就是一个包含了所有操作的大类。
public interface UserManagement
{
//创建用户,更新用户
void createUser(User user);
void updateUser(User user);
//用户组操作
List<User> getUserByGroup(String group);
void addToGroup(User user, String group);
void removeFromGroup(User user, String group);
//找回密码
String sendVerificationCode(User user, String phoneNumber);
void verifyCode(String code);
void resetPassword(User user, String newPassword);
}
public class UserManagementService implements UserManagement
{
//创建用户,更新用户
@Override
public void createUser(User user)
{
//user creation logic
}
@Override
public void updateUser(User user)
{
//update logic
}
//用户组操作
@Override
public List<User> getUserByGroup(String group)
{
//query users by group name, return a list of user by a specific group
}
@Override
public void addToGroup(User user, String group)
{
//add a user to a group
}
@Override
public void removeFromGroup(User user, String group)
{
//remove a user from a group
}
//找回密码
@Override
public String sendVerificationCode(User user, String phoneNumber)
{
//update logic
}
@Override
public void verifyCode(String code)
{
//update logic
}
@Override
public void resetPassword(User user, String newPassword)
{
//update logic
}
}
如何重构,—>接口拆分
需要对上面的UserManagement接口和其实现类进行如下拆分
-
拆分后接口
- IUserMng
- IUserGroup
- IPswChange 拆分后实现类
- UserService
- UserGroupService
- PswChangeService
public interface IUserMng
{
//创建用户,更新用户
void createUser(User user);
void updateUser(User user);
}
public interface IUserGroup
{
//用户组操作
List<User> getUserByGroup(String group);
void addToGroup(User user, String group);
void removeFromGroup(User user, String group);
}
public interface IPswChange
{
//找回密码
String sendVerificationCode(User user, String phoneNumber);
void verifyCode(String code);
void resetPassword(User user, String newPassword);
}
public class UserService implements IUserMng
{
//创建用户,更新用户
@Override
public void createUser(User user)
{
//user creation logic
}
@Override
public void updateUser(User user)
{
//update logic
}
}
public class UserGroupService implements IUserGroup
{
//用户组操作
@Override
public List<User> getUserByGroup(String group)
{
//query users by group name, return a list of user by a specific group
}
@Override
public void addToGroup(User user, String group)
{
//add a user to a group
}
@Override
public void removeFromGroup(User user, String group)
{
//remove a user from a group
}
}
public class PswChangeService implements IPswChange
{
//找回密码
@Override
public String sendVerificationCode(User user, String phoneNumber)
{
//update logic
}
@Override
public void verifyCode(String code)
{
//update logic
}
@Override
public void resetPassword(User user, String newPassword)
{
//update logic
}
}
接口隔离原则与其他设计原则的关系
在面向对象的几大设计原则中,每一个原则又与其它的原则有着密切的关系,他们共同的目标都是围绕软件的可扩展,可维护,灵活性以及降低代码的耦合度。
接口隔离原则与其他一些设计原则密切相关,例如:
**单一职责原则(SRP):**接口应该只包含那些与其功能密切相关的的方法,这与单一职责原则相符。
**依赖倒置原则(DIP):**接口应该被抽象类或接口所依赖,而不是具体类,这与依赖倒置原则相符。
**开闭原则(OCP):**接口应该对扩展开放,对修改封闭,这与开闭原则相符。
接口隔离与单一职责的比较
- 适用范围不同:
- 单一职责原则(SRP)主要关注的是类或模块的设计,它要求一个类或模块应该只有一个引起它变化的原因,即一个类或模块应该只有一个责任。
- 接口隔离原则(ISP)更多地关注接口的设计,它要求接口的设计应该精简单一,客户端不应该依赖于它们不需要的接口。
- 关注点不同:
- SRP关注的是类或模块内部的责任分配,即一个类或模块应该负责完成一个特定的任务。
- 而ISP关注的是类或模块与外部的交互,即接口的设计应该满足客户端的需求,不应该强迫客户端依赖于它们不需要的方法。
- 侧重点不同:
- SRP侧重于避免一个类或模块内部功能的混乱和耦合,通过将不同的职责分离到不同的类或模块中来提高内聚性和降低耦合性。
- 而ISP侧重于避免类或模块与外部的依赖关系过于紧密,通过精简接口的设计来减少客户端与接口的耦合度。
希望这篇文章可以帮助大家理解什么是接口隔离原则,欢迎大家一起交流。
关注我的公众号
欢迎大家关注、点赞、转发,一起交流软件开发、架构设计、云原生技术。