欧美三区_成人在线免费观看视频_欧美极品少妇xxxxⅹ免费视频_a级毛片免费播放_鲁一鲁中文字幕久久_亚洲一级特黄

五種常見(jiàn)的 PHP 設(shè)計(jì)模式

系統(tǒng) 2866 0

關(guān)聯(lián): PHP實(shí)現(xiàn)單件模式的幾種方式

?

設(shè)計(jì)模式 一書(shū)將設(shè)計(jì)模式引入軟件社區(qū),該書(shū)的作者是 Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides Design(俗稱(chēng) “四人幫”)。所介紹的設(shè)計(jì)模式背后的核心概念非常簡(jiǎn)單。經(jīng)過(guò)多年的軟件開(kāi)發(fā)實(shí)踐,Gamma 等人發(fā)現(xiàn)了某些具有固定設(shè)計(jì)的模式,就像建筑師設(shè)計(jì)房子和建筑物一樣,可以為浴室的位置或廚房的構(gòu)造方式開(kāi)發(fā)模板。使用這些模板或者說(shuō)設(shè)計(jì)模式 意味著可以更快地設(shè)計(jì)更好的建筑物。同樣的概念也適用于軟件。

設(shè)計(jì)模式不僅代表著更快開(kāi)發(fā)健壯軟件的有用方法,而且還提供了以友好的術(shù)語(yǔ)封裝大型理念的方法。例如,您可以說(shuō)您正在編寫(xiě)一個(gè)提供松散耦合的消息傳遞系統(tǒng),也可以說(shuō)你正在編寫(xiě)名稱(chēng)為觀察者 的模式。

用較小的示例展示模式的價(jià)值是非常困難的。這往往有些大材小用的意味,因?yàn)槟J綄?shí)際上是在大型代碼庫(kù)中發(fā)揮作用的。本文不展示大型應(yīng)用程序,所以您需要思索的是在您自己的大型應(yīng)用程序中應(yīng)用示例原理的方法 —— 而不是本文演示的代碼本身。這不是說(shuō)您不應(yīng)該在小應(yīng)用程序中使用模式。很多良好的應(yīng)用程序都以小應(yīng)用程序?yàn)槠瘘c(diǎn),逐漸發(fā)展到大型應(yīng)用程序,所以沒(méi)有理由不以此類(lèi)扎實(shí)的編碼實(shí)踐為基礎(chǔ)。

既然您已經(jīng)了解了設(shè)計(jì)模式以及它們的有用之處,現(xiàn)在我們來(lái)看看 PHP V5 的五種常用模式。

1. 工廠(chǎng)模式

最初在設(shè)計(jì)模式 一書(shū)中,許多設(shè)計(jì)模式都鼓勵(lì)使用松散耦合。要理解這個(gè)概念,讓我們最好談一下許多開(kāi)發(fā)人員從事大型系統(tǒng)的艱苦歷程。在更改一個(gè)代碼片段時(shí),就會(huì)發(fā)生問(wèn)題,系統(tǒng)其他部分 —— 您曾認(rèn)為完全不相關(guān)的部分中也有可能出現(xiàn)級(jí)聯(lián)破壞。

該問(wèn)題在于緊密耦合 。系統(tǒng)某個(gè)部分中的函數(shù)和類(lèi)嚴(yán)重依賴(lài)于系統(tǒng)的其他部分中函數(shù)和類(lèi)的行為和結(jié)構(gòu)。您需要一組模式,使這些類(lèi)能夠相互通信,但不希望將它們緊密綁定在一起,以避免出現(xiàn)聯(lián)鎖。

在大型系統(tǒng)中,許多代碼依賴(lài)于少數(shù)幾個(gè)關(guān)鍵類(lèi)。需要更改這些類(lèi)時(shí),可能會(huì)出現(xiàn)困難。例如,假設(shè)您有一個(gè)從文件讀取的 User 類(lèi)。您希望將其更改為從數(shù)據(jù)庫(kù)讀取的其他類(lèi),但是,所有的代碼都引用從文件讀取的原始類(lèi)。這時(shí)候,使用工廠(chǎng)模式會(huì)很方便。

