類的設計原則-SOLID

示意圖

簡介

SOLID:php

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

詳情

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

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

  • 示例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 . '沒有開始';
    }
  }
}

弊端:若是再增長條件,和輸出修改,會加劇邏輯。
改變爲 ->segmentfault

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)

對擴展開放,對修改關閉。
與其修改別人的代碼(或者老代碼)不如先繼承,而後更改。ide

  • 示例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類的代碼->this

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)

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

接口隔離原則 (ISP:Interface Segregation Principle)

針對接口的原則,規範以下:.net

  • 接口儘可能小(細化業務)
  • 接口高內聚(減小對外交互,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. http://www.javashuo.com/article/p-aniccjdm-ey.html
  2. http://www.javashuo.com/article/p-bwsgimpq-do.html
  3. http://blog.csdn.net/jhq0113/article/details/44907029
相關文章
相關標籤/搜索