适配器设计模式(应用于活动业务)

适配器的适用场景

  • 代码的复用性强。

  • 我们一直在使用适配器,如果 只有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 \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;
    }
}
?>
    原文作者:设计模式
    原文地址: https://segmentfault.com/a/1190000008784863
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