工廠(chǎng)模式 是一種類(lèi),它具有為您創(chuàng)建對(duì)象的某些方法。您可以使用工廠(chǎng)類(lèi)創(chuàng)建對(duì)象,而不直接使用 new。這樣,如果您想要更改所創(chuàng)建的對(duì)象類(lèi)型,只需更改該工廠(chǎng)即可。使用該工廠(chǎng)的所有代碼會(huì)自動(dòng)更改。

清單 1 顯示工廠(chǎng)類(lèi)的一個(gè)示列。等式的服務(wù)器端包括兩個(gè)部分:數(shù)據(jù)庫(kù)和一組 PHP 頁(yè)面,這些頁(yè)面允許您添加反饋、請(qǐng)求反饋列表并獲取與特定反饋相關(guān)的文章。

清單 1. Factory1.php

    <?php
interface IUser
{
  function getName();
}

class User implements IUser
{
  public function __construct( $id ) { }

  public function getName()
  {
    return "Jack";
  }
}

class UserFactory
{
  public static function Create( $id )
  {
    return new User( $id );
  }
}

$uo = UserFactory::Create( 1 );
echo( $uo->getName()."\n" );
?>
  
?

IUser 接口定義用戶(hù)對(duì)象應(yīng)執(zhí)行什么操作。IUser 的實(shí)現(xiàn)稱(chēng)為 User,UserFactory 工廠(chǎng)類(lèi)則創(chuàng)建 IUser 對(duì)象。此關(guān)系可以用圖 1 中的 UML 表示。

圖 1. 工廠(chǎng)類(lèi)及其相關(guān) IUser 接口和用戶(hù)類(lèi)

?

?

如果您使用 php 解釋器在命令行上運(yùn)行此代碼,將得到如下結(jié)果:

    % php factory1.php
Jack
%

  
?

測(cè)試代碼會(huì)向工廠(chǎng)請(qǐng)求 User 對(duì)象,并輸出 getName 方法的結(jié)果。

有一種工廠(chǎng)模式的變體使用工廠(chǎng)方法。類(lèi)中的這些公共靜態(tài)方法構(gòu)造該類(lèi)型的對(duì)象。如果創(chuàng)建此類(lèi)型的對(duì)象非常重要,此方法非常有用。例如,假設(shè)您需要先創(chuàng)建對(duì)象,然后設(shè)置許多屬性。此版本的工廠(chǎng)模式會(huì)將該進(jìn)程封裝在單個(gè)位置中,這樣,不用復(fù)制復(fù)雜的初始化代碼,也不必將復(fù)制好的代碼在在代碼庫(kù)中到處粘貼。

清單 2 顯示使用工廠(chǎng)方法的一個(gè)示例。

清單 2. Factory2.php

    <?php
interface IUser
{
  function getName();
}

class User implements IUser
{
  public static function Load( $id )
  {
        return new User( $id );
  }

  public static function Create( )
  {
        return new User( null );
  }

  public function __construct( $id ) { }

  public function getName()
  {
    return "Jack";
  }
}

$uo = User::Load( 1 );
echo( $uo->getName()."\n" );
?>
  
?

這段代碼要簡(jiǎn)單得多。它僅有一個(gè)接口 IUser 和一個(gè)實(shí)現(xiàn)此接口的 User 類(lèi)。User 類(lèi)有兩個(gè)創(chuàng)建對(duì)象的靜態(tài)方法。此關(guān)系可用圖 2 中的 UML 表示。

圖 2. IUser 接口和帶有工廠(chǎng)方法的 user 類(lèi)

?



在命令行中運(yùn)行腳本產(chǎn)生的結(jié)果與清單 1 的結(jié)果相同,如下所示:

    % php factory2.php
