接口隔离原则
接口隔离原则(Interface Segregation Principle, ISP)表明客户端不应该被强迫实现一些他们不会使用的接口,应该把胖接口中的方法分组,然后用多个接口替代它,每个接口服务于一个子模块。简单地说,就是使用多个专门的接口比使用单个接口要好很多。
接口隔离原则基本观点
1)一个类对另外一个类的依赖性应当是建立在最小的接口上的。
ISP 可以达到不强迫客户(接口的使用方法)依赖于他们不用的方法,接口的实现类应该只呈现为单一职责的角色(遵循 SRP 原则) ISP 还可以降低客户之间的相互影响—当某个客户要求提供新的职责(需要变化)而迫使接口发生改变时,影响到其他客户程序的可能性最小。
2)客户端程序不应该依赖它不需要的接口方法(功能)。
客户端程序就应该依赖于它不需要的接口方法(功能),那依赖于什么?依赖它所需要的接口。客户端需要什么接口就是提供什么接口,把不需要的接口剔除,这就要求对接口进行细化,保证其纯洁性。
比如在继承时,由于子类将继承父类中的所有可用方法;而父类中的某些方法,在子类中可能并不需要。例如,普通员工和经理都继承自雇员这个接口,员工需要每天写工作日志,而经理不需要。因此不能用工作日志来卡经理,也就是经理不应该依赖于提交工作日志这个方法。
案例-电子商务的系统订单处理
UML结构如下:
设计思想
一个是用户,只能有查询方法,
一个是外部系统,有添加订单的方法,
一个是管理后台,添加删除修改查询都要用到.
根据接口隔离原则(ISP),一个类对另外一个类的依赖性应当是建立在最小的接口上.
也就是说,对于用户,它只能依赖有一个查询方法的接口.
代码实现
(1)IOrderForPortal 接口
package interfaceSeparate;
public interface IOrderForPortal {
String getOrder();
}
(2)IOrderForOtherSys 接口
package interfaceSeparate;
public interface IOrderForOtherSys {
String insertOrder();
}
(3)IOrderForAdmin 接口
package interfaceSeparate;
public interface IOrderForAdmin {
String deleteOrder();
String updateOrder();
String insertOrder();
String getOrder();
}
(4)Order 类
package interfaceSeparate;
public class Order implements IOrderForAdmin,IOrderForOtherSys,IOrderForPortal {
private Order(){
//--什么都不干,就是为了不让直接 new,防止客户端直接New,然后访问它不需要的方法.
}
//返回给Portal
public static IOrderForPortal getOrderForPortal(){
return (IOrderForPortal)new Order();
}
//返回给OtherSys
public static IOrderForOtherSys getOrderForOtherSys(){
return (IOrderForOtherSys)new Order();
}
//返回给Admin
public static IOrderForAdmin getOrderForAdmin(){
return (IOrderForAdmin)new Order();
}
//--下面是接口方法的实现.只是返回了一个String用于演示
public String getOrder(){
return "implemented getOrder";
}
public String insertOrder(){
return "implemented insertOrder";
}
public String updateOrder(){
return "implemented updateOrder";
}
public String deleteOrder(){
return "implemented deleteOrder";
}
}
(5)InterfaceSeparateTest 类(测试类)
package interfaceSeparate;
public class InterfaceSeparateTest {
public static void main(String[] args) {
IOrderForPortal orderForPortal = Order.getOrderForPortal();
IOrderForOtherSys orderForOtherSys = Order.getOrderForOtherSys();
IOrderForAdmin orderForAdmin = Order.getOrderForAdmin();
System.out.println("Portal门户调用方法:" + orderForPortal.getOrder());
System.out.println("OtherSys外部系统调用方法:" + orderForOtherSys.insertOrder());
System.out.println("Admin管理后台调用方法:" + orderForAdmin.getOrder() + ";" + orderForAdmin.insertOrder() + ";"
+ orderForAdmin.updateOrder() + ";" + orderForAdmin.deleteOrder());
}
}
这样就能很好的满足接口隔离原则了,调用者只能访问它自己的方法,不能访问到不应该访问的方法.
但是以上实现却未能很好的满足单一职责原则,故进行以下改进:
package interfaceSeparate;
public class DiffInterface {
//接口隔离原则
public static void main(String[] args) {
Order myorder=new Order();
Portal portal=new Portal();
System.out.println( portal.checkOrder(myorder));
System.out.println("----------------------------------");
OtherSys otherSys=new OtherSys();
System.out.println(otherSys.addOrder(myorder));
System.out.println("----------------------------------");
Admin admin=new Admin();
System.out.println(admin.aOrder(myorder));
System.out.println(admin.bOrder(myorder));
System.out.println(admin.cOrder(myorder));
System.out.println(admin.dOrder(myorder));
}
}
//定义三个接口
interface IOrderForPortal{
String getOrder();
}
interface IOrderForOtherSys{
String insertOrder();
}
interface IOrderAdmin{
String getOrder();
String insertOrder();
String deleteOrder();
String updateOrder();
}
class Order implements IOrderForAdmin,IOrderForOtherSys,IOrderForPortal {
public String getOrder(){
return " getOrder方法";
}
public String insertOrder(){
return "insertOrder方法";
}
public String updateOrder(){
return "updateOrder方法";
}
public String deleteOrder(){
return "deleteOrder方法";
}
}
class Portal{
//关联关系
public String checkOrder(IOrderForPortal iorder){
//对门户开放的接口就只有它。
return "Portal order Info:"+iorder.getOrder();
}
}
class OtherSys{
//关联关系
public String addOrder(IOrderForOtherSys iorder){
//对其他系统开放的接口就只有它。
return "OtherSys order Info:"+iorder.insertOrder();
}
}
class Admin{
public String aOrder(IOrderForAdmin iorder){
//对门户开放的接口就只有它。
return "Admin order Info:"+iorder.insertOrder();
}
public String bOrder(IOrderForAdmin iorder){
//对门户开放的接口就只有它。
return "Admin order Info:"+iorder.getOrder();
}
public String cOrder(IOrderForAdmin iorder){
//对门户开放的接口就只有它。
return "Admin order Info:"+iorder.deleteOrder();
}
public String dOrder(IOrderForAdmin iorder){
//对门户开放的接口就只有它。
return "Admin order Info:"+iorder.updateOrder();
}
}
运行结果:
小结
接口隔离原则和单一职责都是为了提高类的内聚性、降低它们之间的耦合性,体现了封装的思想,但两者是不同的:
单一职责原则注重的是职责,而接口隔离原则注重的是对接口依赖的隔离。
单一职责原则主要是约束类,它针对的是程序中的实现和细节;接口隔离原则主要约束接口,主要针对抽象和程序整体框架的构建。