主頁(yè) > 知識(shí)庫(kù) > PHP設(shè)計(jì)模式之適配器模式定義與用法詳解

PHP設(shè)計(jì)模式之適配器模式定義與用法詳解

熱門(mén)標(biāo)簽:寧波外呼營(yíng)銷系統(tǒng) 長(zhǎng)沙做地圖標(biāo)注公司 房產(chǎn)中介用的是什么外呼系統(tǒng) 福建銀行智能外呼系統(tǒng)價(jià)格 電話機(jī)器人銷售主要負(fù)責(zé)什么 四川保險(xiǎn)智能外呼系統(tǒng)供應(yīng)商 上海做外呼線路的通信公司 遼寧ai電銷機(jī)器人價(jià)格 地圖標(biāo)注專員怎么樣

本文實(shí)例講述了PHP設(shè)計(jì)模式之適配器模式定義與用法。分享給大家供大家參考,具體如下:

適配器很容易理解, 大多數(shù)人家庭都有手機(jī)轉(zhuǎn)接器, 用來(lái)為移動(dòng)電話充電,這就是一種適配器. 如果只有USB接頭, 就無(wú)法將移動(dòng)電話插到標(biāo)準(zhǔn)插座上. 實(shí)際上, 必須使用一個(gè)適配器, 一端接USB插頭, 一端接插座. 當(dāng)然, 你可以拿出電氣工具,改裝USB連接頭, 或者重新安裝插座, 不過(guò)這樣會(huì)帶來(lái)很多額外的工作, 而且可能會(huì)把連接頭或插座弄壞. 所以, 最可取的方法就是找一個(gè)適配器. 軟件開(kāi)發(fā)也是如此.

類適配器模式(使用繼承)

類適配器模式很簡(jiǎn)單, 不過(guò)與對(duì)象適配器模式相比, 類適配器模式的靈活性弱些, 類適配器簡(jiǎn)單的原因在于 , 適配器(Adapter)會(huì)從被適配者(Adaptee)繼承功能, 所以適配模式中需要編寫(xiě)的代碼比較少.

由于類適配器模式包含雙重繼承, 但是PHP并不支持雙重繼承, 不過(guò)幸運(yùn)的是,PHP可以用接口來(lái)模擬雙重繼承, 下面是一個(gè)正確的結(jié)構(gòu), 不僅繼承了一個(gè)類, 同時(shí)還繼承了一個(gè)接口

class ChildClass extends ParentClass implements ISomeAdapter
{
}

實(shí)現(xiàn)類適配器模式時(shí), 參與者必須包括一個(gè)PHP接口

下面以一個(gè)貨幣兌換為例來(lái)演示:

假設(shè)有一個(gè)企業(yè)網(wǎng)站在同時(shí)銷售軟件服務(wù)和軟件產(chǎn)品, 目前, 所有交易都在美國(guó)進(jìn)行, 所以完全可以用美元來(lái)完成所有計(jì)算.現(xiàn)在開(kāi)發(fā)人員希望能有一個(gè)轉(zhuǎn)換器能處理美元和歐元的兌換, 而不改變?cè)瓉?lái)按美元交易額的類.通過(guò)增加一個(gè)適配器, 現(xiàn)在程序即可以用美元計(jì)算也可以用歐元計(jì)算.

DollarCalc.php

?php
class DollarCalc
{
 private $dollar;
 private $product;
 private $service;
 public $rate = 1;
 public function requestCalc($productNow, $serviceNow)
 {
  $this->product = $productNow;
  $this->service = $serviceNow;
  $this->dollar = $this->product + $this->service;
  return $this->requestTotal();
 }
 public function requestTotal()
 {
  $this->dollar *= $this->rate;
  return $this->dollar;
 }
}

