六大设计原则
- Java设计原则 - 单一职责原则
- Java设计原则 - 里氏替换原则
- Java设计原则 - 依赖倒置原则
- Java设计原则 - 接口隔离原则
- Java设计原则 - 迪米特法则
- Java设计原则 - 开闭原则
定义
客户端不应该依赖它不需要的接口;一个类对另一个类的依赖应该建立在最小的接口上。
总的来说,我们应该要适度拆分接口,举个例子就明白为什么要拆分接口了。
场景
我们设计一台手机,能打电话,发短信,很简单
public interface IPhone {
// 打电话
void call(String number);
// 发短信
void sendMessage(String number, String content);
}
public class Phone implements IPhone {
// 打电话
public void call(String number) {
System.out.println("打电话给" + number);
}
// 发短信
public void sendMessage(String number, String content) {
System.out.println("给" + number + "发短信,内容是" + content);
}
}
现在的手机一般都有拍照和播放媒体功能,所以IPhone接口得添加多2中方法:
public interface IPhone {
// 打电话
void call(String number);
// 发短信
void sendMessage(String number, String content);
// 拍照
void takePicture();
// 播放媒体
void play(Media media);
}
public class Phone implements IPhone {
// 打电话
public void call(String number) {
System.out.println("打电话给" + number);
}
// 发短信
public void sendMessage(String number, String content) {
System.out.println("给" + number + "发短信,内容是" + content);
}
// 拍照
public void takePicture() {
System.out.println("拍照");
}
// 播放媒体
public void play(Media media) {
System.out.println("播放" + media.getName());
}
}
为了满足老年人需求,出一款功能机,这款功能机只有打电话和发短信功能,使用IPhone的接口:
public class FunctionPhone implements IPhone {
// 打电话
public void call(String number) {
System.out.println("打电话给" + number);
}
// 发短信
public void sendMessage(String number, String content) {
System.out.println("给" + number + "发短信,内容是" + content);
}
// 拍照
public void takePicture() {
// 空实现
}
// 播放媒体
public void play(Media media) {
// 空实现
}
}
后来公司发展了,出一款Pad平板,平板只有拍照和播放媒体的功能,还是使用IPhone接口:
public class Pad implements IPhone {
// 打电话
public void call(String number) {
// 空实现
}
// 发短信
public void sendMessage(String number, String content) {
// 空实现
}
// 拍照
public void takePicture() {
System.out.println("拍照");
}
// 播放媒体
public void play(Media media) {
System.out.println("播放" + media.getName());
}
}
到这里,你会发现,功能机FunctionPhone类和平板Pad类都依赖了他们不需要的接口,对于不需要的方法又必须去实现(虽然是空实现)。这显然是一个不好的设计,IPhone接口过于臃肿,我们必须对其进行拆分。
public interface IPhone1 {
// 打电话
void call(String number);
// 发短信
void sendMessage(String number, String content);
}
public interface IPhone2 {
// 拍照
void takePicture();
// 播放媒体
void play(Media media);
}
// 正常手机
public class Phone implements IPhone1, IPhone2 {
// 打电话
public void call(String number) {
System.out.println("打电话给" + number);
}
// 发短信
public void sendMessage(String number, String content) {
System.out.println("给" + number + "发短信,内容是" + content);
}
// 拍照
public void takePicture() {
System.out.println("拍照");
}
// 播放媒体
public void play(Media media) {
System.out.println("播放" + media.getName());
}
}
// 功能机
public class FunctionPhone implements IPhone1 {
// 打电话
public void call(String number) {
System.out.println("打电话给" + number);
}
// 发短信
public void sendMessage(String number, String content) {
System.out.println("给" + number + "发短信,内容是" + content);
}
}
// 平板
public class Pad implements IPhone2 {
// 拍照
public void takePicture() {
System.out.println("拍照");
}
// 播放媒体
public void play(Media media) {
System.out.println("播放" + media.getName());
}
}
这样拆分接口之后,各个类去实现它们所需要的接口,不用去强制实现它们不需要的接口方法。所以,设计接口时,不要试图建立一个庞大的接口给相关类去依赖,要懂得适度拆分接口。
注意
虽然拆分接口可以提高程序设计灵活性,但是过度的拆分,会造成接口数量过多,反而使程序复杂化。记住,过犹不及,一定要适度拆分接口!!!
小结
在程序设计中,依赖几个专用的接口要比依赖一个综合的接口更灵活。接口是设计时对外部设定的“契约”,通过分散定义多个接口,可以预防外来变更的扩散,提高系统的灵活性和可维护性。