代碼的複用性強。php
咱們一直在使用適配器,若是 只有USB鏈接頭,沒法將手機插到標準的插座上面充電 ,這時須要的一個適配器,一端接USB鏈接頭,另外一端接插座設計模式
活動專題,例抽獎,固定的規則是充值有抽獎機會,可是忽然來了一個需求說充值還要分享纔能有抽獎機會,這時能夠運用上這個設計模式app
案例一(來自於php 設計模式 書) - 假設一個企業網站同時銷售軟件服務和軟件產品,目前全部的交易都在美國進行,後續業務決定向歐洲發展要增長貨幣換算(增長適配器)網站
案例二是自已設計於活動專題業務上,只是將邏輯摘取出來,代碼不可直接運行this
靈活性擴展性都很好spa
將目標類和適配者類解耦設計
目標(Target):定義一個客戶端使用的特定接口。
客戶端(Client):使用目標接口,與和目標接口一致的對象合做。
被適配者(Adaptee):一個現存須要適配的接口。
適配器(Adapter):負責將Adaptee的接口轉換爲Target的接口。適配器是一個具體的類,這是該模式的核心。
適配器分爲類適配器和對象適配器兩種,下面將詳細講述。code
來自 php 設計模式 一書的適配器設計模式案例**對象
/** * EuroCalc.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->requestCount(); } private function requestCount() { $this->dollar *= $this->rate; return $this->dollar; } } /** * EuroCalc.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->requestCount(); } private function requestCount() { $this->euro *= $this->rate; return $this->euro; } } /** * 接口 ITarget.php */ interface ITarget { function requester(); } /** * 例:找一個合適的適配器來適合歐洲的插座同樣,如下就是建立這個適配器 * EuroAdapter 實現了一個接口又擴展了一個類 */ class EuroAdapter extends EuroCalc implements ITarget { public function __construct() { $this->requester(); } public function requester() { $this->rate = 0.8111; return $this->rate; } } /** * 用戶 */ class Client { private $euroRequest; private $dollarRequest; public function __construct() { $this->euroRequest = new EuroAdapter(); $this->dollarRequest = new DollarCalc(); $euros = "€"; echo "Euros:$euros".$this->makeAdapterRequest($this->euroRequest)."<br />"; echo "dollar:".$this->makeDollarRequest($this->dollarRequest); } public function makeAdapterRequest(ITarget $req) { return $req->requestCalc(40,50); } public function makeDollarRequest(DollarCalc $req) { return $req->requestCalc(40,50); } } $worker = new Client();
抽獎例子(代碼只顯示對應的設計邏輯部分)接口
<?php /** * 適配器模式 - 抽獎接口 * comment 當後臺規則不知足自動化,能夠添加對應的適配器,增長代碼的複用 * author AT */ namespace controller; // 每月份對應的適配器 06年3月 = SixMarch use \Adapter\SixMarch\LotteryAdapter; /** * 抽獎接口 入口文件 */ final class Lottery extends WebController { // 活動的配置信息 存放後臺配置的活動信息 private $hd_info; public function __construct() { // 加載配置信息 $this->hd_info = ''; } public function _lottery() { // 實例 $lottery = new LotteryAdapter($hd_info); // 取得抽獎結果 $rs = $lottery->_getLotteryResult(); return $rs; } } namespace controller; use \bbts\App as BaseApp; /** * */ class LotteryAdapter extends AutoLottery implements ILottery { public function __construct($hd_info) { // 後臺配置是否須要使用適配器 if($hd_info['use_adapter'] === true) { $adapter_name = $hd_info['adapter_name']; // $adapter_name = 'adapter_name'; test $this->$adapter_name(); } } /** * adapter_name 該活動對應的適配器 */ private function adapter_name() { // 假設不符合自動化的需求條件是必須進入遊戲後5分纔可抽獎,增長適配器的該內容便可,從而不用重寫整個抽獎活動 $game_info = App::$app->model()->checkEnterGameInfo(); if(strtotime($info['TIME']) - time() < 300) { $this->adapter_status = false; $this->adapter_code = -51; } } } namespace controller; use \bbts\App as BaseApp; /** * 自動化抽獎接口的基類 */ class AutoLottery { // 單獨開發條件的狀態 public $adapter_status = true; public $adapter_code = 0; public function _getLotteryResult(){ // 最後判斷適配器的狀態 if(!$this->adapter_status) { App::jetJsonpOutput($this->adapter_return_code); } // 業務邏輯判斷 // 經過則將數據入庫 $rs_status = App::$app->model()->insert($rs); // 返回結果 return $rs; } } ?>