Jack
%
  
?

如上所述,有時(shí)此類(lèi)模式在規(guī)模較小的環(huán)境中似乎有些大材小用。不過(guò),最好還是學(xué)習(xí)這種扎實(shí)的編碼形式,以便應(yīng)用于任意規(guī)模的項(xiàng)目中。

2. 單元素模式

某些應(yīng)用程序資源是獨(dú)占的,因?yàn)橛星抑挥幸粋€(gè)此類(lèi)型的資源。例如,通過(guò)數(shù)據(jù)庫(kù)句柄到數(shù)據(jù)庫(kù)的連接是獨(dú)占的。您希望在應(yīng)用程序中共享數(shù)據(jù)庫(kù)句柄,因?yàn)樵诒3诌B接打開(kāi)或關(guān)閉時(shí),它是一種開(kāi)銷(xiāo),在獲取單個(gè)頁(yè)面的過(guò)程中更是如此。

單元素模式可以滿(mǎn)足此要求。如果應(yīng)用程序每次包含且僅包含一個(gè)對(duì)象,那么這個(gè)對(duì)象就是一個(gè)單元素(Singleton)。清單 3 中的代碼顯示了 PHP V5 中的一個(gè)數(shù)據(jù)庫(kù)連接單元素。

清單 3. Singleton.php

    <?php
require_once("DB.php");

class DatabaseConnection
{
  public static function get()
  {
    static $db = null;
    if ( $db == null )
      $db = new DatabaseConnection();
    return $db;
  }

  private $_handle = null;

  private function __construct()
  {
    $dsn = 'mysql://root:password@localhost/photos';
    $this->_handle =& DB::Connect( $dsn, array() );
  }
 
  public function handle()
  {
    return $this->_handle;
  }
}

print( "Handle = ".DatabaseConnection::get()->handle()."\n" );
print( "Handle = ".DatabaseConnection::get()->handle()."\n" );
?>
  
?

此代碼顯示名為 DatabaseConnection 的單個(gè)類(lèi)。您不能創(chuàng)建自已的 DatabaseConnection,因?yàn)闃?gòu)造函數(shù)是專(zhuān)用的。但使用靜態(tài) get 方法,您可以獲得且僅獲得一個(gè) DatabaseConnection 對(duì)象。此代碼的 UML 如圖 3 所示。

圖 3. 數(shù)據(jù)庫(kù)連接單元素

?



在兩次調(diào)用間,handle 方法返回的數(shù)據(jù)庫(kù)句柄是相同的,這就是最好的證明。您可以在命令行中運(yùn)行代碼來(lái)觀察這一點(diǎn)。

    % php singleton.php
Handle = Object id #3
Handle = Object id #3
%
  
?

返回的兩個(gè)句柄是同一對(duì)象。如果您在整個(gè)應(yīng)用程序中使用數(shù)據(jù)庫(kù)連接單元素,那么就可以在任何地方重用同一句柄。

您可以使用全局變量存儲(chǔ)數(shù)據(jù)庫(kù)句柄,但是,該方法僅適用于較小的應(yīng)用程序。在較大的應(yīng)用程序中,應(yīng)避免使用全局變量,并使用對(duì)象和方法訪(fǎng)問(wèn)資源。

3. 觀察者模式

觀察者模式為您提供了避免組件之間緊密耦合的另一種方法。該模式非常簡(jiǎn)單:一個(gè)對(duì)象通過(guò)添加一個(gè)方法(該方法允許另一個(gè)對(duì)象,即觀察者 注冊(cè)自己)使本身變得可觀察。當(dāng)可觀察的對(duì)象更改時(shí),它會(huì)將消息發(fā)送到已注冊(cè)的觀察者。這些觀察者使用該信息執(zhí)行的操作與可觀察的對(duì)象無(wú)關(guān)。結(jié)果是對(duì)象可以相互對(duì)話(huà),而不必了解原因。

