介面卡設計模式(應用於活動業務)

大嗚發表於2019-02-16

介面卡的適用場景

  • 程式碼的複用性強。

  • 我們一直在使用介面卡,如果 只有USB連線頭,無法將手機插到標準的插座上面充電 ,這時需要的一個介面卡,一端接USB連線頭,另一端接插座

  • 活動專題,例抽獎,固定的規則是充值有抽獎機會,但是突然來了一個需求說充值還要分享才能有抽獎機會,這時可以運用上這個設計模式

案例一(來自於php 設計模式 書) – 假設一個企業網站同時銷售軟體服務和軟體產品,目前所有的交易都在美國進行,後續業務決定向歐洲發展要增加貨幣換算(增加介面卡)

案例二是自已設計於活動專題業務上,只是將邏輯摘取出來,程式碼不可直接執行

優點

  1. 靈活性擴充套件性都很好

  2. 將目標類和適配者類解耦

介面卡所涉及的角色包括下面幾種:

目標(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;
    }
}
?>

相關文章