一.定义
接口隔离原则(Interface Segregation Principle)
1、接口的划分:
一说接口,大家第一印象想到的是Java的抽象代名词,这个并没错,但是这是狭义的,下面说说接口划分,接口是分为两种
1.1、实例接口(Object Interface)
在Java中声明一个类,然后new产生一个实例,是对一个类型食物的描述,这是一种接口
比如:WEB项目说的提供给前端访问的接口,或者说组长让你先把接口的API(类、方法、属性)提供给其他同事,可以并行开发
1.2、类接口(Class Interface)
就是我们说的关键字 interface修饰的类(Java的interface接口),项目中的代码规范以及为了提高代码的扩展性和可维护性定义的规范:
所以接口隔离原则的接口并不是狭义的在Java中interface定义的接口,而是一种广义的接口,可以是接口、抽象类、实体类。
2、接口隔离原则定义如下:
2.1客户端不应该依赖他不需要的接口;
2.2类的依赖关系应该建立在最小接口;
2.3不应该将不同的接口合并到一起,形成一个臃肿的大接口,这是对接口都污染
2.4使用多个专门的接口要比使用单一的总接口要好
不要再一个接口里面放很多方法,这样显的这个类臃肿不堪。接口应该尽量细化,一个接口对应一个功能模块,同时接口里面的方法应该尽可能的少
接口方法尽可能少是在接口设计的时候考虑的,例如一个接口的职责包含10个方法,这10个方法都放在一个接口中,并且提供给多个模块访问,各个模块按照规定的权限来访问,并规定了“不使用的方法不能访问”,这样的设计是不符合接口隔离原则的,接口隔离原则要求“尽量使用多个专门的接口”,这里专门的接口就是指提供给每个模块的都应该是单一接口(即每一个模块对应一个接口),而不是建立一个庞大臃肿的接口来容纳所有的客户端访问。
其实就是说一个接口最好针对一个功能模块,这样子我们客户端可以只需要依赖他需要的,不需要的就不用去实现了
二.示例
场景:我们平常吃饭的餐馆:需要点菜 洗菜 切菜 炒菜 上菜 收钱
一般个人的很小的餐馆:老板当服务员点菜,洗菜,切擦,炒菜,上菜,然后自己收钱
问题:老板生意好,扩大经营,招了10个人,每个人负责自己的客人从点菜到收钱,老板发现人手不够,然后有招了5个人但是发现餐馆依然忙碌,混乱,而且有的客人说菜不好吃
分析:老板就分析,有的人会做粤菜 有的人会做川菜,有的人只会做自己吃吃的菜,有的人刀工好切菜很快,有的人口才好对客人热情,有的人闷闷的不怎么说话
尝试:1.把 切菜 做菜 洗菜某一种优秀的都分归后厨管理,这样厨师长会自己分配;2.把口才好热情的来点菜,把闷闷不说话的上菜等都贵前台管
结果:第二天老板发现,客人说菜比以前进步了是不是来了新厨师,菜也上的快了,整个一天紧紧有条,大家也没有那么累了
1 public interface IChelf { 2 3 public void cooking(); 4 5 public void wash(); 6 } 7 8 public class SichuanChelf implements IChelf { 9 10 @Override 11 public void cooking() { 12 System.out.println("做四川菜"); 13 } 14 15 @Override 16 public void wash() { 17 18 } 19 } 20 // 粤菜厨师 21 public class CantoneseChelf implements IChelf { 22 @Override 23 public void cooking() { 24 System.out.println("我会做粤菜"); 25 } 26 27 @Override 28 public void wash() { 29 30 } 31 } 32 33 // 学徒 34 public class Apprentice implements IChelf { 35 @Override 36 public void cooking() { 37 System.out.println("学习川菜"); 38 } 39 40 @Override 41 public void wash() { 42 System.out.println("学徒从洗菜切菜开始"); 43 } 44 } 45 46 // 厨师长 47 public class HeadChelf { 48 private IChelf chelf; 49 private IChelf apprentice; 50 51 public void cooking(String foodName){ 52 getChelf(foodName); 53 if (null == chelf){ 54 System.out.println("我没有这方面的厨师"); 55 return; 56 } 57 apprentice.wash(); 58 chelf.cooking(); 59 } 60 61 private void getChelf(String foodName){ 62 if (foodName.contains("四川")){ 63 this.chelf = new SichuanChelf(); 64 this.apprentice = new Apprentice(); 65 } else if (foodName.contains("粤菜")) { 66 this.chelf = new CantoneseChelf(); 67 this.apprentice = new Apprentice(); 68 } else { 69 System.out.println("我们没有这个菜品"); 70 } 71 } 72 } 73 74 // 服务员 75 public class Waiter { 76 private HeadChelf headChelf = new HeadChelf(); 77 public void order(String foodName){ 78 headChelf.cooking(foodName); 79 } 80 } 81 82 // 大厅 83 public class Client { 84 85 public static void main(String[] args) { 86 System.out.println("客人:服务员我点菜"); 87 System.out.println("服务员说:你点什么菜"); 88 System.out.println("客人说:四川菜"); 89 Waiter waiter = new Waiter(); 90 waiter.order("四川菜"); 91 System.out.println("==========================="); 92 System.out.println("另一个客人说我要吃粤菜"); 93 waiter.order("粤菜"); 94 } 95 }
运行结果:服务就负责点菜然后交给厨师就行,厨师就负责做菜;然后厨师又分为:洗菜和做菜都由厨师长自己分配,这里既体现了一个接口对应一个功能,接口隔离原则,又体现了单一职责原则,
当然两者适当运用,还体现了依赖倒置原则和开闭原则