查看這個(gè)類,可以看到其中有一個(gè)屬性$rate,requestTotal()方法使用$rate計(jì)算一次交易的金額.在這個(gè)版本中, 這個(gè)值設(shè)置為1,實(shí)際上總金額無(wú)需再乖以兌換率, 不過(guò)如果要為客戶提供折扣或者要增加額外服務(wù)或產(chǎn)品的附加費(fèi), $rate變量會(huì)很方便. 這個(gè)類并不是適合器模式的一部分, 不過(guò)這是一個(gè)起點(diǎn).

需求變化了

現(xiàn)在客戶的公司要向歐洲發(fā)展,所以需要開(kāi)發(fā)一個(gè)應(yīng)用, 能夠用歐元完成同樣的計(jì)算. 你希望這個(gè)歐元計(jì)算能夠像DollarCalc一樣, 所要做的就是改變變量名.

EuroCalc.php

?php
class EuroCalc
{
 private $euro;
 private $product;
 private $service;
 public $rate = 1;
 public function requestCalc($productNow, $serviceNow)
 {
  $this->product = $productNow;
  $this->service = $serviceNow;
  $this->euro = $this->product + $this->service;
  return $this->requestTotal();
 }
 public function requestTotal()
 {
  $this->euro *= $this->rate;
  return $this->euro;
 }
}

接下來(lái), 再把應(yīng)用的其余部分插入到EuroCalc類中. 不過(guò),因?yàn)榭蛻舻乃袛?shù)據(jù)都是按美元計(jì)算的.換句話說(shuō), 如果不重新開(kāi)發(fā)整個(gè)程序, 就無(wú)法在系統(tǒng)中"插入"這個(gè)歐元計(jì)算. 但是你不想這么做. 為了加入EuroCalc, 你需要一個(gè)適配器: 就像找一個(gè)適配器來(lái)適應(yīng)歐洲的插座一樣, 可以創(chuàng)建一個(gè)適配器, 使你的系統(tǒng)能夠使用歐元. 幸運(yùn)的是, 類適配器正是為這樣的情況設(shè)計(jì)的.首先需要?jiǎng)?chuàng)建一個(gè)接口. 在這個(gè)類圖中, 這個(gè)接口名為ITarget. 它只有一個(gè)方法requester(). requester()是一個(gè)抽象方法, 要由接口的具體實(shí)現(xiàn)來(lái)實(shí)現(xiàn)這個(gè)方法.

ITarget.php

?php
interface ITarget
{
 public function requester();
}

現(xiàn)在開(kāi)發(fā)人員可以實(shí)現(xiàn)requester()方法, 請(qǐng)求歐元而不是美元.

在使用繼承的適配器設(shè)計(jì)模式中, 適配器(Adapter)參與都既實(shí)現(xiàn)ITarget接口,還實(shí)現(xiàn)了具體類EuroCalc. 創(chuàng)建EuroAdapter不需要做太多工作, 因?yàn)榇蟛糠止ぷ饕呀?jīng)在EuroCal類中完成.現(xiàn)在要做的就是實(shí)現(xiàn)request()方法, 使它能把美元值轉(zhuǎn)換為歐元值.

EuroAdapter.php

?php
include_once('EuroCalc.php');
include_once('ITarget.php');
class EuroAdapter extends EuroCalc implements ITarget
{
 public function __construct()
 {
  $this->requester();
 }
 public function requester()
 {
  $this->rate = 0.8111;
  return $this->rate;
 }
}

類適配模式中, 一個(gè)具體類會(huì)繼承另一個(gè)具體類, 有這種結(jié)構(gòu)的設(shè)計(jì)模式很少見(jiàn), 大多數(shù)設(shè)計(jì)模式中, 幾乎都是繼承一個(gè)抽象類, 并由類根據(jù)需要實(shí)現(xiàn)其抽象方法和屬性. 換句話說(shuō), 一般談到繼承時(shí), 都是具體類繼承抽象類.

