单一职责原则(SRP)认为,一个类应该有且只有一个改变的原由。换个说法,一个类中的方法应该出于同样的一种原由而改变,它们不应被不同原由所驱使,而导致朝着不同的方向改变。
举个例子来说,考虑一下以下的Java类:
class Employee
{
public Money calculatePay() {...}
public void save() {...}
public String reportHours() {...}
}
这个类由于拥有三种改变的原由,所以违反了SRP。第一种,是跟支付薪水方式有关的商业规则;第二种,是数据库的结构;第三种,是报表的时间格式的字符串。我们不希望这样一个单一的类会被这三种完全不同原由所影响,不希望因为会计认为需要每天改变报表的时间格式,或是DBA每天都要改变数据库结构,也可能是管理人员每天要改变支付薪水的方式,而去改变Employee类。相反,我们希望把这些方法分离到不同类中,这样它们就既能彼此互不干扰,又可随意改变。
当然这好像又与OO的概念相违背,因为一个好的对象应该包含所有操纵它的方法。分解的做法的确有这种趋势,我们因为不希望商业规则与报表格式混杂起来,所以就需要将这些方法放入到不同的类中。
然而,在Ruby中,情况会有些不同。仔细想想下面三个文件:
employeeBusinessRules.rb
class Employee
def calculatePay ... end
end
employeeDatabaseSave.rb
class Employee
def save ... end
end
employeeHourlyReport.rb
class Employee
def reportHours ... end
end
由于在Ruby中,类是在运行时被创建的(也就是说,上面的代码也可视作是一段程序执行片断),类可能是在程序执行的任意时间被展开,更多的方法和成员也可能是在此时被赋到类上。在主程序中我们也许会看到一些诸如:
require 'employeeBusinessRules.rb'
require 'employeeDatabaseSave.rb'
require 'employeeHourlyReport.rb'
因此,类会在余下的程序开始执行前被构造完成。可是没有一个源文件包含了所有这三个不同的方法。实际上,这三个源文件对彼此一无所知,而这就意味着,这三个文件之间并没有耦合。
毫无疑问,我们必须要关注这些成员。为了能访问这些成员(分散在多个源文件中),我们搞不好会使得这些源文件拙劣的耦合起来。可是,假如你有那么一点点地关注并抽象的话,就能使得这些源文件非常漂亮的解耦,进一步的,还可以把这些方法保留在同一个类中(因此也在同一对象中)!
所以,在Ruby中,不用违反SRP原则,就可以把不同的方法放置在同一个类中,并且属于同一个类。你只需简单的将这些有着不同原由的方法放置在不同的源文件中即可。真是鱼与熊掌得其兼啊!
(原文链接网址:http://www.butunclebob.com/ArticleS.UncleBob.SrpInRuby; Robert C. Martin的英文blog网址:http://www.butunclebob.com/ArticleS.UncleBob)
译者注:Robert C. Martin是Object Mentor公司总裁,面向对象设计、模式、UML、敏捷方法学和极限编程领域内的资深顾问。他不仅是Jolt获奖图书《敏捷软件开发:原则、模式与实践》(中文版)(《敏捷软件开发》(英文影印版))的作者,还是畅销书Designing Object-Oriented C++ Applications Using the Booch Method的作者。Martin是Pattern Languages of Program Design 3和More C++ Gems的主编,并与James Newkirk合著了XP in Practice。他是国际程序员大会上著名的发言人,并在C++ Report杂志担任过4年的编辑。
分享到:
相关推荐
ruby-oo-fundamentals-attribute-accessors-lab-wdc01-seng-ft-060120-源码.rar
ruby-oo-fundamentals-attribute-accessors-lab-sea01-seng-ft-071320-master.rar
ISO 9001:2015品質手冊,係企業組織導入ISO 9001:2015必備之文件,很有實務參考價值.
poi-util-0.0.1-SNAPSHOT.jar
座位预定--- OOJS-本地存储 OOJS和本地存储中的座位预定
-url https://localhost:8443/oo --action show-content-packs 在Central中启用身份验证后: go2oo.exe --url https://localhost:8443/oo --action show-content-packs --user <user> --password <password> 支持...
它着重于使用Java编程,Java是一种现代的OO语言,与供应商无关,并且在行业中广泛使用。 认识到编程需要技能和知识,因此本模块着重于使用专业开发环境开发重要Java程序的实践方面。 学生还将获得程序设计,测试和...
udacity-project-3a-oojs
Progetto-OO-BD- 面向对象的对象-traccia 2-ID gruppo:15 TRACCIA 2:按生成对象进行的规划,由基本的对象构成,并由Java编写JavaFX),请在un'azienda中进行。 项目主管,负责人(每位项目经理)。 知识与财产的...
goods表如下: name time product A 2016-1-2 13:23:00 WFEY B 2016-2-17 11:43;34 ASG A 2017-1-10 15:23:00 SGH ...FROM (SELECT name,DATE_FORMAT(time , '%h:%m') AS ti FROM goods) AS OO WHERE ti BETWEEN '12
Grupo-06-OO2-2020 TPC民主体制
2013-oo-programming-part2 赫尔辛基MOOC的第2部分
很多时候,在设计时有两难的情况,这时候我们必须回归到OO原则,以方便判断取舍。可以这么说:OO原则是我们的目标,而设计模式是我们的做法。 --------------------- 作者:owen2335 来源:CSDN 原文:...
Codecool中的第一个OOP项目。 C#。 故事 两个人的经典战舰游戏。 单人和多人游戏选项。 单人游戏有两个难度等级:简单(相对于醉酒的杰克·斯派洛)和中等(相对于古代无言恶魔,克苏鲁)。 可以自行放置或自动放置...
通过剥离它们来添加对 CSS 中的单行注释的支持。 /* * * OOCSS-style Media block */ .media { // TODO } .media > .mediaImg { float : left ; // TODO add clearfix // margin-right: 1em; margin-right ...
但是, String类是Ruby固有的,或包含在Ruby中。 因此,我们可以像在定义自己的任何类中那样在String类中添加或更改方法。猴子修补猴子修补是一种向Ruby的核心类添加方法或更改其核心类的实践。 猴子打补丁很危险!...
Pundit - 一个帮助类引导你利用常规的Ruby类和面向对象的设计模式来构建一个简单的、健壮的、可伸缩的授权系统
像牛一样在日志中说些什么。 _____________ ------------- \ ^__^ \ (oo)\_______ (__)\ )\/\ ||----w | || || :cow: 用法 on : push name : Cowsays jobs : cow : name : Cowsays runs-on : ...
NER的BERT-BILSTM-GCN-CRF在原本BERT-BILSTM-CRF上融合GCN和词性标签等做NER任务数据格式高B-剧种B-名词腔I-剧种I-名词:OO马B-人名B-名词平I-人名I-名词所OO着O B动词扶O B动词贫O I动词小O B -名词I O-名词运行