好湿?好紧?好多水好爽自慰,久久久噜久噜久久综合,成人做爰A片免费看黄冈,机机对机机30分钟无遮挡

主頁 > 知識庫 > PHP設計模式之適配器模式(Adapter)原理與用法詳解

PHP設計模式之適配器模式(Adapter)原理與用法詳解

熱門標簽:百應電話機器人服務 河南電銷卡外呼系統哪家強 揚州地圖標注app 昭通辦理400電話 山西探意電話機器人 騰訊外呼管理系統 青島語音外呼系統招商 岳陽外呼型呼叫中心系統在哪里 山西回撥外呼系統

本文實例講述了PHP設計模式之適配器模式(Adapter)原理與用法。分享給大家供大家參考,具體如下:

這個適配器模式,就是為了將一個類的接口轉換成客戶希望的另外一個接口,并且使用原本不兼容的而不能在一起工作的那些類可以在一起工作。它的核心思想就是把對某些相似的類的操作轉化為一個統一的“接口”(這里是比喻的說話)--適配器,或者比喻為一個“界面”,統一或屏蔽了那些類的細節。適配器模式還構造了一種“機制”,使“適配”的類可以很容易的增減,而不用修改與適配器交互的代碼,符合“減少代碼間耦合”的設計原則。

我們來考慮下開發過程中,我們引用一個第三方類庫的場景,這個類庫隨著版本的改變,它提供的API也可能會改變。如果很不幸的是,你的應用里引用的某個API已經發生改變的時候,除了在心中默默地罵“wocao”之外,你還得去硬著頭皮去改大量的代碼,這個時候,為了減少工作量,我們就可以使用適配器模式。

先來看一個網上的案例:

  • 假如我們原始的有一個UserInfo的類,提供用戶信息的類,早起設計該類的時候,只實現了一個getUserName獲取用戶名的方法。
  • 我們的MyOldObject類中,將從UserInfo這個類中獲取用戶信息,并且輸出用戶名
  • 隨著時間的推移,我們舊的UserInfo這個類只提供的獲取用戶名的方法,已經沒法滿足需求,我們同時需要獲取用戶的年齡等信息。
  • 為了不改變原本UserInfo這個類,我們就繼承UserInfo,建立一個UserInfoAdapter類,實現getAge獲取年齡這樣的方法。
  • 在我們的MyNewObject新的類中,我們實例化UserInfoAdapter,打印出用戶姓名和年齡。
  • 這樣,隨著我們的擴展,我們沒有改變原先UserInfo這個類和使用這個類的接口,我們通過適配的方法,將UserInfo類擴展出來

代碼實現過程如下:

?php
//早期的一個用戶類,只實現獲取用戶名的方法
class UserInfo {
    public function getUserName() {
        return 'initphp';
    }
}

//MyOldObject類,從UserInfo類中獲取信息,輸出用戶名
?php
include_once("UserInfo.php");
class MyOldObject {
    public function write() {
        $UserInfo = new UserInfo;
        echo $UserInfo->getUserName();
    }
}
$a = new MyOldObject;
$a->write();

上述代碼是早期的時候,我們使用的案例。然而UserInfoAdapter類,隨著時間推移,項目需求在變化,UserInfo類無法滿足需求,我們做了UserInfo類的適配器,滿足新功能的需求,如下:

?php
include_once("UserInfo.php");
class UserInfoAdapter extends UserInfo{
    public function getUserAge() {
        return 28;
    }
    public function getUser() {
        return array(
            'username' => $this->getUserName(),
            'age' => $this->getUserAge()
        );
    }
}

MyNewObject類,新功能的類,需要打印出用戶年齡和姓名,UserInfo類無法滿足需求,需要調用UserInfoAdapter適配器這個類,如下:

?php
include_once("UserInfoAdapter.php");
class MyNewObject {
    public function write() {
        $UserInfoAdapter = new UserInfoAdapter;
        print_r($UserInfoAdapter->getUser());
    }
}
$a = new MyNewObject;
$a->write();

大概了解了哈,接下來咱們通過一個故事來了解下。