由于既實(shí)現(xiàn)了一個(gè)接口又?jǐn)U展了一個(gè)類, 所以EuroAdapter類同時(shí)擁有該接口和具體類的接口. 通過(guò)使用requester()方法, EuroAdapter類可以設(shè)置rate值(兌換率), 從而能使用被適配者的功能, 而元而做任何改變.

下面定義一個(gè)Client類, 從EuroAdapter和DollarCalc類發(fā)出請(qǐng)求. 可以看到,原來(lái)的DollarCalc仍能很好地工作, 不過(guò)它沒(méi)有ITarget接口.

Client.php

?php
include_once('EuroAdapter.php');
include_once('DollarCalc.php');
class Client
{
 public function __construct()
 {
  $euro = '€';
  echo "區(qū)元: $euro" . $this->makeApapterRequest(new EuroAdapter()) . 'br />';
  echo "美元: $: " . $this->makeDollarRequest(new DollarCalc()) . 'br />';
 }
 private function makeApapterRequest(ITarget $req)
 {
  return $req->requestCalc(40,50);
 }
 private function makeDollarRequest(DollarCalc $req)
 {
  return $req->requestCalc(40,50);
 }
}
$woker = new Client();

運(yùn)行結(jié)果如下:

Euros: €72.999
Dollars: $: 90

可以看到,美元和歐元都可以處理, 這就是適配器模式的方便之處.

這個(gè)計(jì)算很簡(jiǎn)單, 如果是針對(duì)更為復(fù)雜的計(jì)算, 繼承要提供建立類適配器的Target接口的必要接口和具體實(shí)現(xiàn)

使用組合的適配器模式

對(duì)象適配器模式使用組合而不是繼承, 不過(guò)它也會(huì)完成同樣的目標(biāo). 通過(guò)比較這兩個(gè)版本的適配器模式, 可以看出它們各自的優(yōu)缺點(diǎn). 采用類適配器模式時(shí),適配器可以繼承它需要的大多數(shù)功能, 只是通過(guò)接口稍微調(diào). 在對(duì)象適配器模式中 適配器(Adapter)參與使用被適配者(Adaptee), 并實(shí)現(xiàn)Target接口. 在類適配器模式中, 適配器(Adapter)則是一個(gè)被適配者(Adaptee), 并實(shí)現(xiàn)Target接口.

示例: 從桌面環(huán)境轉(zhuǎn)向移動(dòng)環(huán)境

PHP程序員經(jīng)常會(huì)遇到這樣一個(gè)問(wèn)題:需要適應(yīng)移動(dòng)環(huán)境而做出調(diào)整.不久之前,你可能只需要考慮提供一個(gè)網(wǎng)站來(lái)適應(yīng)多種不同的桌面環(huán)境. 大多數(shù)桌面都使用一個(gè)布局, 再由設(shè)計(jì)人員讓它更美觀. 對(duì)于移動(dòng)設(shè)備, 設(shè)計(jì)人員和開(kāi)發(fā)人員不僅需要重新考慮桌面和移動(dòng)環(huán)境中頁(yè)面顯示的設(shè)計(jì)元素, 還要考慮如何從一個(gè)環(huán)境切換到另一個(gè)環(huán)境.

首先來(lái)看桌面端的類Desktop(它將需要一個(gè)適配器). 這個(gè)類使用了一個(gè)簡(jiǎn)單但很寬松的接口:

IFormat.php

?php
interface IFormat
{
 public function formatCSS();
 public function formatGraphics();
 public function horizontalLayout();
}

它支持css和圖片選擇, 不過(guò)其中一個(gè)方法指示一種水平布局, 我們知道這種布局并不適用小的移動(dòng)設(shè)備.下面給出實(shí)現(xiàn)這個(gè)接口的Desktop類

Desktop.php