一個(gè)簡(jiǎn)單示例是系統(tǒng)中的用戶(hù)列表。清單 4 中的代碼顯示一個(gè)用戶(hù)列表,添加用戶(hù)時(shí),它將發(fā)送出一條消息。添加用戶(hù)時(shí),通過(guò)發(fā)送消息的日志觀察者可以觀察此列表。

清單 4. Observer.php

    <?php
interface IObserver
{
  function onChanged( $sender, $args );
}

interface IObservable
{
  function addObserver( $observer );
}

class UserList implements IObservable
{
  private $_observers = array();

  public function addCustomer( $name )
  {
    foreach( $this->_observers as $obs )
      $obs->onChanged( $this, $name );
  }

  public function addObserver( $observer )
  {
    $this->_observers []= $observer;
  }
}

class UserListLogger implements IObserver
{
  public function onChanged( $sender, $args )
  {
    echo( "'$args' added to user list\n" );
  }
}

$ul = new UserList();
$ul->addObserver( new UserListLogger() );
$ul->addCustomer( "Jack" );
?>
  
?

此代碼定義四個(gè)元素:兩個(gè)接口和兩個(gè)類(lèi)。IObservable 接口定義可以被觀察的對(duì)象,UserList 實(shí)現(xiàn)該接口,以便將本身注冊(cè)為可觀察。IObserver 列表定義要通過(guò)怎樣的方法才能成為觀察者,UserListLogger 實(shí)現(xiàn) IObserver 接口。圖 4 的 UML 中展示了這些元素。

圖 4. 可觀察的用戶(hù)列表和用戶(hù)列表事件日志程序

?

?

如果在命令行中運(yùn)行它,您將看到以下輸出:

    % php observer.php
'Jack' added to user list
%
  
?

測(cè)試代碼創(chuàng)建 UserList,并將 UserListLogger 觀察者添加到其中。然后添加一個(gè)消費(fèi)者,并將這一更改通知 UserListLogger。

認(rèn)識(shí)到 UserList 不知道日志程序?qū)?zhí)行什么操作很關(guān)鍵。可能存在一個(gè)或多個(gè)執(zhí)行其他操作的偵聽(tīng)程序。例如,您可能有一個(gè)向新用戶(hù)發(fā)送消息的觀察者,歡迎新用戶(hù)使用該系統(tǒng)。這種方法的價(jià)值在于 UserList 忽略所有依賴(lài)它的對(duì)象,它主要關(guān)注在列表更改時(shí)維護(hù)用戶(hù)列表并發(fā)送消息這一工作。

此模式不限于內(nèi)存中的對(duì)象。它是在較大的應(yīng)用程序中使用的數(shù)據(jù)庫(kù)驅(qū)動(dòng)的消息查詢(xún)系統(tǒng)的基礎(chǔ)。

4. 命令鏈模式

命令鏈 模式以松散耦合主題為基礎(chǔ),發(fā)送消息、命令和請(qǐng)求,或通過(guò)一組處理程序發(fā)送任意內(nèi)容。每個(gè)處理程序都會(huì)自行判斷自己能否處理請(qǐng)求。如果可以,該請(qǐng)求被處理,進(jìn)程停止。您可以為系統(tǒng)添加或移除處理程序,而不影響其他處理程序。清單 5 顯示了此模式的一個(gè)示例。

清單 5. Chain.php

    <?php
interface ICommand
{
  function onCommand( $name, $args );
}

class CommandChain
{
  private $_commands = array();

  public function addCommand( $cmd )
  {
    $this->_commands []= $cmd;
  }

  public function runCommand( $name, $args )
  {
    foreach( $this->_commands as $cmd )
    {
      if ( $cmd->onCommand( $name, $args ) )
        return;
    }
  }
}

class UserCommand implements ICommand
{
  public function onCommand( $name, $args )
  {
    if ( $name != 'addUser' ) return false;
    echo( "UserCommand handling 'addUser'\n" );
    return true;
  }
}

