欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

PHP面向?qū)ο笪宕笤瓌t之單一職責(zé)原則(SRP)詳解

 更新時(shí)間:2018年04月04日 12:13:27   作者:雪山飛豬  
這篇文章主要介紹了PHP面向?qū)ο笪宕笤瓌t之單一職責(zé)原則(SRP),結(jié)合實(shí)例形式詳細(xì)分析了單一職責(zé)原則(SRP)的概念、原理、定于與使用方法,需要的朋友可以參考下

本文實(shí)例講述了PHP面向?qū)ο笪宕笤瓌t之單一職責(zé)原則(SRP)。分享給大家供大家參考,具體如下:

單一職責(zé)原則(Single Pesponsibility Principle, SRP)

單一職責(zé)有兩個(gè)含義: 一個(gè)是避免相同的職責(zé)分散到不同的類(lèi)中, 別一個(gè)是避免一個(gè)類(lèi)承擔(dān)太多職責(zé)

為什么要遵守SRP呢?

(1)可以減少類(lèi)之間的耦合

如果減少類(lèi)之間的耦合,當(dāng)需求變化時(shí),只修改一個(gè)類(lèi),從而也就隔離了變化;如果一個(gè)類(lèi)有多個(gè)不同職責(zé),它們耦合在一起,當(dāng)一個(gè)職責(zé)發(fā)生變化時(shí),可能會(huì)影響到其他職責(zé)。

(2)提高類(lèi)的復(fù)用性

修改電腦比修理電視機(jī)簡(jiǎn)單多了。主要原因就在于電視機(jī)各個(gè)部件之間的耦合性太高,而電腦則不同,電腦的內(nèi)存、硬盤(pán)、聲卡、網(wǎng)卡、鍵盤(pán)燈等部件都可以很容易地單獨(dú)拆卸和組裝。某個(gè)部件壞了,換上新的即可。上面的例子就體現(xiàn)了單一職責(zé)的優(yōu)勢(shì)。由于使用了單一職責(zé),使得‘組件'可以方便地‘拆卸'和‘組裝'。

不遵守SRP會(huì)影響對(duì)類(lèi)的復(fù)用性。當(dāng)只需要用該類(lèi)的某一個(gè)職責(zé)時(shí),由于它和其他的職責(zé)耦合在一起,也就很難分離出。

遵守SRP在實(shí)際代碼開(kāi)發(fā)中有沒(méi)有什么應(yīng)用?有的。以數(shù)據(jù)持久層為例,所謂的數(shù)據(jù)持久層主要指的是數(shù)據(jù)庫(kù)操作,當(dāng)然,還包括緩存管理等。這時(shí)就需要數(shù)據(jù)持久層支持多種數(shù)據(jù)庫(kù)。應(yīng)該怎么做?定義多個(gè)數(shù)據(jù)庫(kù)操作類(lèi)?想法已經(jīng)很接近了,再進(jìn)一步,就是使用工廠模式。

工廠模式(Faction)允許你在代碼執(zhí)行時(shí)實(shí)例化對(duì)象。它之所以被稱(chēng)為工廠模式是因?yàn)樗?fù)責(zé)‘生產(chǎn)對(duì)象'。以數(shù)據(jù)庫(kù)為例,工廠需要的就是根據(jù)不同的參數(shù),生成不同的實(shí)例化對(duì)象。最簡(jiǎn)單的工廠就是根據(jù)傳入的類(lèi)型名實(shí)例化對(duì)象,如傳入MySQL,就調(diào)用MySQL類(lèi)并實(shí)例化,如果是SQLite,則調(diào)用 SQLite的類(lèi)并實(shí)例化,甚至還可以處理TXT、Execl等‘類(lèi)數(shù)據(jù)庫(kù)'。

工廠類(lèi)也就是這樣的一個(gè)類(lèi),它只負(fù)責(zé)生產(chǎn)對(duì)象,而不負(fù)責(zé)對(duì)象的具體內(nèi)容。

以下是示例

定義一個(gè)適配器的接口

interface Db_Adpater
{
  /**
   * 數(shù)據(jù)庫(kù)連接
   * @param $config 數(shù)據(jù)庫(kù)配置
   * @return mixed resource
   */
  public function connect($config);
  /**
   * 執(zhí)行數(shù)據(jù)庫(kù)查詢(xún)
   * @param $query 數(shù)據(jù)庫(kù)查詢(xún)的SQL字符串
   * @param $handle 連接對(duì)象
   * @return mixed
   */
  public function query($query,$handle);
}

