What
就一個類(接口涯竟、結構體赡鲜、方法等等)而言,應該僅有一個引起它變化的原因庐船。
Why
軟件設計真正要做的許多內容银酬,就是發(fā)現職責并把那些職責互相分離。單一職責原則可以使類的復雜度降低筐钟,實現什么職責都有清晰明確的定義捡硅;類的可讀性提高,復雜度降低(復雜度降低肯定可讀性提高)盗棵;可讀性提高了壮韭,代碼就更容易維護;變更(需求是肯定會變的纹因,程序員都知道)引起的風險(包括測試的難度喷屋,以及需要測試的范圍)降低。
How
需求:實現拍照和播放音樂瞭恰,那先定義兩個功能接口
//具有照相的功能的接口
interface IPhotograph
{
void Photograph();
}
//具有播放音樂功能的接口
interface IPlayMusic
{
void PlayMusic();
}
不遵循單一原則的設計屯曹,播放音樂及拍照功能的改變都會引起變化
//實現照相、播放音樂的手機類
public class MobilePhone : IPhotograph, IPlayMusic
{
//拍照
public void Photograph()
{
Console.WriteLine("拍照片");
}
//播放音樂
public void PlayMusic()
{
Console.WriteLine("播放音樂");
}
}
class Program
{
static void Main(string[] args)
{
IPlayMusic musicPlayer;
IPhotograph photographer;
MobilePhone phone = new MobilePhone();
musicPlayer = phone;
photographer = phone;
//播放音樂
musicPlayer.PlayMusic();
//拍照
photographer.Photograph();
Console.ReadLine();
}
}
遵循單一原則的設計,引發(fā)改變的只有播放音樂功能的變化
//實現播放音樂功能的音樂播放器類
class MusicPlayer : IPlayMusic
{
public void PlayMusic()
{
Console.WriteLine("播放音樂");
}
}
遵循單一原則的設計恶耽,引發(fā)改變的只有攝像功能的變化
//實現照相功能的攝像機類
class Carmera : IPhotograph
{
public void Photograph()
{
Console.WriteLine("拍照片");
}
}
class Program
{
static void Main(string[] args)
{
IPlayMusic musicPlayer;
IPhotograph photographer;
//MobilePhone phone = new MobilePhone();
//musicPlayer = phone;
//photographer = phone;
musicPlayer = new MusicPlayer();
photographer = new Carmera();
//播放音樂
musicPlayer.PlayMusic();
//拍照
photographer.Photograph();
Console.ReadLine();
}
}
糟糕的設計會造成什么樣的后果呢密任?讓我們來設想一下,有一天我們的需求發(fā)生了變化(需求變化-程序員一生的敵人兼朋友)偷俭,現有擁有了一部手機浪讳,有拍照的功能以及播放音樂的功能,滿足了現有的需求涌萤,突然有一天覺得簡單的拍照功能已經不能滿足了淹遵,
現在需要能夠拍攝高清圖片的照相功能,那么怎么辦呢负溪?換手機唄透揣,恩找一個支持高清拍照功能的手機。那么好的川抡,需求又變了辐真,現在想要能播放高品質音樂的功能,但是新換的支持高清拍攝的手機的硬件不支持高品質音樂播放崖堤,好的侍咱,繼續(xù)換手機,前提是還要
支持拍攝高清照片倘感。相信現在已經能夠看出一些端倪了放坏,這兩個職責無論哪一個發(fā)生了變化,你都要去改變手機老玛,現在只有兩個職責淤年,夸張一點說,如果有十個職責呢蜡豹?那么豈不是要天天換手機麸粮,要么就不滿足需求變化。
既然我們看到了糟糕的設計镜廉,現在我們回到單一職責上弄诲,既然你的需求是拍照片和播放音樂,那么我給你一臺相機還有一臺音樂播放器娇唯,哪個功能需要改變你就換哪個齐遵,以后你要換的時候也不必去考慮其他功能,只需要關心引起你自己變化的原因塔插。如果拍照
功能發(fā)生改變梗摇,我們就去改變照相機,播放音樂功能需要改變我們就去改變音樂播放器想许。我們不需要去考慮播放高品質音樂是不是會對拍攝高清圖片的功能造成影響伶授。
我們一定要遵循單一職責原則嗎断序?在現有的需求上能做到當然可以去做,但是往往有的時候糜烹,需求不是在設計的時候發(fā)生改變违诗,而是一定程度之后,你已經有了一定的代碼量了疮蹦,可能修改的開銷很高诸迟,這個時候就仁者見仁智者見智。就如上述挚币,若是將手機類
拆分亮蒋,則影響了底層調用的實現扣典,也需要修改妆毕,弱是調用的地方太多,那么修改的地方也會很多贮尖,若是發(fā)布了笛粘,改起來也不是很方便,但是當然湿硝,也有一定的手法來做這件事情薪前,比如手機類保留,讓手機類擁有一個攝像機類對象和一個音樂播放器類對象关斜,然后播放
音樂方法則調用音樂播放器類實例的播放音樂功能示括,照相功能則調用攝像機類實例的照相功能,這樣可以在不影響原有的東西的基礎上又遵循原則痢畜。