PHP程序员站--PHP编程开发平台
 当前位置:主页 >> PHP高级编程 >> 高级应用 >> 

PHP设计模式介绍 第十三章 适配器模式

PHP设计模式介绍 第十三章 适配器模式

来源:互联网  作者:  发布时间:2010-05-22
接口的改变,是一个需要程序员们必须(虽然很不情愿)接受和处

接口的改变,是一个需要程序员们必须(虽然很不情愿)接受和处理的普遍问题。程序提供者们修改他们的代码;系统库被修正;各种程序语言以及相关库的发展和进化。我孩子的无数玩具中有一个简要地描述了这个两难局面:你无法合理安排一个不得其所的人。

问题

你如何避免因外部库的API改变而带来的不便?假如你写了一个库,你能否提供一种方法允许你软件的现有用户进行完美地升级,即使你已经改变了你的API?为了更好地适宜于你的需要,你应该如何改变一个对象的接口?

解决方案

适配器(Adapter)模式为对象提供了一种完全不同的接口。你可以运用适配器(Adapter)来实现一个不同的类的常见接口,同时避免了因升级和拆解客户代码所引起的纠纷。

考虑一下当(不是假设!)一个第三方库的API改变将会发生什么。过去你只能是咬紧牙关修改所有的客户代码,而情况往往还不那么简单。你可能正从事一项新的项目,它要用到新版本的库所带来的特性,但你已经拥有许多旧的应用程序,并且它们与以前旧版本的库交互运行地很好。你将无法证明这些新特性的利用价值,如果这次升级意味着将要涉及到其它应用程序的客户代码。

注:控制体模式

    适配器(Adapter)模式是控制体模式的最新范例。一个适配器(Adapter)的结构类似于代理服务器(Proxy)和修饰器(Decorator),而它们的不同之处在于,适配器(Adapter)的目的是改变封装类的接口,代理服务器(Proxy)和修饰器(Decorator)则是保持接口不变。

样本代码

让我们看看当API改变时,如何保护应用程序不受影响。

假设你费尽心思寻找合适的库,最后终于找到了HwLib,一个(假设的)被设计用来发送信息的代码集。

下面是HwLib类的源代码:

//  PHP4
/**
*  the  HwLib  helps  programmers  everywhere  write  their  first  program
*  @package  HelloWorld
*  @version  1
*/
class  HwLib  {
/**
*  Say  “Hello”
*  @deprec    this  function  is  going  away  in  the  future
*  @return    string
*/
function  hello()  {
return  ‘Hello  ‘;
}
/**
*  target  audience
*  @return    string


*/
function  world()  {
return  ‘World!’;
}
}
 
下面是库运行的范例:

$hw  =&  new  HwLib;
echo  $hw->hello(),  $hw->world();

HwLib有完备的说明文档。在文档中作者已经明确指出hello()方法会在未来的版本中不被支持(甚至淘汰)。

接下来,现在假设第二版的HwLib已经发布。一个全新的greet()方法代替了hello()。

下面是这个库的新版本(注释已被抽取掉):

//  version  2
class  HwLib  {
function  greet()  {
return  ‘Greetings  and  Salutations  ‘;
}
unction  world()  {
return  ‘World!’;
}
}

为了适应HwLib的不同版本进行编码,先进行一些基于第一版本HwLib接口的测试:

class  AdapterTestCase  extends  UnitTestCase  {
function  TestOriginalApp()  {
$lib  =&  new  HwLib;
$this->assertEqual(
‘Hello  World!’
,$lib->hello().$lib->world());
}
}

你同样可以表明,对这个库的简单升级将造成此应用程序的失效。

class  AdapterTestCase  extends  UnitTestCase  {
function  TestOriginalAppWouldFail()  {
$lib  =&  new  HwLib;  //  now  using  HwLib  version  2
$this->assertFalse(method_exists($lib,  ‘hello’));
}
}

(这个测试以method_exists()为例证。如果你简单地更换这个库的第二版本并且以TestOriginalApp()的测试再次运行AdapterTestCase,PHP就会运行失败,同时报告“致命错误:未定义的函数:hello()”)

针对API“升级”的解决办法就是创建一个适配器(Adapter)。

第一步是获得第二版本HwLib的实例的一个引用,并且把它加入到你的Adapter类中。

class  HwLibV2ToV1Adapter  {
var  $libv2;
function  HwLibV2ToV1Adapter  (&$libv2)  {
$this->libv2  =&  $libv2;
}
}

这个范例展示了将这个实例传递给构造函数的过程,你也可以运用Factory 或 Singleton ,或者其它适合你要求的创建模式,来创建一个新的实例。(通过前两章,你应该对HwLibV2ToV1Adapter的编写用途很熟悉了)


延伸阅读:
从魔兽看PHP设计模式
《PHP设计模式介绍》导言
PHP设计模式介绍 第一章 编程惯用法
PHP设计模式介绍 第二章 值对象模式
PHP设计模式介绍 第三章 工厂模式
PHP设计模式介绍 第四章 单件模式
PHP设计模式介绍 第五章 注册模式
PHP设计模式介绍 第六章 伪对象模式
PHP设计模式介绍 第七章 策略模式
PHP设计模式介绍 第八章 迭代器模式


PHP设计模式介绍 第九章 观测模式
PHP设计模式介绍 第十章 规范模式
PHP设计模式介绍 第十一章 代理模式
PHP设计模式介绍 第十二章 装饰器模式
最新文章
推荐阅读
月点击排行榜
PHP程序员站 Copyright © 2007-2010,PHPERZ.COM All Rights Reserved 粤ICP备07503606号