?php
include_once('IFormat.php');
class Desktop implements IFormat
{
 public function formatCSS()
 {
  echo "引用desktop.cssbr />";
 }
 public function formatGraphics()
 {
  echo "引用desktop.png圖片br />";
 }
 public function horizontalLayout()
 {
  echo '桌面:水平布局';
 }
}

問(wèn)題來(lái)了, 這個(gè)布局對(duì)于小的移動(dòng)設(shè)備來(lái)說(shuō)太寬了. 所以我們的目標(biāo)是仍采用同樣的內(nèi)容, 但調(diào)整為一種移動(dòng)設(shè)計(jì).

下面來(lái)看移動(dòng)端的類Mobile

首先移動(dòng)端有一個(gè)移動(dòng)端的接口

IMobileFormat

?php
interface IMobileFormat
{
 public function formatCSS();
 public function formatGraphics();
 public function verticalLayout();
}

可以看到, IMobileFormat接口和IFormat接口是不一樣的,也就是不兼容的, 一個(gè)包含了方法horizontalLayout(), 另一個(gè)包含方法verticalLaout(), 它們的差別很小, 最主要的區(qū)別是: 桌面設(shè)計(jì)可以采用水平的多欄布局, 而移動(dòng)設(shè)計(jì)要使用垂直布局,而適配器就是要解決這個(gè)問(wèn)題

下面給出一個(gè)實(shí)現(xiàn)了IMoibleFormat接口的Mobile類

Mobile.php

?php
include_once('IMobileFormat.php');
class Mobile implements IMobileFormat
{
 public function formatCSS()
 {
  echo "引用mobile.cssbr />";
 }
 public function formatGraphics()
 {
  echo "引用mobile.png圖片br />";
 }
 public function verticalLayout()
 {
  echo '移動(dòng)端:垂直布局';
 }
}

Mobile類和Desktop類非常相似, 不過(guò)是圖片和CSS引用不同

接下來(lái),我們需要一個(gè)適配器,將Desktop和Mobile類結(jié)合在一起

MobileAdapter.php

?php
include_once('IFormat.php');
include_once('Mobile.php');
class MobileAdapter implements IFormat
{
 private $mobile;
 public function __construct(IMobileFormat $mobileNow)
 {
  $this->mobile = $mobileNow;
 }
 public function formatCSS()
 {
  $this->mobile->formatCSS();
 }
 public function formatGraphics()
 {
  $this->mobile->formatGraphics();
 }
 public function horizontalLayout()
 {
  $this->mobile->verticalLayout();
 }
}

可以看到,MobileAdapter實(shí)例化時(shí)要提供一個(gè)Mobile對(duì)象實(shí)例.還要注意 ,類型提示中使用了IMobileFormat, 確保參數(shù)是一個(gè)Mobile對(duì)象.有意思的是, Adapter參與者通過(guò)實(shí)現(xiàn)horizontalLayout()方法來(lái)包含verticalLayout()方法.實(shí)際上, 所有MobileAdapter方法都包裝了一個(gè)Mobile方法.碰巧的是, 適配器參與者中的一個(gè)方法并不在適配器接口中(verticalLayout());它們可能完全不同, 適配器只是把它們包裝在適配器接口(IFormat)的某一方法中.

客戶調(diào)用(Client)

Client.php

?php
include_once('Mobile.php');
include_once('MobileAdapter.php');
class Client
{
 private $mobile;
 private $mobileAdapter;
 public function __construct()
 {
  $this->mobile = new Mobile();
  $this->mobileAdapter = new MobileAdapter($this->mobile);
  $this->mobileAdapter->formatCSS();
  $this->mobileAdapter->formatGraphics();
  $this->mobileAdapter->horizontalLayout();
 }
}
$worker = new Client();

