《PHP设计模式介绍》第十三章 适配器模式_PHP教程

编辑Tag赚U币
教程Tag:暂无Tag,欢迎添加,赚取U币!

推荐:《PHP设计模式介绍》第十二章 装饰器模式
若你从事过面向对象的php开发,即使很短的时间或者仅仅通过本书了解了一些,你会知道,你可以 通过继承改变或者增加一个类的功能,这是所有面向对象语言的一个基本特性。如果已经存在的一个php

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

问题

你如何避免因外部库的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设计模式介绍》第十一章 代理模式
因为某个对象消耗太多资源,而且你的代码并不是每个逻辑路径都需要此对象, 你曾有过延迟创建对象的想法吗 ( if和else就是不同的两条逻辑路径) ? 你有想过限制访问某个对象,也就是说,提供一组方法

共2页上一页12下一页
来源:模板无忧//所属分类:PHP教程/更新时间:2008-08-22
相关PHP教程