阅读本文大概需要 5 分钟
-
前言
-
1.接口隔离原则概述
-
1.1. 定制服务
-
1.2. 接口污染
-
-
2.接口隔离原则的实际应用
-
2.1. 备忘录模式中的体现
-
前言
1. 接口隔离原则概述
接口隔离原则前面也讲过就是对接口的隔离,那么为什么要对接口隔离呢?主要因为对外暴露接口时有时并不需要暴暴露所有的接口,只需要暴露一定的接口,因此需要对接口进行一定的隔离,将不需要隔离的接口进行隔离。
1.1. 定制服务
比如有一个角色服务,这个服务包含三个方法,分别为method1、method2、method3,这三个方法分别对应三个不同的客户端,正常的操作我们会将三个方法都集成到一个接口中,然后三个客户端实现拥有三个方法的接口,但是我们知道每个客户端都只需要一个方法即可,这样实现对每个客户端就多暴露了两个方法,那么这时就可以使用接口隔离原则,将三个方法分别实现各自的接口,然后再由三个客户端实现,这样就保证了对每个客户端都只暴露需要的方法而不会多暴露额外的方法。
1.2. 接口污染
以上是接口隔离最简单的例子,通过这个例子也可以看出在实际开发中可能会为了便捷而将方法都集成到一个接口中,造成接口的臃肿以及污染,在后续开发中如果需要对外暴露服务方法,那么就无法便捷的实现接口的隔离,所以在实现接口前可以对需要实现的接口进行分析,即每个接口都只实现一种角色或者一种类型任务。
例如有一个Person接口,接口中有eat、drink、walk、run、work、learn等方法,那么我们就可以将Person接口中的方法进行拆分,可以将eat、drink作为一个单独的接口,walk、run作为一个单独的接口、work、learn作为单独的接口,这样就保证了每个接口都只做同一类型的事情,保证一个接口代表一种角色,实现一个接口的对象。这样在后期需要对外暴露服务时可以便捷的实现,从而维护整个系统的稳定以及实用性。
2. 接口隔离原则的实际应用
2.1. 备忘录模式中的体现
备忘录模式是在不破坏封装的条件下,捕捉一个对象的状态,并将之外部化,从而可以在将来合适的时候把这个对象还原到存储起来的状态。
以上代码的例子很好的保证了在不更改封装的条件下捕捉Originator对象的状态,并且经过Memento将该状态存储下来,最后再由CareTaker进行恢复。
对于不破坏封装的理解来说,即需要备忘录对象向外界提供双重接口,一个宽接口,一个窄接口。以上例子中宽接口指的是CareTaker,窄接口指的是Originator。
宽接口可以理解为是需要访问备忘录角色存储的信息,以便恢复自己的状态。
窄接口可以理解为不需要读取备忘录所存储的信息,只要得到一个状态即可。
备忘录模式通过这样的方式实现接口隔离原则,保证了对外提供的接口是轻便不臃肿的。所以说接口隔离原则是指导思想,备忘录模式是实际应用。
/**
* 原始类,该类的会将状态存储到Memento中
* 该类是最初的使用类,使用时变更状态会存储到Memento类中,Memento相当于一个备忘录
*/
public class Originator {
/**
* 以一个状态进行标识,如果状态变更会将该状态存储到Memento中
*/
private String state;
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
/**
* 与Memento进行关联的方法
* @return
*/
public Memento saveStateToMemento() {
return new Memento(state);
}
/**
* 与Memento进行关联的方法
* @return
*/
public void getStateFromMemento(Memento memento) {
state = memento.getState();
}
}
/**
* 保存Originator类的状态类,该类相当于一个备忘录,存储修改的状态,
* Originator修改一次状态,那么就会请求到Memento类进行修改其中的状态
*/
public class Memento {
private String state;
public Memento(String state) {
this.state = state;
}
public String getState() {
return state;
}
}
/**
* 恢复状态类,通过该类可以从Memento类中恢复对象的状态
*/
public class CareTaker {
private List<Memento> mementoList = new ArrayList<>();
public void add(Memento memento) {
mementoList.add(memento);
}
public Memento get(int index) {
return mementoList.get(index);
}
}
/**
*
*/
public class MementoDemo {
public static void main(String[] args) {
Originator originator = new Originator();
CareTaker careTaker = new CareTaker();
/**
* 修改originator的状态
*/
originator.setState("state #1");
originator.setState("state #2");
careTaker.add(originator.saveStateToMemento());
originator.setState("state #3");
careTaker.add(originator.saveStateToMemento());
originator.setState("state #4");
System.out.println("current state:" +originator.getState());
//恢复Memento中的状态
originator.getStateFromMemento(careTaker.get(0));
System.out.println("first save state:"+originator.getState());
//恢复Memento中的状态
originator.getStateFromMemento(careTaker.get(1));
System.out.println("second save state:"+originator.getState());
}
}
依赖倒转的核心是:要依赖于抽象,不要依赖于具体。对这句话的理解抽象就是我们平时接触的接口,接口做的是确定我们要做的目标,而具体则是指实现这个接口的类,这个类中做了实现目标的具体过程。
参考资料:
1、《Java与模式》