class MailCommand implements ICommand
{
  public function onCommand( $name, $args )
  {
    if ( $name != 'mail' ) return false;
    echo( "MailCommand handling 'mail'\n" );
    return true;
  }
}

$cc = new CommandChain();
$cc->addCommand( new UserCommand() );
$cc->addCommand( new MailCommand() );
$cc->runCommand( 'addUser', null );
$cc->runCommand( 'mail', null );
?>
  
?

此代碼定義維護(hù) ICommand 對(duì)象列表的 CommandChain 類(lèi)。兩個(gè)類(lèi)都可以實(shí)現(xiàn) ICommand 接口 —— 一個(gè)對(duì)郵件的請(qǐng)求作出響應(yīng),另一個(gè)對(duì)添加用戶(hù)作出響應(yīng)。 圖 5 給出了 UML。

圖 5. 命令鏈及其相關(guān)命令

?

五種常見(jiàn)的 PHP 設(shè)計(jì)模式

如果您運(yùn)行包含某些測(cè)試代碼的腳本,則會(huì)得到以下輸出:

    % php chain.php
UserCommand handling 'addUser'
MailCommand handling 'mail'
%
  
?

代碼首先創(chuàng)建 CommandChain 對(duì)象,并為它添加兩個(gè)命令對(duì)象的實(shí)例。然后運(yùn)行兩個(gè)命令以查看誰(shuí)對(duì)這些命令作出了響應(yīng)。如果命令的名稱(chēng)匹配 UserCommand 或 MailCommand,則代碼失敗,不發(fā)生任何操作。

為處理請(qǐng)求而創(chuàng)建可擴(kuò)展的架構(gòu)時(shí),命令鏈模式很有價(jià)值,使用它可以解決許多問(wèn)題。

5. 策略模式

我們講述的最后一個(gè)設(shè)計(jì)模式是策略 模式。在此模式中,算法是從復(fù)雜類(lèi)提取的,因而可以方便地替換。例如,如果要更改搜索引擎中排列頁(yè)的方法,則策略模式是一個(gè)不錯(cuò)的選擇。思考一下搜索引擎的幾個(gè)部分 —— 一部分遍歷頁(yè)面,一部分對(duì)每頁(yè)排列,另一部分基于排列的結(jié)果排序。在復(fù)雜的示例中,這些部分都在同一個(gè)類(lèi)中。通過(guò)使用策略模式,您可將排列部分放入另一個(gè)類(lèi)中,以便更改頁(yè)排列的方式,而不影響搜索引擎的其余代碼。

作為一個(gè)較簡(jiǎn)單的示例,清單 6 顯示了一個(gè)用戶(hù)列表類(lèi),它提供了一個(gè)根據(jù)一組即插即用的策略查找一組用戶(hù)的方法。

清單 6. Strategy.php

    <?php
interface IStrategy
{
  function filter( $record );
}

class FindAfterStrategy implements IStrategy
{
  private $_name;

  public function __construct( $name )
  {
    $this->_name = $name;
  }

  public function filter( $record )
  {
    return strcmp( $this->_name, $record ) <= 0;
  }
}

class RandomStrategy implements IStrategy
{
  public function filter( $record )
  {
    return rand( 0, 1 ) >= 0.5;
  }
}

class UserList
{
  private $_list = array();

  public function __construct( $names )
  {
    if ( $names != null )
    {
      foreach( $names as $name )
      {
        $this->_list []= $name;
      }
    }
  }

  public function add( $name )
  {
    $this->_list []= $name;
  }

  public function find( $filter )
  {
    $recs = array();
    foreach( $this->_list as $user )
    {
      if ( $filter->filter( $user ) )
        $recs []= $user;
    }
    return $recs;
  }
}

$ul = new UserList( array( "Andy", "Jack", "Lori", "Megan" ) );
$f1 = $ul->find( new FindAfterStrategy( "J" ) );
print_r( $f1 );

