面向对象设计中的单一职责原则
面向对象设计中的单一职责原则
面向对象设计中的单一职责原则一个优良的系统设计,强调模块间保持低耦合、高内聚的关系,在面向对象设计中这条规则同样适用,所以面向对象的第一个设计原则就是:单一职责原则(SRP,Single Responsibility Principle)。如果一个类承担的职责过多,就等于把这些职责耦合在了一起。当其中一个职责变化时,可能影响其他职责的运作。
单一职责,强调的是职责的分离,在某种程度上对职责的理解,构成了不同类之间耦合关系的设计关键,因此单一职责原则或多或少成为设计过程中一个必须考虑的基础性原则。
在软件编程中,谁也不希望因为修改了一个功能导致其他的功能发生故障。而避免出现这一问题的方法便是遵循单一职责原则。虽然单一职责原则如此简单,并且被认为是常识,但是即便是经验丰富的程序员写出的程序,也会有违背这一原则的代码存在。为什么会出现这种现象呢?因为有职责扩散。所谓职责扩散,就是因为某种原因,职责P被分化为粒度更细的职责P1和P2。
一、遵循单一职责原的优点有:
1、可以降低类的复杂度,一个类只负责一项职责,其逻辑肯定要比负责多项职责简单的多;
2、提高类的可读性,提高系统的可维护性;
3、变更引起的风险降低,变更是必然的,如果单一职责原则遵守的好,当修改一个功能时,可以显著降低对其他功能的影响。
4、需要说明的一点是单一职责原则不只是面向对象编程思想所特有的,只要是模块化的程序设计,都适用单一职责原则。
二、关于单一职责原则,我们的建议是:
1、一个类只有一个引起它变化的原因,否则就应当考虑重构。
2、 SRP由引起变化的原因决定,而不由功能职责决定。虽然职责常常是引起变化的曲线,但是有时却未必,应该审时度势。
3、 测试驱动开发,有助于实现合理分离功能的设计。
4、 可以通过Facade模式或Proxy模式进行职责分离。
5、我们会自然地把职责结合在一起。如果能想到多于一个动机去改变一个类,那么这个类就具有多于一个的职责,就应该考虑类的职责分离。
6、接口一定做到单一职责,类的设计尽量做到只有一个原因引起变化。
7、分层架构模式实际上也体现了这一原则,它将整个系统按照职责的内聚性分为不同的层,层内的模块与类具有宏观的内聚性,它们关注的事情应该是一致的。例如,领域逻辑层就主要关注系统的业务逻辑与业务流程,而数据的持久化与访问则交由数据访问层来负责。
三、以订单的管理为例,我们在领域逻辑层中定义如下的类OrderManager
public class OrderManager { private IOrderRepository repository = RepositoryFactory.CreateOrderRepository(); public void Place(Order order) { if (order.IsValid()) { repository.Add(Order); } else { throw new InvalidOperationException("Order can't be placed. "); } } public void Cancel(Order order) { if (order.IsValid() && order.CanCancel(DateTime.Now)) { repository.Remove(Order); } else { throw new InvalidOperationException("Order can't be canceled. "); } } } public static class RepositoryFactory { public static IOrderRepository CreateOrderRepository() { return new OrderRepository(); } }
OrderManager类的实现体现了单一职责原则的思想。首先,OrderManager类中的Place()和Cancel()方法均属于订单管理的业务逻辑,与领域逻辑层关注的事情是一致的。在这两个方法的实现中,我们需要检验订单的正确性(检验订单是否包含了必要的信息,如联系人、联系地址与联系电话),以及判断当前时间是否在允许取消订单的时间范围内。虽然它们仍然属于订单处理的业务逻辑,但拥有这些检查信息的是Order对象,而不是OrderManager,即Order对象是检查订单的信息专家 。因此,IsValid()和CanCancel()方法应该被定义在Order类中。至于添加和移除订单的操作,虽然保证了下订单和取消订单的业务逻辑实现,但其实现却属于数据访问层的范畴,因而该职责被委派给了OrderRepository类 。至于RepositoryFactory类,则是负责创建OrderRepository对象的工厂类。
这些类的职责以及协作关系如图所示:
将数据访问的逻辑从领域对象中分离出去是有道理的,因为数据访问逻辑的变化方向与订单业务逻辑的变化方向是不一致的,引起职责发生变化的原因也不相同。这也是单一职责原则的核心思想。遵循该原则,就能够有效地分离对象的变与不变,将变化的职责以抽象的方式独立于原对象之外,原对象就更加稳定。我们对访问Order数据表的逻辑进行了封装与抽象,以隔离数据访问逻辑的变化,即使数据访问逻辑发生变化,它影响到的只是OrderRepository类而已。
- python面向对象实例教程(Python面向对象程序设计类的多态用法详解)
- php面向对象怎么用(PHP面向对象程序设计之对象克隆clone和魔术方法__clone用法分析)
- python学生信息管理系统教程(学生信息管理系统Python面向对象版)
- php 面向对象与面向过程(php面向对象重点知识分享)
- php面向对象编程代码(php面向对象程序设计入门教程)
- python面向对象基本思想(详解Python:面向对象编程)
- php使用面向对象如何写好代码(PHP面向对象程序设计模拟一般面向对象语言中的方法重载overload示例)
- python类继承和封装(Python面向对象程序设计类的封装与继承用法示例)
- python中对象方法和顶级方法(Python3.5面向对象程序设计之类的继承和多态详解)
- python对象创建流程(Python3.5面向对象与继承图文实例详解)
- python变量与对象的关系(Python面向对象程序设计类变量与成员变量、类方法与成员方法用法分析)
- php面向对象3大特征(PHP面向对象程序设计重载overloading操作详解)
- python3简单编程(Python3.5面向对象编程图文与实例详解)
- php如何继承多个类(PHP面向对象程序设计子类扩展父类子类重新载入父类操作详解)
- 面向对象的装封、继承、多态的概念理解
- javascript对象添加方法(详解JavaScript面向对象实战之封装拖拽对象)
- 今年考高会很难吗(今年高考会考试吗)
- 盘古开天地 他创造了世界,谁创造了盘古 盘古是伏羲吗(盘古开天地他创造了世界)
- 关于队徽 你了解这些么 二(关于队徽你了解这些么)
- 冬天来了手脚冰凉 真不是因为上辈子你是折翼的天使(冬天来了手脚冰凉)
- 0 1 岁婴儿最强作息指南,照着做养出天使宝宝(01岁婴儿最强作息指南)
- 沪上这16所高校 萌新 礼包开箱 哪一款让你心动(沪上这16所高校萌新)
热门推荐
- mysql提高分页效率(MySQL优化教程之超大分页查询)
- mysql的存储性能优化(MySQL的查询缓存和Buffer Pool)
- 腾讯云服务器配置详解(腾讯云服务器安全组配置图文教程)
- char、nchar、varchar、nvarchar、text、ntext的区别
- vsftpd服务器的安装与配置(编译安装 vsFTP 3.0.3的详细解析)
- 数据化网络流量管理(适合云主机用户使用的流量监控软件)
- vueelementui侧边栏(Vue Element UI自定义描述列表组件)
- laravel自定义实现服务提供者(laravel http 自定义公共验证和响应的方法)
- python str类型怎么转换(Python3中的bytes和str类型详解)
- 云数据中心服务器介绍(云服务器的机房设备有哪些?)
排行榜
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9