多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
[toc] ## 举个例子 > **身高不够鞋来凑** > 身材苗条、长像出众是每个人梦寐以求的,尤其是女孩子!但很多人却因为先天的原因并不能如意,这时就需要通过服装、化妆去弥补。 > 所谓美女,三分靠长相七分靠打扮!比如身高不够,就可以通过穿高跟鞋来弥补 > 这里的高跟鞋就起着一个适配的作用,能让你的形象增高四、五厘米 ## 代码实现 ```php <?php interface IHightPerson { public function getName(); public function getHeight(); } class HighPerson implements IHightPerson { protected $name; public function __construct($name) { $this->name = $name; } public function getName() { return $this->name; } public function getHeight() { return 170; } } class ShortPerson { protected $name; public function __construct($name) { $this->name = $name; } public function getName() { return $this->name; } public function getRealHeight() { return 160; } public function getShoeHeight() { return 6; } } class DecoratePerson extends ShortPerson { public function getHeight() { return parent::getRealHeight() + parent::getShoeHeight(); } } function canPlayReceptionist($person) { return $person->getHeight() >= 165; } function testPerson() { $lira = new HighPerson("Lira"); echo $lira->getName() . "身高" . strval($lira->getHeight()) . ",完美如你,天生的美女!"; $res = "是否适合做接待员:"; if (canPlayReceptionist($lira)) { echo $res . "符合"; } else { echo $res . "不符合"; } echo PHP_EOL; $demi = new DecoratePerson('Demi'); echo $demi->getName() . "身高" . strval($demi->getHeight()) . ",在高跟鞋的适配下,你身高不输高圆圆,气质不输范冰冰!"; if (canPlayReceptionist($demi)) { echo $res . "符合"; } else { echo $res . "不符合"; } } testPerson(); ``` ``` D:\soft\php72\php.exe D:\project\php_dp\index.php Lira身高170,完美如你,天生的美女!是否适合做接待员:符合 Demi身高166,在高跟鞋的适配下,你身高不输高圆圆,气质不输范冰冰!是否适合做接待员:符合 Process finished with exit code 0 ``` > 在上面的例子中,高跟鞋起着一个适配的作用,让其形象增高 5~7 厘米完全不在话下,而且效果立竿见影!使得一些女孩原本不符合接待员的真实身高,在鞋子的帮助下也能符合条件。 > 如高跟鞋一样,使原本不匹配某种功能的对象变得匹配这种功能,这在程序中叫做适配器模式。 ## 什么是适配模式 > 将一个类的接口变成客户端所期望的另一种接口,从而使原本因接口不匹配而无法一起工作的两个类能够在一起工作。 ## 适配器模式的作用: 1. 接口转换,将原有的接口(或方法)转换成另一种接口; 1. 用新的接口包装一个已有的类; 1. 匹配一个老的组件到一个新的接口。 ![](https://box.kancloud.cn/5c8502a68c7059790ff6369cb9428031_722x165.png) ![](https://box.kancloud.cn/0144f3a4d36379592a9da07455fbf4d1_722x157.png) ## 设计要点 > 配器模式中主要三个角色,在设计适配器模式时要找到并区分这些角色: 1. **目标(Target)**: 即你期望的目标接口,要转换成的接口。 1. **源对象(Adaptee)**: 即要被转换的角色,要把谁转换成目标角色。 1. **适配器(Adapter)**: 适配器模式的核心角色,负责把源对象转换和包装成目标对象。 ## 实战应用 > 有一个电子书阅读器的项目(Reader),研发之初,产品经理经过各方讨论,最后告诉我们只支持 TXT 和 Epub 格式的电子书。 > 然后经过仔细思考、精心设计,采用了如图1的代码架构。 > 在这个类图中,有一个阅读器的核心类 Reader,一个 TXT 文档的关键类 TxtBook(负责 TXT 格式文件的解析),和一个 Epub 文档的关键类 EpubBook(负责 Epub 格式文件的解析)。 ![](https://box.kancloud.cn/76cf45d19e0cd9f76ab79ab21a694c6c_542x342.png) 图1:阅读器类图 > 产品上线半年后,市场响应良好,业务部门反映:有很多办公人员也在用我们的阅读器,他们希望这个阅读器能同时支持 PDF 格式,这样就不用在多个阅读器神之间来回切换了, > 此时程序就需要增加对 PDF 格式的支持,而 PDF 并不是核心业务,我们不会单独为其开发一套 PDF 解析内核,而会使用一些开源的 PDF 库(我们称它为第三方库),如 MuPDF、TCPDF 等。而开源库的接口和我们的接口并不相同(如图2),返回的内容也不是我们直接需要的,需要经过一些转换才能符合我们的要求。 ![](https://box.kancloud.cn/118acc2a542701db9ce69570b9e755c5_209x175.png) 图2:第三方 PDF 解析库的类图 > 这时,我们就需要对 PDF 的解析库 MuPDF 进行适配。经过上面的学习,你一定知道这时该用适配器模式了,于是有了如下图3的类图结构。 ![](https://box.kancloud.cn/5c1c886330444017f9815b650f1c7a02_636x343.png) 图3:兼容 PDF 的类图结构