首先了解一下什麼是程式設計模式:
程式設計模式指的是一套被反覆使用,被多數人知曉的,經過分類編目的,程式碼設計經驗的總結
其實透過漫漫的開發之路,程式設計師們逐漸的總結出了程式開發的原則,可以總結為以下六大原則
1.單一職責原則
單一職責就是一個類只負責一個功能,更加具體的說就是對一個類而言,應該是一組相關性很高的函式、資料的封裝,是高內聚低耦合的,對外界而言應該僅有一個引起它變化的原因。但是如何劃分一個類、甚至是一個函式的職責,這就需要每一個開發者自己去設計。
2.里氏替換原則
只要父類出現的地方子類就可以出現,而且替換為子類也不會產生任何的錯誤或者異常,里氏替換原則的核心是抽象。
3.依賴倒置原則
高層模組不應該依賴底層模組,都應該依賴於抽象;抽象不應該依賴於具體,具體依賴於抽象
依賴倒置原則指定了一種特定的解耦形式,使得高層次的模組不依賴與低層次模組的實現細節的目的,依賴模組被顛倒了。依賴倒置原則有以下幾個關鍵點:
1。高層模組不應該依賴於低層模組,兩者都應該依賴其抽象
2。抽象不應該依賴於細節
3。細節應該依賴於抽象
在Java語言中,抽象就是指介面或者抽象類,二者都是不能夠被直接例項化的:細節就是實現類,實現介面或者抽象類而產生的類就是細節,其特點就是可以直接被例項化,也就是可以使用關鍵字new產生一個物件。高層模組就是指呼叫端,底層模組就是指具體的實現類。依賴倒置原則在Java語言中的表現就是:模組間的依賴透過抽象產生,實現類之間不發生直接的依賴關係,其依賴關係是透過介面或者抽象類產生的。使用一句話概括就是:面向介面程式設計或者說是面向抽象程式設計。、
例子:公司是福特和本田公司的金牌合作伙伴,現要求開發一套自動駕駛系統,只要汽車上安裝該系統就可以實現無人駕駛,該系統可以在福特和本田車上使用,只要這兩個品牌的汽車使用該系統就能實現自動駕駛。
福特汽車類,包含三個方法,啟動、停止、轉彎
class FordCar
{
public void Run()
{
Console。WriteLine(“FordCar run”);
}
public void Stop()
{
Console。WriteLine(“FordCar stop”);
}
public void Turn()
{
Console。WriteLine(“FordCar turn”);
}
}
宏達汽車類,包含三個方法,啟動、停止、轉彎
class HondaCar
{
public void Run()
{
Console。WriteLine(“HondaCar run”);
}
public void Stop()
{
Console。WriteLine(“HondaCar stop”);
}
public void Turn()
{
Console。WriteLine(“HondaCar turn”);
}
}
自動駕駛系統,有三個方法啟動汽車、停止汽車、汽車轉向
class AutoSystem
{
HondaCar hondaCar = new HondaCar();
FordCar fordCar = new FordCar();
CarType type;
public AutoSystem(CarType type)
{
this。type = type;
}
public void RunCar()
{
if (type == CarType。Honda)
{
hondaCar。Run();
}
else if (type == CarType。Ford)
{
fordCar。Run();
}
}
public void StopCar()
{
if (type == CarType。Honda)
{
hondaCar。Stop();
}
else if (type == CarType。Ford)
{
fordCar。Stop();
}
}
public void TurnCar()
{
if (type == CarType。Honda)
{
hondaCar。Turn();
}
else if (type == CarType。Ford)
{
fordCar。Turn();
}
}
}
目前來看,是滿足需求的,但是隨著發展業務也在發展,現在如果發展了夥伴,需要對其他品牌的汽車新增自動駕駛系統,比如紅旗、奇瑞等品牌,那麼如果沿用以前的方式,就需要去修改AutoSystem了,先增加兩個新的品牌汽車的物件,然後在啟動汽車、停止汽車、汽車轉向中進行修改增加分支語句對不同的品牌來進行判斷然後加上各種操作,這樣就違背的OCP,而且複雜的分支語句也會容易造成錯誤,如果以後再繼續擴充套件其他的品牌的話,那麼這樣的程式肯定是不易於維護的,程式的健壯性是較差的,大大的增加了開發的成本。那麼敏感的同學已經看出來,既然不同的汽車品牌之間都擁有相同的行為,那麼為什麼不定義一個介面呢?現在我們先來定義一個介面,然後將各個品牌的汽車實現這個介面實現,那麼在AutoSystem中我們就可以針對定義的介面操作了。
interface ICar
{
void Run();
void Stop();
void Turn();
}
自動駕駛系統也就是高層模組現在針對的是這個抽象的介面,無論什麼汽車,只要實現了ICar介面,就能進行相關的操作。
class AutoSystem
{
ICar car;
public AutoSystem(ICar car)
{
this。car = car;
}
public void RunCar()
{
car。Run();
}
public void StopCar()
{
car。Stop();
}
public void TurnCar()
{
car。Turn();
}
}
福特汽車類也就是底層模組,實現了ICar介面,現在依賴的是抽象的介面
class FordCar : ICar
{
public void Run()
{
Console。WriteLine(“FordCar run”);
}
public void Stop()
{
Console。WriteLine(“FordCar stop”);
}
public void Turn()
{
Console。WriteLine(“FordCar turn”);
}
}
宏達汽車類也就是底層模組,實現了ICar介面,現在依賴的是抽象的介面
class HondaCar : ICar
{
public void Run()
{
Console。WriteLine(“HondaCar run”);
}
public void Stop()
{
Console。WriteLine(“HondaCar stop”);
}
public void Turn()
{
Console。WriteLine(“HondaCar turn”);
}
}
當高層模組依賴底層的時候,那麼高層的複用性就較差,就如上例所說的增加汽車品牌種類。如果高層與底層都是依賴於抽象的話,那麼高層複用性就較好,因為透過繼承象出來的介面實現多型,那麼複用的地方就多了,這樣的設計無疑是較為穩定的。
4.介面隔離原則
介面隔離原則的定義是:客戶端不應該依賴於他不需要的介面。另一種定義是:類之間的依賴關係應該建立在最小的介面上。介面隔離原則將非常龐大,臃腫的介面拆分成更小的和更具體的介面,這樣客戶端將會值需要知道它們感興趣的方法。介面隔離原則的目的是系統解開耦合,從而容易重構、更改和部署。
5.迪米特法則
一個物件應該對其他物件有最少的瞭解,通俗的講,一個類應該對自己需要耦合或呼叫的類知道的最少,類的內部如何實現與呼叫者或者依賴者沒有關係,呼叫者或者依賴者只需要知道他需要的方法即可,其他的一概不管。類與類之間的關係越密切,耦合度越大,當一個類發生改變時,對另一個類的影響也越大。
6.開閉原則
軟體中的物件(類、模組、函式等)應該對於擴充套件是開放的,但是對於修改是封閉的。在軟體的生命週期內,因為變化、升級和維護等原因需要對軟體的原有程式碼進行修改時,可能會將錯誤的程式碼引入,從而破壞原有系統。因此當軟體需求發生變化時,我們應該儘量透過擴充套件的方式 來實現變化,而不是透過修改已有的程式碼。