`

美中不足的适配器模式(adapter pattern)

阅读更多

之前买过个ipad玩,当用其充电器充电时遇到了点麻烦(有的同学应该知道),家里没有适合它的插座。还好,卖家送了个接头转换部件,问题轻松解决。这就是适配器的作用。

<?php
interface IUserInfo{
	public function getUserName();
	public function getUserId();
	public function getUserInfo();
}

class UserInfo implements IUserInfo{
	public function getUserId() {
		return 123;
	}
	public function getUserName() {
		return 'XXXX';
	}
	public function getUserInfo() {
		return array( 'userId' => 123, 'userName' => 'XXXX' );
	}
}

interface IOuterUser{
	public function getOutUserId();
	public function getOutUserName();
	public function getOutUserInfo();
}

class OutUser implements IOuterUser{
	public function getOutUserId() {
		return array( 'id' => 111 );
	}
	public function getOutUserName() {
		return array( 'name' => 'OOOO' );
	}
	public function getOutUserInfo() {
		return array( 'id' => 111, 'name' => 'OOOO' );
	}
}
?>

看下这段代码,有两个获取用户信息的接口,一个内部,一个外部,可以发现,两个接口的实现类的返回类型有完全不同。好比,现在内部的接口就是“插座”,外部的接口就是ipad,现在需要一个“适配器”将这个外部的接口给转化成内部的。类图如下:



 OutUserInfo就是我的适配器,代码如下:

class OutUserInfo extends OutUser implements IUserInfo{
	public function getUserId() {
		$return = $this->getOutUserId();
		return $return['id'];
	}
	public function getUserName() {
		$return = $this->getOutUserName();
		return $return['name'];
	}
	public function getUserInfo() {
		$userInfo = $this->getOutUserInfo();
		return array( 'userId' => $userInfo['id'], 'userName' => $userInfo['name'] );
	}
}
$outUserInfo = new OutUserInfo();
var_dump( $outUserInfo->getUserId() );
var_dump( $outUserInfo->getUserName() );
var_dump( $outUserInfo->getUserInfo() );
运行结果:
int(111)
string(4) "OOOO"
array(2) {
  ["userId"]=>
  int(111)
  ["userName"]=>
  string(4) "OOOO"
}
[Finished in 0.3s]

 

有人会问,为什么不让内部的转化成外部的?相像一下,你家里现在所有的插座都是只能插两角的(ipad是三角的),现在全部转化成三角,那手机等等其他用两角的怎么充电?

 

 

适配器模式的定义

将一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。适配器模式由三个角色构成:

1、Target目标角色

该角色定义把其他类转换为何种接口,也就是我们的期望接口,例子中的IUserInfo接口中就是目标角色。

2、Adaptee源角色

就是被转换的角色。例子中的OutUser

3、Adapter适配器角色

适配器的核心角色,其他的两个角色都是已经存在的角色,而适配器角色是需要新建立的,它的职责非常简单,把源角色转换为目标角色。

 

 

适配器模式的优点

1、适配器模式可以让两个没有任何关系的类在一起运行,只要适配器这个角色能够搞定他们就成。

2、增加了类的透明性

想想看,我们访问的Target目标角色,但是具体的实现都委托给了源角色,而这些对高层次模块是透明的,也是它不需要关心的。

3、提高了类的复用度

4、灵活性非常好

某天,我的ipad坏了,扔了,因此适配器拔掉就可以了。太方便了

 

 

适配器模式的使用场景

适配器模式的应用场景只要记住一点就足够了:你有动机修改一个已经上线的接口时,适配器模式可能是最适合你的模式。

 

 

适配器模式的注意事项

适配器模式最好在详细设计阶段不要考虑它,它不是为了解决还处在开发阶段的问题,而是解决正在服役的项目问题,没有一个系统分析师会在做详细设计的时候考虑使用适配器模式,这个模式使用的主要场景是扩展应用中。项目一定要遵守依赖倒置原则里氏替换原则,否则即使在适合使用适配器的场合下,也会带来非常大的改造。

 

 

适配器模式的扩展

上面的例子是比较幸运的情况,试想一下,如果外部不是一个接口,而是多个,该如何?

 

<?php
interface IUserInfo{
	public function getUserName();
	public function getUserId();
}

class UserInfo implements IUserInfo{
	public function getUserId() {
		return 123;
	}
	public function getUserName() {
		return 'XXXX';
	}
}

interface IOuterUserId{
	public function getOutUserId();
}
interface IOuterUserName{
	public function getOutUserName();
}
class OutUserId implements IOuterUserId{
	public function getOutUserId() {
		return array( 'id' => 111 );
	}
}
class OutUserName implements IOuterUserName{
	public function getOutUserName() {
		return array( 'name' => 'OOOO' );
	}
}
?>

 代码所示,现外部是由两个接口组成,我们知道无论是java还是php都是不支持多继承的!既然这样,那就用类关联吧。

 

 


 适配器代码:

 

class OutUserInfo implements IUserInfo{
	private $outUserid = null;
	private $outUserName = null;
	public function __construct($outUserid,$outUserName){
		$this->outUserid = $outUserid;
		$this->outUserName = $outUserName;
	}
	public function getUserId() {
		$return = $this->outUserid->getOutUserId();
		return $return['id'];
	}
	public function getUserName() {
		$return = $this->outUserName->getOutUserName();
		return $return['name'];
	}
}
$outUserid = new OutUserId();
$outUserName = new OutUserName();
$outUserInfo = new OutUserInfo($outUserid,$outUserName);
var_dump( $outUserInfo->getUserId() );
var_dump( $outUserInfo->getUserName() );
运行结果:
int(111)
string(4) "OOOO"
[Finished in 0.1s]

 这种适配器叫做对象适配器,而上面的例子则是类适配器。

 

类适配器是类间继承,对象适配器是对象的合成关系,也可以说是类的关联关系。

 

 

适配器模式是一个补偿模式,通常用来解决接口不相容的问题,在百分之百的完美设计中是不可能使用到的,但真的有百分之百的完美设计吗?因此我们需要这么这种补偿方式来处理这完美中的不足!

 

 

 

  • 大小: 5 KB
  • 大小: 8 KB
2
1
分享到:
评论
2 楼 home198979 2014-04-18  
aimarcby 写道
适配器的英文是adapter,标题单词拼写有误哈。
不过瑕不掩瑜,挺好的。

多谢提醒,已修正
1 楼 aimarcby 2014-04-18  
适配器的英文是adapter,标题单词拼写有误哈。
不过瑕不掩瑜,挺好的。

相关推荐

    Windows 7美中不足的地方有哪些?.docx

    Windows 7美中不足的地方有哪些?.docx

    Jquery之美中不足小结

    在QWrap群里讨论时,有同学问jquery/yui等已做到极致,我们有没必要再重复造一个叫QWrap的轮子?

    数据库模型设计.doc

    看过之后深受启发,同时也感到两点美中不足: 1、这两部书的成书时间较早,且原作内容是基于美国企业的业务需求而建,有些最新 的行业信息及"中国特色"的东西没有收录。 2、书中原作者所使用的设计符号是作者专用的...

    Html Help WorkShop建议教程

    由于chm帮助文件是基于HTML文件特征的,所以前期...主题文件可以用任何一个HTML编辑器进行编辑,也可用HTML Help Workshop编辑,唯一美中不足的是它的编辑器是纯文字模式,对于HTML文件而言不具备所见即所得的效果。

    Android中解决RecyclerView各种点击事件的方法

    自从Google推出了RecyclerView之后,便可以完全取代ListView,个人感觉唯一的美中不足是对于itemView的各种点击事件不够完美。观点只代表个人看法。应最近项目需求实现itemView的子项点击事件,便写篇博客记录一下,...

    贪吃蛇源码

    这是用Codeblocks平台,使用了WxWidgets跨平台开发库,写的贪吃蛇的代码,具备了基本的模式,美中不足是关卡的设计和美工的设计不好了,但是框架具备了。

    什么是VLAN

    这种基于工作流的分组模式,大大提高了网络规划和重组的管理功能。在同一个VLAN中的工作站,不论它们实际与哪个交换机连接,它们之间的通讯就好象在独立的交换机上一样。同一个VLAN中的广播只有VLAN中的成员才能听到...

    强大的图片颜色抓取工具 拾色器 颜色选择器

    美中不足是需要 AIR 平台,这对做设计的人来说不算事儿,否则的话。。。就显得不那么随心了。 Dorado 是一款用起来比 MarkMan 更方面更灵活的标注工具。 Dorado 就更方便一些了,只有一个文件,运行起来就可以用了...

    Mybatis 增强工具 MyBatis-Plus

    Mybatis 的基础使用方式,其中有一部分美中不足的是 Mybatis 本身并未提供分页功能,还需要我们自己手动添加 PageHelper 插件或者自己实现分页的工具类,并且对单表的操作并不友好,简单的 insert 、 update 、 ...

    利用GUI简单实现贪吃蛇小游戏

    这个贪吃蛇项目实现了简单的GUI界面和键盘监听用户交互,美中不足是比较简陋,而且不是完全的面向对象项目。由于经验与理解尚不足,我暂时没有能力将它更加完善。如果您有好的意见,欢迎与我联系。 代码包中包含所...

    【Imageglass】支持70多种格式的开源无边框图片查看器

    可调整为无边框,如下(新版8.0比起旧版有个美中不足的地方,就是在无边框的情况下不能自由缩放窗口,必须退出无边框才行) 可以更换软件和图标皮肤(20来款),我这边加载奇慢,下载这些倒都是没问题的,有加速器...

    fullPage全屏滚动视差切换效果(兼容IE7及以上版本

    都很漂亮,美中不足的就是兼容性较差 今天给大家推荐的这款可以兼容IE 7以及以上版本,非常适合企业类的网站使用 使用方法: 1、将head中的样式引入到你的网页中 2、将body里的代码部分拷贝到你...

    Android平台上的蓝牙串口调试助手安装包(.apk)

    推荐一款在Android平台上的蓝牙串口调试助手,完全纯净无广告,想要的调试功能都有,唯一美中不足的就是不支持设置字符编码、发送新行,但这完全无大碍,比应用市场里下载的一大片广告好多了。 资源来源于我之前看的...

    asqare_llk_5_src

    美中不足的是生成后的jar文件不能正常读写文件。 如果觉得下载该资源花费积分过高,可以去(免积分)下载asqare_llk_5_jar文件,那个文件是该游戏的jar文件,下载运行看看该资源值不值10积分。 如果下载此文件,记得给...

    pdg文件阅读器-PdgThumbViewer

    box view,很不错,文件不大,但功能很全,但美中不足有时打开文件会出现黑条…… PdgThumbViewer,这个不错,够小,够简单。但就是没有放大缩小的功能,好在能全屏,凑合用好了! --TTT BLOG

    使用ashx进行XML转Tree的增删改查操作

    但是美中不足就是体积太大,前不久做项目的时候遇到这个问题,恰好发现里面一个压缩过的 Ext.js只有200K,但是已经能够构建一个完整的ExtTree,于是就花了点时间把它改造成一个xml To ExtTree的这样一个小控件,分享...

    Qt 中实现任意阶贝塞尔曲线绘制 & 动态调节

    然而,美中不足的是,Qt 的贝塞尔曲线只支持二次和三次,对于更高阶的似乎就无能为力了。 即便多个 quadTo() 或 cubicTo() 连用的效果也非常不理想。 因此,我想到利用贝塞尔的公式生成曲线点,然后用直线来连接,...

    浅谈Java的输入输出流

     Java语言的输入输出功能是十分强大而灵活的,美中不足的是看上去输入输出的代码并不是很简洁,因为你往往需要包装许多不同的对象。在Java类库中,IO部分的内容是很庞大的,因为它涉及的领域很广泛:标准输入输出,...

Global site tag (gtag.js) - Google Analytics