• 允许一个Adapter与多个Adaptee—即Adaptee本身以及它的所有子类(如果有子类的话)—同时工作。Adapter也可以一次给所有的Adaptee添加功能。
• 使得重定义Adaptee的行为比较困难。这就需要生成Adaptee的子类并且使得Adapter引用这个子类而不是引用Adaptee本身。
使用Adapter模式时需要考虑的其他一些因素有:
1) Adapter的匹配程度 对Adaptee的接口与Target的接口进行匹配的工作量各个Adapter可能不一样。工作范围可能是,从简单的接口转换(例如改变操作名 )到支持完全不同的操作集合。Adapter的工作量取决于Target接口与Adaptee接口的相似程度
2) 可插入的Adapter 当其他的类使用一个类时,如果所需的假定条件越少,这个类就更具可复用性。如果将接口匹配构建为一个类,
就不需要假定对其他的类可见的是一个相同的接口。也就是说,接口匹配使得我们可以将自己的类加入到一些现有的系统中去,
而这些系统对这个类的接口可能会有所不同。
3) 使用双向适配器提供透明操作 使用适配器的一个潜在问题是,它们不对所有的客户都透明。被适配的对象不再兼容 Adaptee的接口,
因此并不是所有 Adaptee对象可以被使用的地方它都可以被使用。双向适配器提供了这样的透明性。
在两个不同的客户需要用不同的方式查看同一个对象时,双向适配器尤其有用。
9. 实现
类适配器使用的是继承
让我们看看当API改变时,如何保护应用程序不受影响。
<?php
/**
* 类适配器模式
* @author guisu
*
*/
/**
* 目标角色
* @version 1.0
*/
class Target {
/**
* 这个方法将来有可能改进
*/
public function hello(){
echo 'Hello ';
}
/**
* 目标点
*/
public function world(){
echo 'world';
}
}
/**
* Client 程序
*
*/
class Client {
/**
* Main program.
*/
public static function main() {
$Target = new Target();
$Target->hello();
$Target->world();
}
}
Client::main();
?>
我们Target已经明确指出hello()方法会在未来的版本中改进,甚至不被支持或者淘汰。接下来,现在假设第二版的Target已经发布。一个全新的greet()方法代替了hello()。
<?php
/**
* 类适配器模式
* @author guisu
*
*/
/**
* 目标角色
* @version 2.0
*/
class Target {
/**
* 这个方法将来有可能继续改进
*/
public function greet(){
echo 'Greet ';
}
/**
* 目标点
*/
public function world(){
echo 'world';
}
}
如果我们继续使用原来的client代码,肯定会报错,找不到hello方法。
针对API“升级”的解决办法就是创建一个适配器(Adapter)。