適配器模式中的Client類必須包裝Adaptee(Mobile)的一個(gè)實(shí)例, 以便集成到Adapter本身.實(shí)例化Adapter時(shí), Client使用Adatee作為參數(shù)來(lái)完成Adapter的實(shí)例化.所以客戶必須首先創(chuàng)建一個(gè)Adapter對(duì)象(new Mobile()), 然后創(chuàng)建一個(gè)Adapter((new MobileAdapter($this->mobile)).

Client類的大多數(shù)請(qǐng)求都是通過(guò)MobileAdapter發(fā)出的. 不過(guò)這個(gè)代碼的最后他使用了Mobile類的實(shí)例.

適配器和變化

PHP程序員要即該面對(duì)變化.不同版本的PHP會(huì)變化, 可能增加新的功能, 另外還可能取消一些功能.而且隨著PHP的大大小小的變化,MySQL也在改變.例如, mysql的擴(kuò)展包升級(jí)為mysqli, PHP開(kāi)發(fā)人員需要相應(yīng)調(diào)整, 要改為使用mysqli中的新API.這里適合采用適配器模式嗎?可能不適合.適配器可能適用, 可能不適用,這取決于你的程序如何配置.當(dāng)然可以重寫(xiě)所有連接和交互代碼, 不過(guò)這可不是適配器模式的本意, 這就像是重新安裝USB連接頭, 想把它插進(jìn)標(biāo)準(zhǔn)的墻上插座一樣. 不過(guò), 如果所有原來(lái)的mysql代碼都在模塊中, 你可以修改這個(gè)模塊(類),換入一個(gè)有相同接口的新模塊.只是要使用mysqli而不是mysql.我不認(rèn)為交換等同于適配器, 不過(guò)道理是一樣的, 在適配器模式中, 原來(lái)的代碼沒(méi)有任何改變, 有變化的只是適配器.

如果需要結(jié)合使用兩個(gè)不兼容的接口, 這種情況下, 適配器模式最適用.適配器可以完成接口的"聯(lián)姻".可以把適配器看作是一個(gè)婚姻顧問(wèn);通過(guò)創(chuàng)建一個(gè)公共接口來(lái)克服雙方的差異.利用 這種設(shè)計(jì)模式, 可以促成二者的合作,而避免完全重寫(xiě)某一部分.

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

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

您可能感興趣的文章:
  • PHP設(shè)計(jì)模式之適配器模式(Adapter)原理與用法詳解
  • php設(shè)計(jì)模式 Adapter(適配器模式)
  • PHP設(shè)計(jì)模式之適配器模式代碼實(shí)例
  • 學(xué)習(xí)php設(shè)計(jì)模式 php實(shí)現(xiàn)適配器模式
  • PHP設(shè)計(jì)模式之適配器模式原理與用法分析
  • php設(shè)計(jì)模式之適配器模式原理、用法及注意事項(xiàng)詳解
  • php設(shè)計(jì)模式之適配器模式實(shí)例分析【星際爭(zhēng)霸游戲案例】
  • PHP設(shè)計(jì)模式(四)原型模式Prototype實(shí)例詳解【創(chuàng)建型】
  • PHP設(shè)計(jì)模式(三)建造者模式Builder實(shí)例詳解【創(chuàng)建型】
  • PHP設(shè)計(jì)模式(一)工廠模式Factory實(shí)例詳解【創(chuàng)建型】
  • PHP設(shè)計(jì)模式概論【概念、分類、原則等】
  • PHP設(shè)計(jì)模式(五)適配器模式Adapter實(shí)例詳解【結(jié)構(gòu)型】

標(biāo)簽:佛山 延安 宿遷 澳門(mén) 常德 工商登記 宜春 深圳

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《PHP設(shè)計(jì)模式之適配器模式定義與用法詳解》,本文關(guān)鍵詞  PHP,設(shè)計(jì)模式,之,適配器,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問(wèn)題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無(wú)關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《PHP設(shè)計(jì)模式之適配器模式定義與用法詳解》相關(guān)的同類信息!
  • 本頁(yè)收集關(guān)于PHP設(shè)計(jì)模式之適配器模式定義與用法詳解的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章