接口隔离原则(Interface Segregation Principle, ISP)是SOLID五大设计原则之一,其核心思想是:客户端不应该被迫依赖于它不使用的方法;接口应当尽量小而专一,避免创建“胖”接口(即一个接口中定义了太多的方法)。
通过应用接口隔离原则,可以使系统更加灵活,维护性更高,并且减少类之间的耦合。
需要隔离的内容
- 方法:一个接口中不应包含过多的方法,特别是那些客户端不需要使用的方法。
- 实现:不同的接口实现应该针对特定的客户端需求,而不是一个通用的实现服务于所有客户端。
- 变化:接口的变化应该只影响到依赖于该接口的部分客户端,而不是所有客户端。
Java示例
假设我们设计一个系统,系统中有打印机(Printer)和复印机(Copier),同时也有一种设备是多功能一体机(MultiFunctionPrinter),即可以打印,也可以复印。
违反接口隔离原则的设计:
// 胖接口
public interface Machine {
void print();
void copy();
}
public class Printer implements Machine {
@Override
public void print() {
// 实现打印
System.out.println("Printing document.");
}
@Override
public void copy() {
// 打印机不具备复印功能,但由于实现了Machine接口,这里必须提供空实现或抛出异常
throw new UnsupportedOperationException("Copy not supported.");
}
}
public class Copier implements Machine {
@Override
public void print() {
// 复印机不具备打印功能,这里必须提供空实现或抛出异常
throw new UnsupportedOperationException("Print not supported.");
}
@Override
public void copy() {
// 实现复印
System.out.println("Copying document.");
}
}
public class MultiFunctionPrinter implements Machine {
@Override
public void print() {
System.out.println("Printing document.");
}
@Override
public void copy() {
System.out.println("Copying document.");
}
}
在上面的设计中,Printer
和Copier
类被迫实现了它们不需要的方法,这违反了接口隔离原则。
符合接口隔离原则的设计:
// 将接口拆分为更小的、专一的接口
public interface PrinterInterface {
void print();
}
public interface CopierInterface {
void copy();
}
// 单独实现打印功能的类
public class Printer implements PrinterInterface {
@Override
public void print() {
System.out.println("Printing document.");
}
}
// 单独实现复印功能的类
public class Copier implements CopierInterface {
@Override
public void copy() {
System.out.println("Copying document.");
}
}
// 实现多功能一体机,同时实现两个接口
public class MultiFunctionPrinter implements PrinterInterface, CopierInterface {
@Override
public void print() {
System.out.println("Printing document.");
}
@Override
public void copy() {
System.out.println("Copying document.");
}
}
在符合接口隔离原则的设计中,我们将Machine
接口拆分为PrinterInterface
和CopierInterface
,这样每个类只需关心它需要实现的功能。Printer
类只实现打印接口,Copier
类只实现复印接口,而MultiFunctionPrinter
类则实现两个接口,从而提供了打印和复印功能。
好处
- 高内聚低耦合:每个接口都只负责一项职责,类之间的依赖关系更加明确。
- 灵活性增强:可以更容易地添加新功能或修改现有功能,而不会影响其他不相关的功能。
- 可维护性提高:当一个接口发生变化时,只需修改依赖于该接口的类,而不会影响其他类。
通过应用接口隔离原则,我们可以设计出更加清晰、灵活和可维护的系统。