開始的時候,黑棗玩具公司專門生產玩具,生產的玩具不限于狗、貓、獅子,魚等動物,并且每個玩具都可以進行“張嘴”與“閉嘴”操作,分別調用了openMouth與closeMouth方法。在這個時候,黑棗玩具公司的程序猿就定義一個抽象類Toy,甚至是接口Toy,完事其他的類去繼承父類,實現父類的方法,很和諧的是吧。

后來,為了擴大業務,也因為紅棗遙控公司可以使用遙控設備對動物進行嘴巴控制,黑棗玩具公司打算與紅棗遙控公司合作。不過,麻煩的是,紅棗遙控公司的遙控設備是調用的動物的doMouthOpen及doMouthClose方法。所以,黑棗玩具公司的程序員現在必須要做的是對Toy系列類進行升級改造,使Toy能調用doMouthOpen及doMouthClose方法。

在考慮實現的方法時,黑棗玩具公司的程序猿可以再在他們的父類子類里給紅棗遙控公司添加這么兩個方法就好啦。但是,當黑棗玩具公司的程序猿一次又一次在父類子類里面重復添加著這兩個方法的時候,總會想著如此重復的工作,難道不能解決么?當有數百個子類的時候,程序員會改瘋的。程序員往往比的是誰在不影響效率的時候更會“偷懶”,這樣做下去程序員會覺得自己很傻。

咱也不廢話了,先來看下最開始的時候的代碼:

abstract class Toy
{
  public abstract function openMouth();
  public abstract function closeMouth();
}
class Dog extends Toy
{
  public function openMouth()
  {
    echo "Dog open Mouth\n";
  }
  public function closeMouth()
  {
    echo "Dog open Mouth\n";
  }
}
class Cat extends Toy
{
  public function openMouth()
  {
    echo "Cat open Mouth\n";
  }
  public function closeMouth()
  {
    echo "Cat open Mouth\n";
  }
}

完事,因為綠棗遙控公司遙控設備更便宜穩定,所以黑棗玩具公司又打算要與綠棗遙控公司合作。

不過綠棗遙控公司的遙控設備是調用的動物的operMouth(type)方法來實現嘴巴控制。如果type)方法來實現嘴巴控制。如果type為0則“閉嘴”,反之張嘴。這下好了,程序員又得對Toy及其子類進行升級,使Toy能調用operMouth()方法。

在這個時候,程序員必須要動腦子想辦法了,就算自己勤快,萬一哪天紫棗青棗黃棗山棗這些遙控公司全來的時候,忽略自己不斷增多的工作量不說,這個Toy類可是越來越大,總有一天程序員不崩潰,系統也會崩潰的。

那么,問題出在哪里呢?

其實就是一開始的代碼設計實現違反了“開-閉”原則,也就是一個軟件實體應當對擴展開放,對修改關閉。也就是說,在設計一個模塊的時候,應當使這個模塊可以在不被修改的前提下被擴展。也就是說每個尸體都是一個小王國,你讓我參與你的事情這個可以,但你不能修改我的內部,除非我的內部代碼確實可以優化。

來看下最后的結果:

?php
abstract class Toy
{
  public abstract function openMouth();
  public abstract function closeMouth();
}
class Dog extends Toy
{
  public function openMouth()
  {
    echo "Dog open Mouth\n";
  }
  public function closeMouth()
  {
    echo "Dog close Mouth\n";
  }
}
class Cat extends Toy
{
  public function openMouth()
  {
    echo "Cat open Mouth\n";
  }
  public function closeMouth()
  {
    echo "Cat close Mouth\n";
  }
}
//目標角色:紅棗遙控公司
interface RedTarget
{
  public function doMouthOpen();
  public function doMouthClose();
}
//目標角色:綠棗遙控公司及
interface GreenTarget
{
  public function operateMouth($type = 0);
}
//類適配器角色:紅棗遙控公司
class RedAdapter implements RedTarget
{
  private $adaptee;
  function __construct(Toy $adaptee)
  {
    $this->adaptee = $adaptee;
  }
  //委派調用Adaptee的sampleMethod1方法
  public function doMouthOpen()
  {
    $this->adaptee->openMouth();
  }
  public function doMouthClose()
  {
    $this->adaptee->closeMouth();
  }
}
//類適配器角色:綠棗遙控公司
class GreenAdapter implements GreenTarget
{
  private $adaptee;
  function __construct(Toy $adaptee)
  {
    $this->adaptee = $adaptee;
  }
  //委派調用Adaptee:GreenTarget的operateMouth方法
  public function operateMouth($type = 0)
  {
    if ($type) {
      $this->adaptee->openMouth();
    } else {
      $this->adaptee->closeMouth();
    }
  }
}
class testDriver
{
  public function run()
  {
     //實例化一只狗玩具
    $adaptee_dog = new Dog();
    echo "給狗套上紅棗適配器\n";
    $adapter_red = new RedAdapter($adaptee_dog);
    //張嘴
    $adapter_red->doMouthOpen();
    //閉嘴
    $adapter_red->doMouthClose();
    echo "給狗套上綠棗適配器\n";
    $adapter_green = new GreenAdapter($adaptee_dog);
    //張嘴
    $adapter_green->operateMouth(1);
    //閉嘴
    $adapter_green->operateMouth(0);
  }
}
$test = new testDriver();
$test->run();

