面向对象设计中的单一职责原则强调的是不要给一个类赋予太多职责的重要性。
“开发一个满足规范的软件就跟走在水面上一样,除非是结了冰才行(或者需求冻结不变了)”——Edward V. Berard。
我们都清楚,软件开发的规格要求并不是一成不变的。你开发的软件随时都可能会发生变化。今天这个软件的确是在履行它的职责。但是这样就够了吗?你设计的软件能够拥抱变化吗(我觉得小微的人应该都懂)?
好的面向对象的设计才是关键。
好吧。我知道什么是面向对象设计,并且我也的确在项目中用到了它们。
如果你是这么想的,那么请你问自己几个问题。
1. 你的代码是可重用的吗?
2. 如果需求改变了,是否很容易能修改完成?
3. 能否在不修改代码的前提下进行扩展?
别担心。并不是你一个人会面临这些问题。我们会一块学习如何能让我们的软件在面对改变时能更具灵活性。
这个问题已经有不少人研究过了,他们得出的结论是OOD原则。
下面就是我们需要掌握的5项原则。
S = 单一职责原则
O = 开闭原则
L = 里氏替换原则
I = 接口分离原则
D = 依赖反转原则
单一职责原则:
类有且应当只有一个改变的理由。
我们来用一个现实生活中的例子来说明下这点。
[img]http://t2.qpic.cn/mblogpic/3237533ea2d9fb089fbc/2000[/img]
想像一下你在一家印度的软件公司上班(阿三?)。你会在业余时间写点东西,编辑报纸或者完成些例行任务(写代码)。一般来说,你的生活中会有多个职责/兴趣。
当公司出现了些不好的问题,你的老板挑你的毛病,你就会变得很心烦。通常来说,福无双至,祸不单行,别的事也会一团糟。
[b]最著名的一个例子:[/b]
[b]codeProject.com[/b]
如果只是因为一个设备里能够实现多个特性你就会这么做吗?这样很难维护和管理。
因此这个原则告诉你的是,如果你有一个类承担了多项职责,那么你应该重新考虑下这个类,将它进行拆分。完全正确!通常我们会在函数或者方法上应用这个原则。
考虑下面这段代码:
注意一下你会发现"Student"这个类有多个职责。它会处理所有的CRUD操作,同时还会为学生打印成绩单。问题就在于类中的方法是互相依赖的。
只要有一个方法变了,别的方法可能就得改变,因为它们都住在同一个家里,爸妈都是同一个。
解决方案:
类层面的单一职责:
我们将这个类拆分开来,这样每个类就都满足单一职责了。
类1:Student
类2:StudentDB
类3:StudentReport
方法层面的单一职责:
在方法层面的话更应该严格遵循单一职责原则,这样才能避免代码变得混乱不堪。
比如说:
我们可以看到insertStudent的职责是将学生数据插入到数据库中,而不是去创建数据库连接,或者说校验对象。我们可以将别的功能委托给其它的函数来完成。这样的话万一出现问题我们也方便进行调试。
原创文章转载请注明出处:[url=http://it.deepinmind.com/%E5%85%B6%E5%AE%83/2014/06/23/single-responsibility-principle-in-oop.html]http://it.deepinmind.com[/url]
[url=http://www.codezag.com/single-responsibility-principle-in-oop]英文原文链接[/url]
“开发一个满足规范的软件就跟走在水面上一样,除非是结了冰才行(或者需求冻结不变了)”——Edward V. Berard。
我们都清楚,软件开发的规格要求并不是一成不变的。你开发的软件随时都可能会发生变化。今天这个软件的确是在履行它的职责。但是这样就够了吗?你设计的软件能够拥抱变化吗(我觉得小微的人应该都懂)?
好的面向对象的设计才是关键。
好吧。我知道什么是面向对象设计,并且我也的确在项目中用到了它们。
如果你是这么想的,那么请你问自己几个问题。
1. 你的代码是可重用的吗?
2. 如果需求改变了,是否很容易能修改完成?
3. 能否在不修改代码的前提下进行扩展?
别担心。并不是你一个人会面临这些问题。我们会一块学习如何能让我们的软件在面对改变时能更具灵活性。
这个问题已经有不少人研究过了,他们得出的结论是OOD原则。
下面就是我们需要掌握的5项原则。
S = 单一职责原则
O = 开闭原则
L = 里氏替换原则
I = 接口分离原则
D = 依赖反转原则
单一职责原则:
类有且应当只有一个改变的理由。
我们来用一个现实生活中的例子来说明下这点。
[img]http://t2.qpic.cn/mblogpic/3237533ea2d9fb089fbc/2000[/img]
想像一下你在一家印度的软件公司上班(阿三?)。你会在业余时间写点东西,编辑报纸或者完成些例行任务(写代码)。一般来说,你的生活中会有多个职责/兴趣。
当公司出现了些不好的问题,你的老板挑你的毛病,你就会变得很心烦。通常来说,福无双至,祸不单行,别的事也会一团糟。
[b]最著名的一个例子:[/b]
[b]codeProject.com[/b]
如果只是因为一个设备里能够实现多个特性你就会这么做吗?这样很难维护和管理。
因此这个原则告诉你的是,如果你有一个类承担了多项职责,那么你应该重新考虑下这个类,将它进行拆分。完全正确!通常我们会在函数或者方法上应用这个原则。
考虑下面这段代码:
<?php
class Student {
public $studentName = '';
public $studentRegNo = '';
// Responsibility 1
function insertStudent($aStudent) {
// Logic for inserting a student to database.
}
function selectStudent($aStudent){
//logic
}
function deleteStudent($aStudent){
//logic
}
// Responsibility 2
function generateMarkSheet($aStudent) {
//logic for generating marks.
}
}
?>
注意一下你会发现"Student"这个类有多个职责。它会处理所有的CRUD操作,同时还会为学生打印成绩单。问题就在于类中的方法是互相依赖的。
只要有一个方法变了,别的方法可能就得改变,因为它们都住在同一个家里,爸妈都是同一个。
解决方案:
类层面的单一职责:
我们将这个类拆分开来,这样每个类就都满足单一职责了。
类1:Student
类2:StudentDB
类3:StudentReport
class Student {
private $studentName = '';
private $studentRegNo = '';
public function getstudentName()
{
return $this->studentName;
}
public function setstudentName($studentName)
{
$this->studentName = $studentName;
}
}
class StudentDB {
function selectStudent($aStudent){
//logic
}
function deleteStudent($aStudent){
//logic
}
}
class StudentReport {
function generateMarkSheet($aStudent) {
//logic for generating marks.
}
}
}
方法层面的单一职责:
在方法层面的话更应该严格遵循单一职责原则,这样才能避免代码变得混乱不堪。
比如说:
public function insertStudent($aStudent){
/*
1. establish mysql connection.
2. validate aStudent object.
3. insert data to database.
}
我们可以看到insertStudent的职责是将学生数据插入到数据库中,而不是去创建数据库连接,或者说校验对象。我们可以将别的功能委托给其它的函数来完成。这样的话万一出现问题我们也方便进行调试。
原创文章转载请注明出处:[url=http://it.deepinmind.com/%E5%85%B6%E5%AE%83/2014/06/23/single-responsibility-principle-in-oop.html]http://it.deepinmind.com[/url]
[url=http://www.codezag.com/single-responsibility-principle-in-oop]英文原文链接[/url]