PHP設計原則梳理,參考《PHP核心技術與最佳實踐》、《敏捷開發原則、模式與實踐》,文章PHP面向對象設計的五大原則、設計模式原則SOLIDphp
class ParseText { private $content; public function decodeText(String $content) { // TODO: decode content } public function saveText() { // TODO:: save $this->content; } } /* 問題思考: 解析的文本類型會有多種-html、xml、json 保存的文本也會有多種途徑-redis、mysql、file 客戶端只須要解析文本時必須會引入saveText不須要的方法 兩個職責之間沒有強烈的依賴關係存在 任意職責需求變化都須要更改這個類 */ /* 符合SRP的設計 職責拆分 */ class Decoder { private $content; public function decodeText(String $content) { // TODO: decode content } public function getText() { return $this->content; } } class Store { public function save($content) { // TODE: save } }
軟件設計所作的許多內容就是發現職責併合理的分離職責間的關係。若是應用程序的變化老是同時影響多個職責,就不必分離職責。html
設計應用程序時,類的接口不是內聚的。不一樣的客戶端只包含集中的部分功能,但系統會強制客戶端實現模塊中全部方法,而且還要編寫一些啞方法。這樣的接口成爲胖接口或者是接口污染,這樣的接口會給系統引入一些不當的行爲,資源浪費,影響其餘客戶端程序加強了耦合性等mysql
/* * 公告接口 */ interface Employee { public function startWork(); public function endWork(); } /* * 定義特定客戶端接口 */ interface Coder { public function writeCode(); } interface Ui { public function designPage(); } class CoderClient implements Employee, Coder { public function startWork() { //TODO:: start work time } public function endWork() { //TODO:: end work time } public function writeCode() { //TODO:: start write code return 'hellow world'; } } $c = new CoderClient(); echo $c->writeCode();
胖類會致使他們的客戶端程序之間產生不正常的而且有害的耦合關係。經過把胖客戶度分解成多個特定於客戶端的接口,客戶端牢牢依賴於他們實際調用的方法,從而解除了客戶端與他們沒有調用的方法之間的依賴關係。接口隔離應作的小而少。redis
隨着軟件系統規模的不斷擴大,系統的維護和修改的複雜性不斷提升。系統一處的更改每每會影響到其餘模塊。正確的運用OCP原則能夠解決此類問題。sql
/* * 定義有固定行爲的抽象接口 */ interface Process { public function action(String $content); } /* * 繼承抽象接口,擴展不一樣的行爲 */ class WriteToCache implements Process { public function action(String $content) { return 'write content to cache: '.$content; } } class ParseText { private $content; public function decodeText($content) { $this->content = $content; } public function addAction(Process $process) { if ($process instanceof Process) { return $process->action($this->content); } } } $p = new ParseText(); $p->decodeText('content'); echo $p->addAction(new WriteToCache());
OCP核心思想就是抽象接口編程,抽象相對穩定。讓類依賴與固定的抽象,經過面向對象的繼承和多態讓類繼承抽象,複寫其方法或固有行爲,是想新的擴展方法/功能,實現擴展。編程
面向對象中大量的繼承關係十分廣泛和簡單,這種繼承規則是什麼,最佳的繼承層次的規則又是什麼,怎樣優雅的設計繼承關係,子類能正確的對基類中的某些方法進行從新,這是LSP原則所要處理的問題。json
假設一個函數a,他的參數引用一個基類b,c是b的派生類,若是將c的對象做爲b類型傳遞給a,會致使a出現錯誤的行爲,那沒c就違法了LSP原則。segmentfault
/* * 基類 */ class Computer { public function action($a, $b) { return $a+$b; } } /* * 子類複習了父類方法,改變了action 的行爲 * 違反了LSP原則 */ class Client extends Computer { public function action($a, $b) { return $a-$b; } } function run(Computer $computer, $a, $b) { return $computer->action($a, $b); } echo run((new Client()), 3, 5);
LSP是OCP得以應用的最主要的原則之一,正是由於子類性的可替換行是的基類類型在無需修改的狀況下擴展功能。設計模式
軟件開發設計中,老是傾向於建立一些高層模塊依賴底層模塊,底層模塊更改時直接影響到高層模塊,從而迫使他們改變。DIP原則描述了高層次模塊怎樣調用低層次模塊。函數
interface Arithmetic { //public function sub($a, $b); } class Client { public function computer(Arithmetic $arithmetic, $a, $b) { return $arithmetic->add($a, $b); } } class Addition implements Arithmetic { public function add($a, $b) { return $a + $b; } } $c = new Client(); echo $c->computer(new Addition(), 2, 3); /* client 高層類 依賴於Arithmetic,Addition底層實現細節類實現Arithmetic接口,達到兩者依賴於抽象接口的DIP設計原則 */
DIP原則就是每一個高層次模塊定義一個它所需服務的接口聲明,低層次模塊實現這個接口。每一個高層次類經過該抽象接口使用服務。
面向對象軟件開發中合理的遵循設計原則能夠更好的設計代碼,減小沒必要要的錯誤,提升程序的可維護性,可擴展性和穩定性。