介面卡的適用場景
-
程式碼的複用性強。
-
我們一直在使用介面卡,如果 只有USB連線頭,無法將手機插到標準的插座上面充電 ,這時需要的一個介面卡,一端接USB連線頭,另一端接插座
-
活動專題,例抽獎,固定的規則是充值有抽獎機會,但是突然來了一個需求說充值還要分享才能有抽獎機會,這時可以運用上這個設計模式
案例一(來自於php 設計模式 書) – 假設一個企業網站同時銷售軟體服務和軟體產品,目前所有的交易都在美國進行,後續業務決定向歐洲發展要增加貨幣換算(增加介面卡)
案例二是自已設計於活動專題業務上,只是將邏輯摘取出來,程式碼不可直接執行
優點
-
靈活性擴充套件性都很好
-
將目標類和適配者類解耦
介面卡所涉及的角色包括下面幾種:
目標(Target):定義一個客戶端使用的特定介面。
客戶端(Client):使用目標介面,與和目標介面一致的物件合作。
被適配者(Adaptee):一個現存需要適配的介面。
介面卡(Adapter):負責將Adaptee的介面轉換為Target的介面。介面卡是一個具體的類,這是該模式的核心。
介面卡分為類介面卡和物件介面卡兩種,下面將詳細講述。
案例一
來自 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 AdapterSixMarchLotteryAdapter;
/**
* 抽獎介面 入口檔案
*/
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 btsApp 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 btsApp 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;
}
}
?>