C#软件设计——小话设计模式原则之:接口隔离原则ISP
前言:有朋友问我,设计模式原则这些东西在园子里都讨论烂了,一搜一大把的资料,还花这么大力气去整这个干嘛。博主不得不承认,园子里确实很多这方面的文章,并且不乏出色的博文。博主的想法是,既然要完善知识体系,就不能半途而废。今天就来看看设计模式原则的另一个:接口隔离原则。
软件设计原则系列文章索引
- C#软件设计——小话设计模式原则之:依赖倒置原则DIP
- C#软件设计——小话设计模式原则之:单一职责原则SRP
- C#软件设计——小话设计模式原则之:接口隔离原则ISP
- C#软件设计——小话设计模式原则之:开闭原则OCP
一、原理介绍
1、官方定义
接口隔离原则,英文缩写ISP,全称Interface Segregation Principle。
原始定义:Clients should not be forced to depend upon interfaces that they don't use,还有一种定义是The dependency of one class to another one should depend on the smallest possible interface。
官方翻译:其一是不应该强行要求客户端依赖于它们不用的接口;其二是类之间的依赖应该建立在最小的接口上面。简单点说,客户端需要什么功能,就提供什么接口,对于客户端不需要的接口不应该强行要求其依赖;类之间的依赖应该建立在最小的接口上面,这里最小的粒度取决于单一职责原则的划分。
2、自己理解
2.1、原理解释
- 不应该强行要求客户端依赖于它们不用的接口。语句很好理解,即客户端需要什么接口,就依赖什么接口,不需要的就不依赖。那么我们反过来说,如果客户端依赖了它们不需要的接口,那么这些客户端程序就面临不需要的接口变更引起的客户端变更的风险,这样就会增加客户端和接口之间的耦合程度,显然与“高内聚、低耦合”的思想相矛盾。
- 类之间的依赖应该建立在最小的接口上面。何为最小的接口,即能够满足项目需求的相似功能作为一个接口,这样设计主要就是为了“高内聚”。那么我们如何设计最小的接口呢?那就要说说粒度的划分了,粒度细化的程度取决于我们上一章讲的的单一职责原则里面接口划分的粒度。从这一点来说,接口隔离和单一职责两个原则有一定的相似性。
2.2、接口隔离原则和单一职责原则
从功能上来看,接口隔离和单一职责两个原则具有一定的相似性。其实如果我们仔细想想还是有区别的。
(1)从原则约束的侧重点来说,接口隔离原则更关注的是接口依赖程度的隔离,更加关注接口的“高内聚”;而单一职责原则更加注重的是接口职责的划分。
(2)从接口的细化程度来说,单一职责原则对接口的划分更加精细,而接口隔离原则注重的是相同功能的接口的隔离。接口隔离里面的最小接口有时可以是多个单一职责的公共接口。
(3)单一职责原则更加偏向对业务的约束,接口隔离原则更加偏向设计架构的约束。这个应该好理解,职责是根据业务功能来划分的,所以单一原则更加偏向业务;而接口隔离更多是为了“高内聚”,偏向架构的设计。
二、场景示例
下面就以订单的操作为例来说明下接口隔离的必要性。
1、胖接口
软件设计最初,我们的想法是相同功能的方法放在同一个接口里面,如下,所有订单的操作都放在订单接口IOrder里面。理论上来说,这貌似没错。我们来看看如何设计。
public interface IOrder
{
//订单申请操作
void Apply(object order); //订单审核操作
void Approve(object order); //订单结束操作
void End(object order); }
刚开始只有销售订单,我们只需要实现这个接口就好了。
public class SaleOrder:IOrder
{
public void Apply(object order)
{
throw new NotImplementedException();
} public void Approve(object order)
{
throw new NotImplementedException();
} public void End(object order)
{
throw new NotImplementedException();
}
}
后来,随着系统的不断扩展,我们需要加入生产订单,生产订单也有一些单独的接口方法,比如:排产、冻结、导入、导出等操作。于是我们向订单的接口里面继续加入这些方法。于是订单的接口变成这样:
public interface IOrder
{
//订单申请操作
void Apply(object order); //订单审核操作
void Approve(object order); //订单结束操作
void End(object order); //订单下发操作
void PlantProduct(object order); //订单冻结操作
void Hold(object order); //订单删除操作
void Delete(object order); //订单导入操作
void Import(); //订单导出操作
void Export();
}
我们生产订单的实现类如下
//生产订单实现类
public class ProduceOrder : IOrder
{
/// <summary>
/// 对于生产订单来说无用的接口
/// </summary>
/// <param name="order"></param>
public void Apply(object order)
{
throw new NotImplementedException();
} /// <summary>
/// 对于生产订单来说无用的接口
/// </summary>
/// <param name="order"></param>
public void Approve(object order)
{
throw new NotImplementedException();
} /// <summary>
/// 对于生产订单来说无用的接口
/// </summary>
/// <param name="order"></param>
public void End(object order)
{
throw new NotImplementedException();
} public void PlantProduct(object order)
{
Console.WriteLine("订单下发排产");
} public void Hold(object order)
{
Console.WriteLine("订单冻结");
} public void Delete(object order)
{
Console.WriteLine("订单删除");
} public void Import()
{
Console.WriteLine("订单导入");
} public void Export()
{
Console.WriteLine("订单导出");
}
}
销售订单的实现类也要相应做修改
//销售订单实现类
public class SaleOrder:IOrder
{
public void Apply(object order)
{
Console.WriteLine("订单申请");
} public void Approve(object order)
{
Console.WriteLine("订单审核处理");
} public void End(object order)
{
Console.WriteLine("订单结束");
} #region 对于销售订单无用的接口方法
public void PlantProduct(object order)
{
throw new NotImplementedException();
} public void Hold(object order)
{
throw new NotImplementedException();
} public void Delete(object order)
{
throw new NotImplementedException();
} public void Import()
{
throw new NotImplementedException();
} public void Export()
{
throw new NotImplementedException();
}
#endregion
}
需求做完了,上线正常运行。貌似问题也不大。系统运行一段时间之后,新的需求变更来了,要求生成订单需要一个订单撤销排产的功能,那么我们的接口是不是就得增加一个订单撤排的接口方法CancelProduct。于是乎接口变成这样:
public interface IOrder
{
//订单申请操作
void Apply(object order); //订单审核操作
void Approve(object order); //订单结束操作
void End(object order); //订单下发操作
void PlantProduct(object order); //订单撤排操作
void CancelProduct(object order); //订单冻结操作
void Hold(object order); //订单删除操作
void Delete(object order); //订单导入操作
void Import(); //订单导出操作
void Export();
}
这个时候问题就来了,我们的生产订单只要实现这个撤销的接口貌似就OK了,但是我们的销售订单呢,本来销售订单这一块我们不想做任何的变更,可是由于我们IOrder接口里面增加了一个方法,销售订单的实现类是不是也必须要实现一个无效的接口方法?这就是我们常说的“胖接口”导致的问题。由于接口过“胖”,每一个实现类依赖了它们不需要的接口,使得层与层之间的耦合度增加,结果导致了不需要的接口发生变化时,实现类也不得不相应的发生改变。这里就凸显了我们接口隔离原则的必要性,下面我们就来看看如何通过接口隔离来解决上述问题。
2、接口隔离
我们将IOrder接口分成两个接口来设计
//删除订单接口
public interface IProductOrder
{
//订单下发操作
void PlantProduct(object order); //订单撤排操作
void CancelProduct(object order); //订单冻结操作
void Hold(object order); //订单删除操作
void Delete(object order); //订单导入操作
void Import(); //订单导出操作
void Export();
} //销售订单接口
public interface ISaleOrder
{
//订单申请操作
void Apply(object order); //订单审核操作
void Approve(object order); //订单结束操作
void End(object order);
}
对应的实现类只需要实现自己需要的接口即可
//生产订单实现类
public class ProduceOrder : IProductOrder
{
public void PlantProduct(object order)
{
Console.WriteLine("订单下发排产");
} public void CancelProduct(object order)
{
Console.WriteLine("订单撤排");
} public void Hold(object order)
{
Console.WriteLine("订单冻结");
} public void Delete(object order)
{
Console.WriteLine("订单删除");
} public void Import()
{
Console.WriteLine("订单导入");
} public void Export()
{
Console.WriteLine("订单导出");
}
} //销售订单实现类
public class SaleOrder : ISaleOrder
{ public void Apply(object order)
{
Console.WriteLine("订单申请");
} public void Approve(object order)
{
Console.WriteLine("订单审核处理");
} public void End(object order)
{
Console.WriteLine("订单结束");
}
}
这样设计就能完美解决上述“胖接口”导致的问题,如果需要增加订单操作,只需要在对应的接口和实现类上面修改即可,这样就不存在依赖不需要接口的情况。通过这种设计,降低了单个接口的复杂度,使得接口的“内聚性”更高,“耦合性”更低。由此可以看出接口隔离原则的必要性。
三、总结
通过以上订单功能的优化,我们看到了接口隔离原则的必要性,当然,关于接口隔离原则和单一职责原则的细节我们也不必过多追究,不管何种原则,能解决我们的设计问题就是好的原则、我们必须遵守的原则。欢迎园友拍砖斧正。如果园友们觉得本文对你有帮助,请帮忙推荐,博主将继续努力~~
C#软件设计——小话设计模式原则之:接口隔离原则ISP的更多相关文章
- C#软件设计——小话设计模式原则之:依赖倒置原则DIP
前言:很久之前就想动笔总结下关于软件设计的一些原则,或者说是设计模式的一些原则,奈何被各种bootstrap组件所吸引,一直抽不开身.群里面有朋友问博主是否改行做前端了,呵呵,其实博主是想做“全战”, ...
- C#软件设计——小话设计模式原则之:单一职责原则SRP
前言:上篇C#软件设计——小话设计模式原则之:依赖倒置原则DIP简单介绍了下依赖倒置的由来以及使用,中间插了两篇WebApi的文章,这篇还是回归正题,继续来写写设计模式另一个重要的原则:单一职责原则. ...
- C#软件设计——小话设计模式原则之:开闭原则OCP
前言:这篇继续来看看开闭原则.废话少说,直接入正题. 软件设计原则系列文章索引 C#软件设计——小话设计模式原则之:依赖倒置原则DIP C#软件设计——小话设计模式原则之:单一职责原则SRP C#软件 ...
- 设计原则:接口隔离原则(ISP)
接口隔离原则的英文是Interface Segregation Principle,缩写就是ISP.与里氏替换原则一样其定义同样有两种 定义1: Clients should not be force ...
- 面向对象的六大原则之 接口隔离原则——ISP
ISP = Interface Segregation Principle ISP的定义如下: 1.客户端不应该依赖他不需要的接口 2.一个类对另外一个类的依赖性应该是建立在最小的接口上 3.不应 ...
- IOS设计模式的六大设计原则之接口隔离原则(ISP,Interface Segregation Principle)
定义 客户端不应该依赖它不需要的接口: 一个类对另一个类的依赖应该建立在最小的接口上. 定义解读 定义包含三层含义: 一个类对另一个类的依赖应该建立在最小的接口上: 一个接口代表一个角色,不应该将不同 ...
- 最简单直接地理解Java软件设计原则之接口隔离原则
理论性知识 定义 接口隔离原则, Interface Segregation Principle,(ISP). 一个类对应一个类的依赖应该建立在最小的接口上: 建立单一接口,不要建立庞大臃肿的接口: ...
- 设计模式 第一天 UML图,设计模式原则:开闭原则、依赖倒转原则、接口隔离原则、合成复用原则、迪米特法则,简单工厂模式
1 课程大纲 2 UML的概述 总结: UML unified model language 统一建模语言 一共有十种图: 类图 用例图 时序图 * 对象图 包图 组件图 部署图 协作图 状态图 (最 ...
- java设计模式学习笔记--接口隔离原则
接口隔离原则简述 客户端不应该依赖它不需要的接口,即一个类对另一个类的依赖应建立在最小的接口上 应用场景 如下UML图 类A通过接口Interface1依赖类B,类C通过接口Interface1依赖类 ...
随机推荐
- Eclipse开发环境设置(Maven+Spring MVC+Flex)
1. 环境设置 1.1. Java环境设置 1)JAVA_HOME D:\GreenSoftware\Java\Java8X64\jdk1.8.0_91 2)PATH ;%JAVA_HOME%/bin ...
- AMD规范与CMD规范的区别是什么?
AMD规范与CMD规范的区别是什么? 在比较之前,我们得先来了解下什么是AMD规范?什么是CMD规范?当然先申明一下,我个人也是总结下而已,也是网上看到的资料,自己总结下或者可以说整理下而已,供 ...
- iOS UIPageViewController
UIPageViewController是App中常用的控制器.它提供了一种分页效果来显示其childController的View.用户可以通过手势像翻书一样切换页面.切换页面时看起来是连续的,但静 ...
- Http相关知识
Http的无状态性 无状态是指,当浏览器发送请求给服务器的时候,服务器响应客户端的请求.但是当同一个浏览器再次发送请求给服务器的时候,服务器并不知道它就是刚才的浏览器.简单的说就是,服务器不会去记得你 ...
- 熟悉HTML CSS布局模型
HTML最难的地方来了!这个我反复了很多遍, 包括现在写博客, 也对我自己算是一种温习, 我这块怕是没办法写的很好懂, 因为我自己还不能把我学到的准确通俗易懂的表达出来, 给自己记个笔记, 以后再来一 ...
- VSALM 动手实验 - 持续集成
Visual Studio 应用生命周期管理(VSALM - Visual Studio Application Lifecycle Managemnet)是微软基于Visual Studio产品线所 ...
- javascript-装饰者模式
装饰者模式笔记 在不改变原对象的基础上, 通过对其进行包装拓展(添加属性或方法)使原有对象可以满足用户的更复杂要求. 需求不是一成不变的,需求会不断改进,以增强用户体验 demo实例:对输入框添加fo ...
- NHibernate Profiler使用方法
NHibernate Profiler是一款可以监视NHibernate里的sql语句的工具 1.下载NHibernate Profiler 2.在你的NHibernate项目中添加引用(在NHibe ...
- Java中图片压缩处理
原文http://cuisuqiang.iteye.com/blog/2045855 整理文档,搜刮出一个Java做图片压缩的代码,稍微整理精简一下做下分享. 首先,要压缩的图片格式不能说动态图片,你 ...
- Window下python2.7+Apache+mod_wsgi+Django服务器配置
前言:试着使用python搭建一个网页,分别在windows下和linux下,本篇文章主要讲解Window下python+Apache+mod_wsgi+Django服务器配置过程中遇见的问题和解决方 ...