$f2 = $ul->find( new RandomStrategy() );
print_r( $f2 );
?>
  
?

此代碼的 UML 如圖 6 所示。

圖 6. 用戶(hù)列表和用于選擇用戶(hù)的策略

?

五種常見(jiàn)的 PHP 設(shè)計(jì)模式

UserList 類(lèi)是打包名稱(chēng)數(shù)組的一個(gè)包裝器。它實(shí)現(xiàn) find 方法,該方法利用幾個(gè)策略之一來(lái)選擇這些名稱(chēng)的子集。這些策略由 IStrategy 接口定義,該接口有兩個(gè)實(shí)現(xiàn):一個(gè)隨機(jī)選擇用戶(hù),另一個(gè)根據(jù)指定名稱(chēng)選擇其后的所有名稱(chēng)。運(yùn)行測(cè)試代碼時(shí),將得到以下輸出:

    % php strategy.php
Array
(
    [0] => Jack
    [1] => Lori
    [2] => Megan
)
Array
(
    [0] => Andy
    [1] => Megan
)
%
  
?

測(cè)試代碼為兩個(gè)策略運(yùn)行同一用戶(hù)列表,并顯示結(jié)果。在第一種情況中,策略查找排列在 J 后的任何名稱(chēng),所以您將得到 Jack、Lori 和 Megan。第二個(gè)策略隨機(jī)選取名稱(chēng),每次會(huì)產(chǎn)生不同的結(jié)果。在這種情況下,結(jié)果為 Andy 和 Megan。

策略模式非常適合復(fù)雜數(shù)據(jù)管理系統(tǒng)或數(shù)據(jù)處理系統(tǒng),二者在數(shù)據(jù)篩選、搜索或處理的方式方面需要較高的靈活性。

結(jié)束語(yǔ)

本文介紹的僅僅是 PHP 應(yīng)用程序中使用的幾種最常見(jiàn)的設(shè)計(jì)模式。在設(shè)計(jì)模式 一書(shū)中演示了更多的設(shè)計(jì)模式。不要因架構(gòu)的神秘性而放棄。模式是一種絕妙的理念,適用于任何編程語(yǔ)言、任何技能水平。

?

來(lái)源: http://www.ibm.com/developerworks/cn/opensource/os-php-designptrns/

?

關(guān)聯(lián): PHP實(shí)現(xiàn)單件模式的幾種方式

?

五種常見(jiàn)的 PHP 設(shè)計(jì)模式


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 国产高清美女一级a毛片久久 | 国产亚洲精品久久久999无毒 | 91精品欧美久久久久久动漫 | 国产在线网站 | 性久久久久久久久久 | 久久99热这里只频精品6中文字幕 | 91精品国产91久久久久久最新 | 91高清国产经典在线观看 | 激情婷婷综合 | 欧美一级在线播放 | 久久99久久99精品免观看不卡 | 天天艹久久 | 国产成人一区二区 | 亚洲精品福利在线 | 欧美色呦呦 | 2022国产成人福利精品视频 | 在线观看国产情趣免费视频 | 国产福利在线看 | 天堂网果冻传媒 | 久久99综合国产精品亚洲首页 | 操免费视频 | 国产一级毛片高清视频完整版 | 一区二区三区欧美在线观看 | 久草论坛 | 窝窝午夜精品一区二区 | 人操人摸| 日韩精品在线一区 | 久久草视频这里只精品 | 日韩视频在线观看免费视频 | 神马久久蜜桃 | 免费久久精品国产片香蕉 | 一区二区三区欧美 | 五月天激激婷婷大综合蜜芽 | 综合精品 | 91精品国产综合久久婷婷香蕉 | 99亚洲精品高清一二区 | 日本粉嫩一区二区三区视频 | 91福利视频合集 | 色播视频在线播放 | 成人av一区二区三区 | 久久黄色大片 |