大概了解了使用方式之后,我們來看下適配器模式之中的主要角色:

  1. 目標(Target)角色:定義客戶端使用的與特定領域相關的接口,這也就是我們所期待得到的
  2. 源(Adaptee)角色:需要進行適配的接口
  3. 適配器(Adapter)角色:對Adaptee的接口與Target接口進行適配;適配器是本模式的核心,適配器把源接口轉換成目標接口,此角色為具體類

使用場景如下:

   1、你想使用一個已經存在的類,而它的接口不符合你的需求
   2、你想創建一個可以復用的類,該類可以與其他不相關的類或不可預見的類協同工作
   3、你想使用一個已經存在的子類,但是不可能對每一個都進行子類化以匹配它們的接口。對象適配器可以適配它的父類接口(僅限于對象適配器)

再來看下類適配器和對象適配器的一些解釋和區別:

類適配器:Adapter與Adaptee是繼承關系

   1、用一個具體的Adapter類和Target進行匹配。結果是當我們想要一個匹配一個類以及所有它的子類時,類Adapter將不能勝任工作
   2、使得Adapter可以重定義Adaptee的部分行為,因為Adapter是Adaptee的一個子集
   3、僅僅引入一個對象,并不需要額外的指針以間接取得adaptee

對象適配器:Adapter與Adaptee是委托關系

   1、允許一個Adapter與多個Adaptee同時工作。Adapter也可以一次給所有的Adaptee添加功能
   2、使用重定義Adaptee的行為比較困難

再來看下其它和適配器模式的對比:

  1. 橋梁模式(bridge模式):橋梁模式與對象適配器類似,但是橋梁模式的出發點不同,橋梁模式目的是將接口部分和實現部分分離,從而對它們可以較為容易也相對獨立的加以改變。而對象適配器模式則意味著改變一個已有對象的接口
  2. 裝飾器模式(decorator模式):裝飾模式增強了其他對象的功能而同時又不改變它的接口。因此裝飾模式對應用的透明性比適配器更好。

最后來看下類適配器和對象適配器案例,如下:

//類適配器使用的是繼承
?php
/**
 * 目標角色
 */
interface Target {
 /**
  * 源類也有的方法1
  */
 public function sampleMethod1();
 /**
  * 源類沒有的方法2
  */
 public function sampleMethod2();
}
/**
 * 源角色
 */
class Adaptee {
 /**
  * 源類含有的方法
  */
 public function sampleMethod1() {
  echo 'Adaptee sampleMethod1 br />';
 }
}
/**
 * 類適配器角色
 */
class Adapter extends Adaptee implements Target {
 /**
  * 源類中沒有sampleMethod2方法,在此補充
  */
 public function sampleMethod2() {
  echo 'Adapter sampleMethod2 br />';
 }
}
class Client {
 /**
  * Main program.
  */
 public static function main() {
  $adapter = new Adapter();
  $adapter->sampleMethod1();
  $adapter->sampleMethod2();
 }
}
Client::main();
?>

//對象適配器使用的是委派
?php
/**
 * 目標角色
 */
interface Target {
 /**
  * 源類也有的方法1
  */
 public function sampleMethod1();
 /**
  * 源類沒有的方法2
  */
 public function sampleMethod2();
}
/**
 * 源角色
 */
