類的設計原則

簡介

SOLID:

  • S: 單一職責原則 (SRP)
  • O: 開閉原則 (OCP)
  • L: 里氏替換原則 (LSP)
  • I: 介面隔離原則 (ISP)
  • D: 依賴反轉原則 (DIP)
  • 迪米特法則

詳情

單一職責原則(SRP:Single responsibility principle)

解耦和增強內聚性(高內聚,低耦合),一個類和方法的只負責一個職責

  • 示例1:一個類中一個方法職責混亂。

class Activity{ public function getActivity() { if ($this->startDate < time() && $this->endDate > time()) { return 活動: . $this->name . 已經在 . date(Y-m-d H:i:s, $this->startDate) . 開始; } else { return 活動: . $this->name . 沒有開始; } }}

弊端:如果再增加條件,和輸出修改,會加重邏輯。

改變為 ->

class Activity{ public function getActivity() { return $this->isStart ? $this->getStartWord() : $this->getEndWord(); } public function isStart() { return $this->startDate < time() && $this->endDate > time(); } public function getStartWord() { return 活動: . $this->name . 已經在 . date(Y-m-d H:i:s, $this->startDate) . 開始; } public function getNotStartWord() { return 活動: . $this->name . 沒有開始; }}

  • 示例2:類的職責混亂

class Activity{ public function __construct(Activity $activity) { $this->activity = $activity; } public function draw() { if ($this->isStart()) { return $this->draw(); } throw Exception(沒有開始); }}

弊端:類的職責不清。抽獎和活動不應該屬於同一個類

更改為->

class Activity{ public function __construct(Activity $activity) { $this->activity = $activity; $this->config = 38_festival; } public function draw() { if ($this->isStart()) { return $this->initDrawManage->draw(); } throw Exception(沒有開始); } public function initDrawManage() { !isset($this->drawManage) && $this->drawManage = new DrawManage($this->config) return $this->drawManage }}class DrawManage{ public function __construct($config) { $this->config = $config } public function draw() { ... }}

開閉原則(OCP:Open/Closed Principle)

對擴展開放,對修改關閉。

與其修改別人的代碼(或者老代碼)不如先繼承,然後更改。

* 示例1:新增一個學生,應當採用繼承的方式來做,而不是修改原有的代碼

interface UserInterface{ public function getUserIdentify();}class User implements UserInterface{ private $identify = 先生/女士; public function getUserIdentify { return $this->name . $this->identify; }}

改為->

interface UserInterface{ public function getUserIdentify();}class User implements UserInterface{ private $identify = 先生/女士; public function getUserIdentify { return $this->name . $this->identify; }}class Student extend User{ private $identify = 學生; }

  • 示例2:調整結構。

    增加新的角色和工種時

interface UserInterface{ public function getUserIdentify();}class User implements UserInterface{ private $identify = young; public function getUserIdentify() { return $this->identify; }}class Student extend User{ private $identify = student; }class Work{ private $identify public function __construct(UserInterface $identify) { $this->identify = $identify; } public function getWorking() { return $this->identify->getIdentify() == student ? $this->study() : $this->working(); } public function study() { return 學習; } public function wordking() { return 工作; }}

弊端:修改代碼~~

更改Work類的代碼->

interface UserInterface{ public function getUserIdentify(); public function doing();}class User implements UserInterface{ private $identify = young; public function getUserIdentify() { return $this->identify; } public function doing() { return working; }}class Student extend User{ private $identify = student; public function doing() { return study; }}class Work{ private $identify public function __construct(UserInterface $identify) { $this->identify = $identify; } public function getWorking() { return $this->identify->doing(); }}

里氏替換原則(LSP:Liskov Substitution Principle)

父類出現的地方子類就可以出現,且替換成子類也不會出現任何錯誤或者異常。

介面隔離原則 (ISP:Interface Segregation Principle)

針對介面的原則,規範如下:

* 介面盡量小(細化業務)

* 介面高內聚(減少對外交互,public方法少)

* 定製服務(應單獨為一個個體服務)

* 有限設計(和第一個規範相輔相成)

示例:

interface User{ public function working(); public function studing();}class Student implements User{ public function working() { // 學生不工作(假設) return null; } ...}class Worker implements User{ public fucntion studing { // 不學習(假設) return null; }}

可以修改->

interface StudentInterface{ public function studing();}interface WorkerInterface{ public function working();}class Student implements StudentInterface{ ...}class Worker implements WorkerInterface{ ...}

依賴反轉原則 (DIP:Dependency Inversion Principle)

高層模塊不應該依賴低層模塊,二者都應該依賴其抽象;抽象不應該依賴細節;細節應該依賴抽象。

這個原則剛好本文的第二小節開閉原則示例1貌似就違反了,但是要看具體業務的,如果是A是父類,B是子類,具有一定的聯繫,無法分割就不遵循。如果A類和B類是平級關係,繼承只是共用一些方法,那就有必要讓兩者都依賴抽象,便於該改動。

迪米特法則(Law of Demeter)

迪米特法則也叫做最少知識原則(Least Knowledge Principle,LKP),即一個對象應該對其他對象有最少的了解。不關心其他對象內部如何處理。

綜述

根據實際情況使用不同的原則,可以使得程序降低耦合和冗餘代碼,優化程序。根據這些規則,會有一系列的設計模式,在實際使用時沒必要強行套用設計模式,需要根據業務實際劃分合理即可。長城不是一天就能修好的~~~

參考

  1. cnblogs.com/HouJiao/p/5
  2. segmentfault.com/a/1190
  3. blog.csdn.net/jhq0113/a

推薦閱讀:

TAG:設計原則 | 設計模式 |