定義一個(gè)實(shí)現(xiàn)了DB_Adpater接口的MySQL數(shù)據(jù)庫(kù)操作類(lèi)

class Db_Adapter_Mysql implements Db_Adpater
{
  private $_dbLink;  //數(shù)據(jù)庫(kù)連接字符串標(biāo)識(shí)
  /**
   * 數(shù)據(jù)庫(kù)連接函數(shù)
   * @param $config 數(shù)據(jù)庫(kù)配置
   * @return resource
   * @throws Db_Exception
   */
  public function connect($config)
  {
    if($this->_dbLink = @mysql_connect($config->host . (empty($config->port) ? '' : ':' . $config->prot) ,$config->user, $config->password, true))
    {
      if(@mysql_select_db($config->database, $this->_dbLink))
      {
        if($config->charset)
        {
          mysql_query("SET NAME '{$config->charset}'", $this->_dbLink);
        }
        return $this->_dbLink;
      }
    }
    throw new Db_Exception(@mysql_error($this->_dbLink));
  }
  /**
   * 執(zhí)行數(shù)據(jù)庫(kù)查詢(xún)
   * @param $query 數(shù)據(jù)庫(kù)查詢(xún)SQL字符串
   * @param $handle 連接對(duì)象
   * @return resource
   */
  public function query($query,$handle)
  {
    if($resource = @mysql_query($query,$handle))
      return $resource;
  }
}

定義一個(gè)實(shí)現(xiàn)了DB_Adpater接口的SQLite數(shù)據(jù)庫(kù)操作類(lèi)

class Db_Adapter_sqlite implements Db_Adpater
{
  private $_dbLink;  //數(shù)據(jù)庫(kù)連接字符串標(biāo)識(shí)
  public function connect($config)
  {
    if($this->_dbLink = sqlite_open($config->file, 0666, $error))
    {
      return $this->_dbLink;
    }
    throw new Db_Exception($error);
  }
  public function query($query, $handle)
  {
    if($resource = @sqlite_query($query,$handle))
    {
      return $resource;
    }
  }
}

現(xiàn)在如果需要一個(gè)數(shù)據(jù)庫(kù)操作的方法怎么做,只需定義一個(gè)工廠類(lèi),根據(jù)傳入不同的生成需要的類(lèi)即可

class sqlFactory
{
  public static function factory($type)
  {
    if(include_once 'Drivers/' . $type . '.php')
    {
      $classname = 'Db_Adapter_'.$type;
      return new $classname;
    }
    else
      throw new Exception('Driver not found');
  }
}

調(diào)用時(shí),就可以這么寫(xiě)

$db = sqlFactory::factory('MySQL');
$db = sqlFactory::factory('SQLite');

我們把創(chuàng)建數(shù)據(jù)庫(kù)連接這塊程序單獨(dú)拿出來(lái),程序中的CURD就不用關(guān)心什么數(shù)據(jù)庫(kù)了,只要按照規(guī)范使用對(duì)應(yīng)的方法即可。

工廠方法讓具體的對(duì)象解脫出來(lái),使其不再依賴(lài)具體的類(lèi),而是抽象。

設(shè)計(jì)模式里面的命令模式也是SRP的體現(xiàn),命令模式分離“命令的請(qǐng)求者”和“命令的實(shí)現(xiàn)者”方面的職責(zé)。舉一個(gè)很好理解的例子,就是你去餐館訂餐吃飯,餐館存在顧客、服務(wù)員、廚師三個(gè)角色。作為顧客,你要列出菜單,傳給服務(wù)員,由服務(wù)員通知廚師去實(shí)現(xiàn)。作為服務(wù)員,只需要調(diào)用準(zhǔn)備飯菜這個(gè)方法(對(duì)廚師喊“該炒菜了”),廚師聽(tīng)到要炒菜的請(qǐng)求,就立即去做飯。在這里,命令的請(qǐng)求和實(shí)現(xiàn)就完成了解耦。

模擬這個(gè)過(guò)程,首先定義廚師角色,廚師進(jìn)行實(shí)際做飯、燒湯的工作。

以下是示例

/**
 * 廚師類(lèi),命令接受者與執(zhí)行者
 * Class cook
 */
class cook
{
  public function meal()
  {
    echo '番茄炒雞蛋',PHP_EOL;
  }
  public function drink()
  {
    echo '紫菜蛋花湯',PHP_EOL;
  }
  public function ok()
  {
    echo '完畢',PHP_EOL;
  }
}
//然后是命令接口
interface Command
{
  public function execute();
}