class Adaptee {
 /**
  * 源類含有的方法
  */
 public function sampleMethod1() {
  echo 'Adaptee sampleMethod1 br />';
 }
}
/**
 * 類適配器角色
 */
class Adapter implements Target {
 private $_adaptee;
 public function __construct(Adaptee $adaptee) {
  $this->_adaptee = $adaptee;
 }
 /**
  * 委派調用Adaptee的sampleMethod1方法
  */
 public function sampleMethod1() {
  $this->_adaptee->sampleMethod1();
 }
 /**
  * 源類中沒有sampleMethod2方法,在此補充
  */
 public function sampleMethod2() {
  echo 'Adapter sampleMethod2 br />';
 }
}
class Client {
 /**
  * Main program.
  */
 public static function main() {
  $adaptee = new Adaptee();
  $adapter = new Adapter($adaptee);
  $adapter->sampleMethod1();
  $adapter->sampleMethod2();
 }
}
Client::main();
?>

好啦,本次記錄就到這里了。

更多關于PHP相關內容感興趣的讀者可查看本站專題:《php面向對象程序設計入門教程》、《PHP數組(Array)操作技巧大全》、《PHP基本語法入門教程》、《PHP運算與運算符用法總結》、《php字符串(string)用法總結》、《php+mysql數據庫操作入門教程》及《php常見數據庫操作技巧匯總》

希望本文所述對大家PHP程序設計有所幫助。

您可能感興趣的文章:
  • PHP pthreads v3下worker和pool的使用方法示例
  • PHP-FPM 設置多pool及配置文件重寫操作示例
  • PHP設計模式之建造者模式(Builder)原理與用法案例詳解
  • PHP設計模式之策略模式(Strategy)入門與應用案例詳解
  • PHP設計模式之單例模式入門與應用詳解
  • PHP設計模式之觀察者模式入門與應用案例詳解
  • php設計模式之單例模式用法經典示例分析
  • php設計模式之觀察者模式定義與用法經典示例
  • 淺談PHP設計模式之對象池模式Pool

標簽:宜賓 南陽 湛江 黃南 銅川 鎮江 婁底 寶雞

巨人網絡通訊聲明:本文標題《PHP設計模式之適配器模式(Adapter)原理與用法詳解》,本文關鍵詞  PHP,設計模式,之,適配器,;如發現本文內容存在版權問題,煩請提供相關信息告之我們,我們將及時溝通與處理。本站內容系統采集于網絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《PHP設計模式之適配器模式(Adapter)原理與用法詳解》相關的同類信息!
  • 本頁收集關于PHP設計模式之適配器模式(Adapter)原理與用法詳解的相關信息資訊供網民參考!
  • 推薦文章
    主站蜘蛛池模板: 张柏芝B大毛又多又长| 嗯啊哦哈| 将夜西瓜视频免费观看| 久久永久免费| 天久久久噜噜噜久久国产精品爽爽| 欧美a级网站| 女女互慰刺激小说| 琪琪精品视频在线观看| japanese18日本护士xxxx| A片毛片视频三亚私人| ai明星造梦网站| 成人羞羞动漫| 男男往下面灌牛奶play视频| 国产欧美一二三无码视频| 日本成年网| 欧美在线高清视频播放免费| 嗯啊不要男男| 欲色天天婬香婬色综合网| 男女XXOO做爰猛烈gif动图| 萌白酱甜味弥漫白浆vip官方| xxx黄色片| 男女亲吻摸下面胸视频| 爆乳j罩杯超乳AV在线| 精品久久久| 外国大片又大又好看的PPT| 全是肉的高H文〈男男〉| 一级国产a级a毛片无卡| 99久久er这里只有精品18| 一级作爱视频免费观看| 久久久久精品| 少妇真人直播免费视频| 歪歪漫画免费漫画页面在线看漫画免费观看 | 床伴小说| jzzijzzij亚洲成熟丰满少妇| 三浦恵子AV在线观看| 精品国产一区二区三区久久影院| 女仆扒开腿秘?让人桶爽的动漫| 国产伦精品一区二区三区三免费 | 毛片基地美国| 日产a在线播放| 国产毛片A级久久久不卡精品|