十六、适配器模式Adapter(结构型模式)
2016-05-03 14:44
246 查看
1、意图
什么是适配器,大家可能猛一下说不出来,那给大家举个简单的例子,用过港版手机的人都知道,那边的插板是三个大插头,那么回到大陆怎么使用两孔的插座呢,这时候我们就需要转换器了。这个转化器我们也叫作适配器,适配器模式,把一个类的接口变换成客户端所期待的另一种接口,从而使原本不匹配而无法在一起工作的两个,类能够在一起工作。
适配器模式分为类适配器模式和对象适配器模式。
关于类适配器模式,因为java的单继承,如果继承一个类,另外的则只能是接口,需要手动实现相应的方法。
2、结构图和代码
adapted类别的接口提供了SpecificRequest()函数,经由这个转接器转换为Taget类别的新接口,其提供了Request()函数给Client使用。Adapter将Adaptee的接口封装起来,而提供新的接口给Client,这样做的好处是:让Client依赖于新的接口,而不依赖于旧接口,一旦旧接口更改时,并不会影响到Client,因而创造了Adaptee类别的新陈代谢的自由度。
例子:
在我们有A插头是三口的,现在要实现插入两口的电源一起工作,此时我们需要一个中间的适配器,又称转换器来给A电源套上一个两口的插头。
A电源的连接功能
interface PowerA{
public void connect();
}
class PowerAImpl implements PowerA{
public void connect(){
System.out.println("电源A已连接,开始工作");
}
}
B电源的插入功能
interface PowerB{
public void insert();
}
class PowerBImpl implements PowerB{
public void insert(){
System.out.println("电源B已插入,开始工作");
}
}
现在我们可以理解为给A插头添加上一个B插头的插入功能。具体怎么实现呢,写一个适配器类,在其中使用到A的连接方法时添加上B的实现,代码实现如下:
class PowerAdapter implements PowerA{
private PowerB powerB; //被适配的接口
public PowerAdapter(PowerB powerB){
this.powerB = powerB;
}
public void connect(){
powerB.insert();
}
}具体调用如下:
代码写完了,我们来总结一下,如上:代码中总共有三个角色
1、源(Adapee)角色:需要适配的接口,也就是A插头
2、目标(Target)角色:这就是所期待得到的接口,即B插头
3、适配器(Adaper)角色:适配器类是本模式的核心。适配器把源接口转换成目标接口。显然,这一角色不可以是接口,而必须是具体类。
3、效果
--上面论述的主要是对象适配器,关于类适配器除了实现目标端口外,还要实现你要兼容的源类,这样可以少写几行代码,但是从组合优于继承的角度看,它总则没有那么的干净。
--对同一个适配器(即同一个对象)对同样的源进行双向甚至多向的适配,则能使其适用两个甚至多个客户调用。
适配器模式的优点
- 更好的复用性
系统需要使用现有的类,而此类的接口不符合系统的需要。那么通过适配器模式就可以让这些功能得到更好的复用。
- 更好的扩展性
在实现适配器功能的时候,可以调用自己开发的功能,从而自然地扩展系统的功能。
适配器模式的缺点
过多的使用适配器,会让系统非常零乱,不易整体进行把握。比如,明明看到调用的是A接口,其实内部被适配成了B接口的实现,一个系统如果太多出现这种情况,无异于一场灾难。因此如果不是很有必要,可以不使用适配器,而是直接对系统进行重构。
4、与代理模式的区别
代理模式是接口不变,但里面的内容改变。而适配器模式恰恰相反,接口改变,但内容不变。
什么是适配器,大家可能猛一下说不出来,那给大家举个简单的例子,用过港版手机的人都知道,那边的插板是三个大插头,那么回到大陆怎么使用两孔的插座呢,这时候我们就需要转换器了。这个转化器我们也叫作适配器,适配器模式,把一个类的接口变换成客户端所期待的另一种接口,从而使原本不匹配而无法在一起工作的两个,类能够在一起工作。
适配器模式分为类适配器模式和对象适配器模式。
关于类适配器模式,因为java的单继承,如果继承一个类,另外的则只能是接口,需要手动实现相应的方法。
2、结构图和代码
adapted类别的接口提供了SpecificRequest()函数,经由这个转接器转换为Taget类别的新接口,其提供了Request()函数给Client使用。Adapter将Adaptee的接口封装起来,而提供新的接口给Client,这样做的好处是:让Client依赖于新的接口,而不依赖于旧接口,一旦旧接口更改时,并不会影响到Client,因而创造了Adaptee类别的新陈代谢的自由度。
例子:
在我们有A插头是三口的,现在要实现插入两口的电源一起工作,此时我们需要一个中间的适配器,又称转换器来给A电源套上一个两口的插头。
A电源的连接功能
interface PowerA{
public void connect();
}
class PowerAImpl implements PowerA{
public void connect(){
System.out.println("电源A已连接,开始工作");
}
}
B电源的插入功能
interface PowerB{
public void insert();
}
class PowerBImpl implements PowerB{
public void insert(){
System.out.println("电源B已插入,开始工作");
}
}
现在我们可以理解为给A插头添加上一个B插头的插入功能。具体怎么实现呢,写一个适配器类,在其中使用到A的连接方法时添加上B的实现,代码实现如下:
class PowerAdapter implements PowerA{
private PowerB powerB; //被适配的接口
public PowerAdapter(PowerB powerB){
this.powerB = powerB;
}
public void connect(){
powerB.insert();
}
}具体调用如下:
public static void main(String[] args){ PowerA a = new PowerAImpl(); //connect(a); PowerB b = new PowerBImpl(); PowerAdapter pa = new PowerAdapter(b); connect(pa); } public static void connect(PowerA powerA){ powerA.connect(); }
代码写完了,我们来总结一下,如上:代码中总共有三个角色
1、源(Adapee)角色:需要适配的接口,也就是A插头
2、目标(Target)角色:这就是所期待得到的接口,即B插头
3、适配器(Adaper)角色:适配器类是本模式的核心。适配器把源接口转换成目标接口。显然,这一角色不可以是接口,而必须是具体类。
3、效果
--上面论述的主要是对象适配器,关于类适配器除了实现目标端口外,还要实现你要兼容的源类,这样可以少写几行代码,但是从组合优于继承的角度看,它总则没有那么的干净。
--对同一个适配器(即同一个对象)对同样的源进行双向甚至多向的适配,则能使其适用两个甚至多个客户调用。
适配器模式的优点
- 更好的复用性
系统需要使用现有的类,而此类的接口不符合系统的需要。那么通过适配器模式就可以让这些功能得到更好的复用。
- 更好的扩展性
在实现适配器功能的时候,可以调用自己开发的功能,从而自然地扩展系统的功能。
适配器模式的缺点
过多的使用适配器,会让系统非常零乱,不易整体进行把握。比如,明明看到调用的是A接口,其实内部被适配成了B接口的实现,一个系统如果太多出现这种情况,无异于一场灾难。因此如果不是很有必要,可以不使用适配器,而是直接对系统进行重构。
4、与代理模式的区别
代理模式是接口不变,但里面的内容改变。而适配器模式恰恰相反,接口改变,但内容不变。
相关文章推荐
- 调用百度API去生成短链接
- 五、SpringBoot JPA 配置redis
- 第十一周 阅读程序(5b)
- ViBe前景检测算法
- js 浏览器写coke
- springMVC post方式乱码解决方案
- 【转】一个域名对应多个IP地址,接下来系统是依据什么决定使用哪个IP地址的?
- Nagios 监控
- Nginx打开目录浏览功能(autoindex)
- top命令显示CPU使用率过了100%原因
- SDUT 2170 The Largest SCC
- ReactNative准备:环境的创建和应用
- DateGrid行变色—winform—pda
- CSU 1656 Paper of FlyBrother(后缀数组)
- Redis 起步
- 125. Valid Palindrome [easy] (Python)
- 图像去雾
- 4月29日 例1
- 侧滑菜单 drawerlayout 与 NavigationView
- Javascript 模块化编程(一):模块的写法