Java设计原则 - 接口隔离原则

六大设计原则

  • 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());
    }
}

这样拆分接口之后,各个类去实现它们所需要的接口,不用去强制实现它们不需要的接口方法。所以,设计接口时,不要试图建立一个庞大的接口给相关类去依赖,要懂得适度拆分接口。

注意

虽然拆分接口可以提高程序设计灵活性,但是过度的拆分,会造成接口数量过多,反而使程序复杂化。记住,过犹不及,一定要适度拆分接口!!!

小结

在程序设计中,依赖几个专用的接口要比依赖一个综合的接口更灵活。接口是设计时对外部设定的“契约”,通过分散定义多个接口,可以预防外来变更的扩散,提高系统的灵活性和可维护性。

你可能感兴趣的:(Java,软件设计原则)