輪到服務(wù)員出場(chǎng),服務(wù)員是命令的傳送者,通常你到飯館吃飯都是叫服務(wù)員吧,不能直接叫廚師,一般都是叫“服務(wù)員,給我來(lái)盤(pán)番茄炒西紅柿”。所以,服務(wù)員是顧客和廚師之間的命令溝通都。

class MealCommand implements Command
{
  private $cook;
  //綁定命令接受者
  public function __construct(cook $cook)
  {
    $this->cook = $cook;
  }
  public function execute()
  {
    $this->cook->meal();//把消息傳給廚師,讓廚師做飯,下同
  }
}
class DrinkCommand implements Command
{
  private $cook;
  //綁定命令接受者
  public function __construct(cook $cook)
  {
    $this->cook = $cook;
  }
  public function execute()
  {
    $this->cook->drink();
  }
}

現(xiàn)在顧客可以按照菜單叫服務(wù)員了

class cookControl
{
  private $mealcommand;
  private $drinkcommand;
  //將命令發(fā)送者綁定以命令接收器上面來(lái)
  public function addCommand(Command $mealcommand, Command $drinkcommand)
  {
    $this->mealcommand = $mealcommand;
    $this->drinkcommand = $drinkcommand;
  }
  public function callmeal()
  {
    $this->mealcommand->execute();
  }
  public function calldrink()
  {
    $this->drinkcommand->execute();
  }
}

好了,現(xiàn)在完成整個(gè)過(guò)程

$control = new cookControl;
$cook = new cook;
$mealcommand = new MealCommand($cook);
$drinkcommand = new DrinkCommand($cook);
$control->addCommand($mealcommand,$drinkcommand);
$control->callmeal();
$control->calldrink();

從上面的例子可以看出,原來(lái)設(shè)計(jì)模式并非純理論的東西,而是來(lái)源于實(shí)際生活,就連普通的餐館老板都懂設(shè)計(jì)模式這門(mén)看似高深的學(xué)問(wèn)。其實(shí),在經(jīng)濟(jì)和管理活動(dòng)中對(duì)流程的優(yōu)化就是對(duì)各種設(shè)計(jì)模式的摸索和實(shí)踐。所以,設(shè)計(jì)模式并非計(jì)算機(jī)編程中的專(zhuān)利。事實(shí)上,設(shè)計(jì)模式的起源并不是計(jì)算機(jī),而是源于建筑學(xué)。

在設(shè)計(jì)模式方面,不僅以上這兩種體現(xiàn)了SRP,還有別的(比如代理模式)也體現(xiàn)了SRP。SRP不只是對(duì)類(lèi)設(shè)計(jì)有意義,對(duì)以模塊、子系統(tǒng)為單位的系統(tǒng)架構(gòu)設(shè)計(jì)同樣有意義。

模塊、子系統(tǒng)也應(yīng)該僅有一個(gè)引起它變化的原因,如MVC所倡導(dǎo)的各個(gè)層之間的相互分離就是SRP在系統(tǒng)總體設(shè)計(jì)中的應(yīng)用。

SRP是最簡(jiǎn)單的原則之一,也是最難做好的原則之一。我們會(huì)很自然地將職責(zé)連接在一起。找到并且分離這些職責(zé)是軟件設(shè)計(jì)需要達(dá)到的目的

一些簡(jiǎn)單的應(yīng)用遵循的做法如下:

根據(jù)業(yè)務(wù)流程,把業(yè)務(wù)對(duì)象提煉出來(lái)。如果業(yè)務(wù)的流程的鏈路太復(fù)雜,就把這個(gè)業(yè)務(wù)對(duì)象分離為多個(gè)單一業(yè)務(wù)對(duì)象。當(dāng)業(yè)務(wù)鏈標(biāo)準(zhǔn)化后,對(duì)業(yè)務(wù)對(duì)象的內(nèi)部情況做進(jìn)一步處理,把第一次標(biāo)準(zhǔn)化視為最高層抽象,第二次視為次高層抽象,以此類(lèi)推,直到“恰如其分”的設(shè)計(jì)層次

職責(zé)的分類(lèi)需要注意。有業(yè)務(wù)職責(zé),還要有脫離業(yè)務(wù)的抽象職責(zé),從認(rèn)識(shí)業(yè)務(wù)到抽象算法是一個(gè)層層遞進(jìn)的過(guò)程。就好比命令模式中的顧客,服務(wù)員和廚師的職責(zé),作為老板(即設(shè)計(jì)師)的你需要規(guī)劃好各自的職責(zé)范圍,即要防止越俎代庖,也要防止互相推諉。

