<?php include_once('EuroAdapter.php'); include_once('DollarCalc.php'); class Client { public function __construct() { $euro = ''; echo "区元: $euro" . $this->makeApapterRequest(new EuroAdapter()) . '<br />'; echo "美元: $: " . $this->makeDollarRequest(new DollarCalc()) . '<br />'; } private function makeApapterRequest(ITarget $req) { return $req->requestCalc(40,50); } private function makeDollarRequest(DollarCalc $req) { return $req->requestCalc(40,50); } } $woker = new Client();
运行结果如下:
Euros: 72.999
Dollars: $: 90
可以看到,美元和欧元都可以处理, 这就是适配器模式的方便之处.
这个计算很简单, 如果是针对更为复杂的计算, 继承要提供建立类适配器的Target接口的必要接口和具体实现
使用组合的适配器模式
对象适配器模式使用组合而不是继承, 不过它也会完成同样的目标. 通过比较这两个版本的适配器模式, 可以看出它们各自的优缺点. 采用类适配器模式时,适配器可以继承它需要的大多数功能, 只是通过接口稍微调. 在对象适配器模式中 适配器(Adapter)参与使用被适配者(Adaptee), 并实现Target接口. 在类适配器模式中, 适配器(Adapter)则是一个被适配者(Adaptee), 并实现Target接口.
示例: 从桌面环境转向移动环境
PHP程序员经常会遇到这样一个问题:需要适应移动环境而做出调整.不久之前,你可能只需要考虑提供一个网站来适应多种不同的桌面环境. 大多数桌面都使用一个布局, 再由设计人员让它更美观. 对于移动设备, 设计人员和开发人员不仅需要重新考虑桌面和移动环境中页面显示的设计元素, 还要考虑如何从一个环境切换到另一个环境.
首先来看桌面端的类Desktop(它将需要一个适配器). 这个类使用了一个简单但很宽松的接口:
IFormat.php
<?php interface IFormat { public function formatCSS(); public function formatGraphics(); public function horizontalLayout(); }
它支持css和图片选择, 不过其中一个方法指示一种水平布局, 我们知道这种布局并不适用小的移动设备.下面给出实现这个接口的Desktop类
Desktop.php
<?php include_once('IFormat.php'); class Desktop implements IFormat { public function formatCSS() { echo "引用desktop.css<br />"; } public function formatGraphics() { echo "引用desktop.png图片<br />"; } public function horizontalLayout() { echo '桌面:水平布局'; } }
问题来了, 这个布局对于小的移动设备来说太宽了. 所以我们的目标是仍采用同样的内容, 但调整为一种移动设计.
下面来看移动端的类Mobile
首先移动端有一个移动端的接口
IMobileFormat
<?php interface IMobileFormat { public function formatCSS(); public function formatGraphics(); public function verticalLayout(); }
可以看到, IMobileFormat接口和IFormat接口是不一样的,也就是不兼容的, 一个包含了方法horizontalLayout(), 另一个包含方法verticalLaout(), 它们的差别很小, 最主要的区别是: 桌面设计可以采用水平的多栏布局, 而移动设计要使用垂直布局,而适配器就是要解决这个问题
下面给出一个实现了IMoibleFormat接口的Mobile类
Mobile.php
<?php include_once('IMobileFormat.php'); class Mobile implements IMobileFormat { public function formatCSS() { echo "引用mobile.css<br />"; } public function formatGraphics() { echo "引用mobile.png图片<br />"; } public function verticalLayout() { echo '移动端:垂直布局'; } }
Mobile类和Desktop类非常相似, 不过是图片和CSS引用不同
接下来,我们需要一个适配器,将Desktop和Mobile类结合在一起
MobileAdapter.php
<?php include_once('IFormat.php'); include_once('Mobile.php'); class MobileAdapter implements IFormat { private $mobile; public function __construct(IMobileFormat $mobileNow) { $this->mobile = $mobileNow; } public function formatCSS() { $this->mobile->formatCSS(); } public function formatGraphics() { $this->mobile->formatGraphics(); } public function horizontalLayout() { $this->mobile->verticalLayout(); } }