现实中的问题
有一个插座,这个插座是三个口的,但是我们手上只有两个触角的插头,一种笨方法就是直接强行把两个触角掰弯,插进去(这种事情我就做过),还有一种方法就是找一个转换头来。
看下面一张图就大概明白了,很明显现有系统很难和厂商提供的匹配,该怎么做呢?那么适配器这是就派上用场了
定义
将一个类的接口,转换成客户期望的另一个接口。适配器让原本接口不兼容的类可以合作无间。
接着上面问题
这个模式可以通过创建适配器进行接口转换,让不兼容的接口变成兼容。这可以让客户从实现的接口解耦。如果在一段时间之后,我们想要改变接口,适配器可以将改变的部分封装起来,客户就不必为了应对不同的接口每次跟着修改。
类图如下:
如上适配器类图包含的OO设计原则:使用对象组合,以修改的接口包括被适配者:这种做法还有额外的优点,那就是,被适配者的任何子类都可以搭配着适配者使用
代码具体实现
1 、首先我们需要一个目标接口,也就是我们上面提到的三个口的插头
target 目标
package Adapter;
public interface ThreeInterface {
public void OfferPowerForThree(); //三个口的插头有 一 个 功能,能够为三个触角的插头提供电源
}
2、其次我们需要被适配者,也就是两个触角的插头
package Adapter;
public interface TwoInterface {
public void OfferPowerForTwo();//两个口的插头有一个功 能,能够为两个触角的插头提供电源
}
实现:
package Adapter;
public class RealTwo implements TwoInterface{
@Override
public void OfferPowerForTwo() {
// TODO Auto-generated method stub
System.out.println("我可以为两个触角的插头提供电源!");
}
}
3、需要一个适配器
package Adapter;
public class ThreeToTwoAdapter implements ThreeInterface {
TwoInterface twoInterface;
public ThreeToTwoAdapter(TwoInterface twoInterface)
{
this.twoInterface=twoInterface;
}
@Override
public void OfferPowerForThree() {
// TODO Auto-generated method stub
twoInterface.OfferPowerForTwo();
}
}
4、需要一个场景,这个场景下面,没有被是适配者可以直接用的资源,需要适配器进行转换,在上面的例子中也就是有一个两个触角的插头三十没用可以用的两个口的插座。
package Adapter;
public class Test {
//现在这快地方只有 三个口 的 插 座 ,但是插头是两个触角的,需要一个适配器
public static void main(String []args)
{
//1、熟悉定义一个两个触角的插头,这个是本来自带的
TwoInterface twoInterface=new RealTwo();
//2、定义一个适配器,使得三个口的插座可以为两个触角的插头提供电源
ThreeInterface threeInterface=new ThreeToTwoAdapter(twoInterface);
//3、提供电源
threeInterface.OfferPowerForThree();
}
}
类适配器模式
上面提到的其实成为对象适配器模式,还有一种称为类适配器模式,下面来看看类适配器模式:
类图
类图和对象适配器有点类似,唯一的差别就在于类适配器继承了Target和Adaptee
适配器模式的优缺点
优点
- 将目标类和适配者类解耦,通过引入一个适配器类来重用现有的适配者类,而无须修改原有代码。
- 增加了类的透明性和复用性,将具体的实现封装在适配者类中,对于客户端类来说是透明的,而且提高了适配者的复用性。
- 灵活性和扩展性都非常好,通过使用配置文件,可以很方便地更换适配器,也可以在不修改原有代码的基础上增加新的适配器类,完全符合“开闭原则”。
类适配器模式还具有如下优点:
- 由于适配器类是适配者类的子类,因此可以在适配器类中置换一些适配者的方法,使得适配器的灵活性更强。
对象适配器模式还具有如下优点:
- 一个对象适配器可以把多个不同的适配者适配到同一个目标,也就是说,同一个适配器可以把适配者类和它的子类都适配到目标接口。
缺点
类适配器模式的缺点如下: 对于Java、C#等不支持多重继承的语言,一次最多只能适配一个适配者类,而且目标抽象类只能为抽象类,不能为具体类,其使用有一定的局限性,不能将一个适配者类和它的子类都适配到目标接口。
对象适配器模式的缺点如下: 与类适配器模式相比,要想置换适配者类的方法就不容易。如果一定要置换掉适配者类的一个或多个方法,就只好先做一个适配者类的子类,将适配者类的方法置换掉,然后再把适配者类的子类当做真正的适配者进行适配,实现过程较为复杂。