更多關(guān)于PHP相關(guān)內(nèi)容感興趣的讀者可查看本站專(zhuān)題:《php面向?qū)ο蟪绦蛟O(shè)計(jì)入門(mén)教程》、《PHP數(shù)組(Array)操作技巧大全》、《PHP基本語(yǔ)法入門(mén)教程》、《PHP運(yùn)算與運(yùn)算符用法總結(jié)》、《php字符串(string)用法總結(jié)》、《php+mysql數(shù)據(jù)庫(kù)操作入門(mén)教程》及《php常見(jiàn)數(shù)據(jù)庫(kù)操作技巧匯總

希望本文所述對(duì)大家PHP程序設(shè)計(jì)有所幫助。

相關(guān)文章

  • 深入Memcache的Session數(shù)據(jù)的多服務(wù)器共享詳解

    深入Memcache的Session數(shù)據(jù)的多服務(wù)器共享詳解

    本篇文章是對(duì)Memcache的Session數(shù)據(jù)的多服務(wù)器共享進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-06-06
  • php模板函數(shù) 正則實(shí)現(xiàn)代碼

    php模板函數(shù) 正則實(shí)現(xiàn)代碼

    有些空閑,就弄了下template函數(shù),比較粗糙。主要是利用正則表達(dá)式,把模板文件(html文件)轉(zhuǎn)換成php文件,從而實(shí)現(xiàn)前后臺(tái)分離,即是所謂的mvc思想了
    2012-10-10
  • php完全過(guò)濾HTML,JS,CSS等標(biāo)簽

    php完全過(guò)濾HTML,JS,CSS等標(biāo)簽

    全是正則過(guò)濾HTML標(biāo)簽,但是今天自己拿來(lái)用都不好用了.原因??就是標(biāo)簽轉(zhuǎn)義了.
    2009-01-01
  • php通過(guò)sort()函數(shù)給數(shù)組排序的方法

    php通過(guò)sort()函數(shù)給數(shù)組排序的方法

    這篇文章主要介紹了php通過(guò)sort()函數(shù)給數(shù)組排序的方法,實(shí)例分析了php中sort()函數(shù)的功能及相關(guān)使用技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2015-03-03
  • PHP遍歷目錄文件的常用方法小結(jié)

    PHP遍歷目錄文件的常用方法小結(jié)

    這篇文章主要介紹了PHP遍歷目錄文件的常用方法,結(jié)合實(shí)例形式總結(jié)分析了php針對(duì)文件與目錄的常用遍歷技巧與運(yùn)行效率,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2017-02-02
  • 解析PHP中VC6 X86和VC9 X86的區(qū)別及 Non Thread Safe的意思

    解析PHP中VC6 X86和VC9 X86的區(qū)別及 Non Thread Safe的意思

    本篇文章是對(duì)PHP中VC6 X86和VC9 X86的區(qū)別及 Non Thread Safe的意思進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-06-06
  • php連接微軟MSSQL(sql server)完全攻略

    php連接微軟MSSQL(sql server)完全攻略

    在研究ezSQL的時(shí)候就看到了mssql_connect()等一些php提供的連接MSSQL的函數(shù),本以為php這個(gè)開(kāi)源的風(fēng)靡世界的編程語(yǔ)言對(duì)連接微軟的數(shù)據(jù)應(yīng)該是不在話(huà)下的,但是到真正執(zhí)行的時(shí)候,才發(fā)現(xiàn)困難多多
    2016-11-11
  • php獲取用戶(hù)瀏覽器版本的方法

    php獲取用戶(hù)瀏覽器版本的方法

    這篇文章主要介紹了php獲取用戶(hù)瀏覽器版本的方法,可使用$_SERVER['HTTP_USER_AGENT']獲取用戶(hù)信息,是非常實(shí)用的技巧,需要的朋友可以參考下
    2015-01-01
  • PHP API接口必備之輸出json格式數(shù)據(jù)示例代碼

    PHP API接口必備之輸出json格式數(shù)據(jù)示例代碼

    這篇文章主要給大家介紹了關(guān)于PHP API接口必備之輸出json格式數(shù)據(jù)的相關(guān)資料文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起看看吧。
    2017-06-06
  • 使用PHP求兩個(gè)文件的相對(duì)路徑

    使用PHP求兩個(gè)文件的相對(duì)路徑

    本篇文章是對(duì)使用PHP求兩個(gè)文件的相對(duì)路徑進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-06-06

最新評(píng)論