写代码太菜了,被女朋友我分手第一天,来学习接口隔离原则。在B站看了一个视频,该死:b23.tv/UetYdY8
1. 什么是接口隔离原则?
1. 定义
接口隔离原则: 强调一个类不应该强制实现它用不到的接口。具体来说,一个类应该对它的客户端提供尽可能小的接口,而不强迫客户端依赖于它们不使用的方法。
2. 举例说明
public interface Animal {
void eat();
void sleep();
void fly();
}
我们有两个具体的动物类:Bird
和 Snake
public class Bird implements Animal {
public void eat() {
// 实现吃的行为
}
public void sleep() {
// 实现睡觉的行为
}
public void fly() {
// 实现飞的行为
}
}
public class Snake implements Animal {
public void eat() {
// 实现吃的行为
}
public void sleep() {
// 实现睡觉的行为
}
public void fly() {
// 啊,蛇不能飞!这里不应该有这个方法
}
}
在这个例子中,Snake
类实现了 fly
方法,但是这并不符合蛇的行为,因为蛇是不会飞的。这违反了接口隔离原则。
修改:为了符合接口隔离原则:将 Animal
接口分解为更小的接口,每个接口代表一个行为:
public interface Eater {
void eat();
}
public interface Sleeper {
void sleep();
}
public interface Flyer {
void fly();
}
public class Bird implements Eater, Sleeper, Flyer {
// 实现相应的方法
}
public class Snake implements Eater, Sleeper {
// 实现相应的方法
}
这就是接口隔离原则的核心思想
:将庞大的接口分解为更小的、更具体的接口,以提高类的灵活性,降低耦合度。
2.接口隔离原则在工程中的体现
第一个例子是完完全全的接口,现在我们再换一种理解方式,把接口理解为单个接口或函数。那接口隔离原则就可以理解为:函数的设计要功能单一,不要将多个不同的功能逻辑在一个函数中实现。
考虑一个需求:从一组数字中筛选出偶数并计算它们的平均值。
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9);
filterEvenNumbersAndCalculateAverage(numbers);
}
// 不是纯函数,有副作用
private static void filterEvenNumbersAndCalculateAverage(List<Integer> numbers) {
List<Integer> evens = new ArrayList<>();
for (int num : numbers) {
if (num % 2 == 0) {
evens.add(num);
}
}
double average = evens.isEmpty() ? 0 : calculateAverage(evens);
System.out.println("Filtered even numbers: " + evens);
System.out.println("Average of even numbers: " + average);
}
// 纯函数,只关注计算平均值
private static double calculateAverage(List<Integer> numbers) {
double sum = 0;
for (int num : numbers) {
sum += num;
}
return numbers.isEmpty() ? 0 : sum / numbers.size();
}
}
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9);
List<Integer> evens = filterEvenNumbers(numbers);
double average = calculateAverage(evens);
System.out.println("Filtered even numbers: " + evens);
System.out.println("Average of even numbers: " + average);
}
// 纯函数,只关注筛选偶数
private static List<Integer> filterEvenNumbers(List<Integer> numbers) {
List<Integer> evens = new ArrayList<>();
for (int num : numbers) {
if (num % 2 == 0) {
evens.add(num);
}
}
return evens;
}
// 纯函数,只关注计算平均值
private static double calculateAverage(List<Integer> numbers) {
double sum = 0;
for (int num : numbers) {
sum += num;
}
return numbers.isEmpty() ? 0 : sum / numbers.size();
}
}
这个代码有点长,但是表达的思想很简单,就是保持方法的纯度
,其中一个是求奇数,一个是求平均值,可能A需求就既求奇偶数,也求平均值,可能是B需求只是求平均值。这个时候我们就应该对代码提纯,提高代码的复用性,而用不到求奇偶数的类就不需要提供改方法,虽然后面可以写成工具类
,但是工具类里也要保持方法之间的隔离。
你应该已经发现,接口隔离原则跟单一职责原则有点类似,不过还是有点区别的:
- 焦点不同: ISP主要关注接口设计,强调接口的精简和高内聚性;SRP主要关注
模块
、类
、接口
的设计,强调类的单一职责。 - 适用范围: ISP更侧重于接口的设计层面,而SRP更侧重于类的设计层面。
ISP提供了一种判断接口是否职责单一的标准:通过调用者如何使用接口来间接地判定。如果调用者只使用部分接口或接口的部分功能,那接口的设计就不够职责单一。
今天就先到这里了,晚安。