您的位置:首页 > 其它

设计模式-适配器模式

2016-08-15 19:28 197 查看

适配器定义:

适配器模式(Adapter Pattern) :将一个接口转换成客户希望的另一个接口,适配器模式使接口不兼容的那些类可以一起工作,其别名为包装器(Wrapper)。适配器模式既可以作为类结构型模式,也可以作为对象结构型模式。

角色介绍 

目标(Target)角色:这就是所期待得到的接口。注意:由于这里讨论的是类适配器模式,因此目标不可以是类。

源(Adapee)角色:现在需要适配的接口。

适配器(Adaper)角色:适配器类是本模式的核心。适配器把源接口转换成目标接口。显然,这一角色不可以是接口,而必须是具体类。

分类:

类适配器和对象适配器

类适配器:



具体实现:

类适配器模式

/**
* Target角色
*/
public interface FiveVolt {
public int getVolt5();
}


/**

* Adaptee角色,需要被转换的对象

*/

public class Volt220 {
public int getVolt220() {
return 220;
}
}


// adapter角色

public class ClassAdapter extends Volt220 implements FiveVolt {

@Override
public int getVolt5() {
return 5;
}

}


  Target角色给出了需要的目标接口,而Adaptee类则是需要被转换的对象。Adapter则是将Volt220转换成Target的接口。对应的是Target的目标是要获取5V的输出电压,而Adaptee即正常输出电压是220V,此时我们就需要电源适配器类将220V的电压转换为5V电压,解决接口不兼容的问题。

public class Test {
public static void main(String[] args) {
ClassAdapter adapter = new ClassAdapter();
System.out.println("输出电压 : " + adapter.getVolt5());
}
}


对象适配器:



对象适配器的具体实现

 与类的适配器模式一样,对象的适配器模式把被适配的类的API转换成为目标类的API,与类的适配器模式不同的是,对象的适配器模式不是使用继承关系连接到Adaptee类,而是使用代理关系连接到Adaptee类。

     Adaptee类 ( Volt220 ) 并没有getVolt5()方法,而客户端则期待这个方法。为使客户端能够使用Adaptee类,需要提供一个包装类Adapter。这个包装类包装了一个Adaptee的实例,从而此包装类能够把Adaptee的API与Target类的API衔接起来。Adapter与Adaptee是委派关系,这决定了适配器模式是对象的。

示例代码如下 :

/**

* Target角色

*/

public interface FiveVolt {
public int getVolt5();
}


/**

* Adaptee角色,需要被转换的对象

*/

public class Volt220 {
public int getVolt220() {
return 220;
}
}


// 对象适配器模式

public class ObjectAdapter implements FiveVolt {

Volt220 mVolt220;

public ObjectAdapter(Volt220 adaptee) {
mVolt220 = adaptee;
}

public int getVolt220() {
return mVolt220.getVolt220();
}

@Override
public int getVolt5() {
return 5;
}

}


注意,这里为了节省代码,我们并没有遵循一些面向对象的基本原则。

使用示例 :

public class Test {
public static void main(String[] args) {
ObjectAdapter adapter = new ObjectAdapter(new Volt220());
System.out.println("输出电压 : " + adapter.getVolt5());
}
}


模式结构:

适配器模式包含如下角色:

Target:目标抽象类

Adapter:适配器类

Adaptee:适配者类

Client:客户类

适配器模式有对象适配器和类适配器两种实现:

对象适配器:



类适配器:



优点:

1.将目标类和适配者类解耦,通过引入一个适配器类来重用现有的适配者类,而无须修改原有代码。

2.增加了类的透明性和复用性,将具体的实现封装在适配者类中,对于客户端类来说是透明的,而且提高了适配者的复用性。

3.灵活性和扩展性都非常好,通过使用配置文件,可以很方便地更换适配器,也可以在不修改原有代码的基础上增加新的适配器类,完全符合“开闭原则”。

类适配器模式还具有如下优点:

由于适配器类是适配者类的子类,因此可以在适配器类中置换一些适配者的方法,使得适配器的灵活性更强。

对象适配器模式还具有如下优点:

一个对象适配器可以把多个不同的适配者适配到同一个目标,也就是说,同一个适配器可以把适配者类和它的子类都适配到目标接口。

缺点:

类适配器模式的缺点如下:

对于Java、C#等不支持多重继承的语言,一次最多只能适配一个适配者类,而且目标抽象类只能为抽象类,不能为具体类,其使用有一定的局限性,不能将一个适配者类和它的子类都适配到目标接口。

对象适配器模式的缺点如下:

与类适配器模式相比,要想置换适配者类的方法就不容易。如果一定要置换掉适配者类的一个或多个方法,就只好先做一个适配者类的子类,将适配者类的方法置换掉,然后再把适配者类的子类当做真正的适配者进行适配,实现过程较为复杂。

我的微信二维码如下,欢迎交流讨论



欢迎关注《IT面试题汇总》微信订阅号。每天推送经典面试题和面试心得技巧,都是干货!

微信订阅号二维码如下:



参考:
https://github.com/simple-android-framework-exchange/android_design_patterns_analysis/tree/master/adapter/mr.simple
http://design-patterns.readthedocs.io/zh_CN/latest/structural_patterns/adapter.html
http://www.cnblogs.com/java-my-life/archive/2012/04/13/2442795.html

<script type="text/javascript">
$(function () {
$('pre.prettyprint code').each(function () {
var lines = $(this).text().split('\n').length;
var $numbering = $('<ul/>').addClass('pre-numbering').hide();
$(this).addClass('has-numbering').parent().append($numbering);
for (i = 1; i <= lines; i++) {
$numbering.append($('<li/>').text(i));
};
$numbering.fadeIn(1700);
});
});
</script>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: