接口隔离原则
- 一 官方定义
- 二 案例演示
- 普通方案
- 案例分析
- 解决方案
- 解决方案
- 案例总结
- 三 与单一职责原则对比
一 官方定义
接口隔离原则(Interface Segregation Principle),又称为ISP原则,官方定义为:
- Clients should not be forced to depend upon interfaces that they don’t use.
(客户端不应该依赖它不需要的接口)- The dependency of one class to another one should depend on the smallest possible
interface. (类间的依赖关系应该建立在最小的接口上)
基本介绍
通俗的来讲,不要在一个接口里面定义过多的方法,接口应该尽量细化
二 案例演示
假设有这样一个案例场景,现在有一个接口knife,给定他有三个能力,可以切苹果,切番茄,切土豆, 两个类张厨师,李厨师分别具有这些能力,有一个水果店类,假设是需要张师傅来切苹果和切番茄,而另一个蔬菜店类需要李师傅来切番茄和切土豆
普通方案
public class SegregationDemo {
public static void main(String[] args) {
//水果店类
new FruitShop().cutApple(new CookZhang());
new FruitShop().cutTomato(new CookZhang());
//蔬菜店类
new VegetableShop().cutTomato(new CookLi());
new VegetableShop().cutPotato(new CookLi());
}
}
// 定义接口knife
interface Knife {
//切苹果的能力
void cutApple();
//切番茄的能力
void cutTomato();
//切土豆的能力
void cutPotato();
}
//张厨师类
class CookZhang implements Knife {
@Override
public void cutApple() {
System.out.println("张厨师正在切苹果");
}
@Override
public void cutTomato() {
System.out.println("张厨师正在切番茄");
}
@Override
public void cutPotato() {
System.out.println("张厨师正在切土豆");
}
}
//李厨师类
class CookLi implements Knife {
@Override
public void cutApple() {
System.out.println("李厨师正在切苹果");
}
@Override
public void cutTomato() {
System.out.println("李厨师正在切番茄");
}
@Override
public void cutPotato() {
System.out.println("李厨师正在切土豆");
}
}
/*假设有这样一个案例场景,现在有一个接口knife,给定他有三个能力,可以切苹果,切番茄,切土豆,两个类张
厨师,李厨师分别具有这些能力,有一个水果店类,假设是需要张师傅来切苹果和切番茄,而另一个蔬菜店类需要
李师傅来切番茄和切土豆*/
//水果店类
class FruitShop {
// 将接口类型作为参数传入
public void cutApple(Knife knife) {
knife.cutApple();
}
public void cutTomato(Knife knife) {
knife.cutTomato();
}
}
//蔬菜店类
class VegetableShop {
public void cutTomato(Knife knife) {
knife.cutTomato();
}
public void cutPotato(Knife knife) {
knife.cutPotato();
}
}
案例分析
1、VegetableShop使用到Knife中两个方法,同样FruitShop也是如此
2、CookZhang,CookLi分别实现Knife这个接口Knifes对于CookZhang,CookLi不是最小的接口,
换句话说CookZhang,CookLi就必须实现他们不需要的方法。导致这个类出现了耦合
这就违反了接口隔离原则(类间的依赖关系应该建立在最小的接口上)
解决方案
解决方案
根据接口隔离原则,我们将Knife拆分为三个独立的接口不就行了吗!
步骤:
- 将Knife拆分为AppleKnife,TomatoKinfe,PotatoKnife三个独立的接口
- CookZhang(张厨师类 )实现AppleKnife,TomatoKinfe
- CookLi(李厨师类)实现TomatoKinfe,PotatoKnife
- FruitShop(水果店类)cutApple方法和cutTomato方法分别传入AppleKnife和TomatoKinfe
- VegetableShop(蔬菜店类)cutTomato方法和cutPotato方法分别传入TomatoKinfe和PotatoKnife
public class SegregationDemo {
public static void main(String[] args) {
//水果店类
new FruitShop().cutApple(new CookZhang());
new FruitShop().cutTomato(new CookZhang());
//蔬菜店类
new VegetableShop().cutTomato(new CookLi());
new VegetableShop().cutPotato(new CookLi());
}
}
//示例接口隔离原则
// 将接口knife拆分为三个独立的接口
interface AppleKnife {
//切苹果的能力
void cutApple();
}
interface TomatoKinfe{
//切番茄的能力
void cutTomato();
}
interface PotatoKnife{
//切土豆的能力
void cutPotato();
}
//张厨师类
class CookZhang implements AppleKnife,TomatoKinfe {
@Override
public void cutApple() {
System.out.println("张厨师正在切苹果");
}
@Override
public void cutTomato() {
System.out.println("张厨师正在切番茄");
}
}
//李厨师类
class CookLi implements TomatoKinfe,PotatoKnife {
@Override
public void cutTomato() {
System.out.println("李厨师正在切番茄");
}
@Override
public void cutPotato() {
System.out.println("李厨师正在切土豆");
}
}
/*假设有这样一个案例场景,现在有一个接口knife,给定他有三个能力,可以切苹果,切番茄,切土豆,
两个类张厨师,李厨师分别具有这些能力,有一个水果店类,假设是需要张师傅来切苹果和切番茄,而另一个蔬菜店类需要
李师傅来切番茄和切土豆*/
//水果店类
class FruitShop {
// 将接口类型作为参数传入
public void cutApple(AppleKnife knife) {
knife.cutApple();
}
public void cutTomato(TomatoKinfe knife) {
knife.cutTomato();
}
}
//蔬菜店类
class VegetableShop {
public void cutTomato(TomatoKinfe knife) {
knife.cutTomato();
}
public void cutPotato(PotatoKnife knife) {
knife.cutPotato();
}
}
案例总结
接口隔离原则就是当我一个类通过接口依赖(使用)另一个类的时候,要保证依赖的该接口是最小的,
接口里面有方法用不到的,就进行隔离,而隔离的做法就是,就对原来接口进行拆分,拆分为最小粒度,来避免耦合
三 与单一职责原则对比
单一职责原则:合理的职责分解,一个类只负责一项职责
接口隔离原则:类间的依赖关系应该建立在最小的接口上
相同点
都要求对结构进行拆分,都要求更小的粒度,都希望减少耦合
不同点
审视角度的不同
单一职责原则:类与接口职责单一,注重的是职责
接口隔离原则:要求我们尽量使用多个专门的接口,注重的是接口的设计
我们使用接口隔离原则进行接口拆分的时候,要遵循单一职责原则