1、什么是适配器模式
适配器模式:将一个类的接口,转换成客户端 期望的另一个接口。适配器让原本接口不兼容的类可以合作无间。
这个模式可以通过创建适配器进行接口转换,让不兼容的接口变成兼容。可以让客户端从从实现的接口解耦,如果在一段时间后,想要改变接口,适配器可以将改变的部分封装起来,客户端就不必为了应对不同的接口而每次跟着改变。
2. 适配器模式的结构
请先看类图:
(对象适配器)
(类适配器)
他有如下几个角色:
目标角色(Target):这是所期待得到接口
源角色(Adaptee):这是需要适配的接口
适配器角色(Adaper):这是本模式的核心类。适配器把源接口转换成目标接口
下面请看代码分析:
类适配器:
目标角色(Target):
//目标角色(Target)
public interface Target {
void specificMethod();
}
源角色(Adaptee):
//源角色(Adaptee)
public class Adaptee {
public void adapteeMethod(){};
}
适配器角色(Adaper):
//适配器角色(Adapter)
public class Adapter extends Adaptee implements Target{
/**
* 由于源类Adaptee没有方法specificMethod()
* 因此适配器补充上这个方法
*/
@Override
public void specificMethod() {
//do something
}
}
这就是一个简单的类适配器模式的案例,下面演示一个实际问题:
我们都知道,如果要用java自带的方式实现一个观察者模式,那么观察者就必须要实现Observer接口,那么如果现在要将 HashMap作为观察者应该怎么办哪?
这时候就可以用到适配器了:
public class HashMapAdapter extends HashMap implements Observer {
@Override
public void update(Observable o, Object arg) {
//当观察者状态改变时
super.clear();
}
}
我们先写一个HashMapAdapter 的适配器角色,然后使其继承HashMap,并实现Observer接口,这样就成为了一个HashMap的观察者。当被观察者状态改变时,就清空HashMap。
看完了类适配器,然后我们来看一下对象适配器吧:
目标角色(Target):
//目标角色(Target)
public interface Target {
void specificMethod();
}
源角色(Adaptee):
//源角色(Adaptee)
public class Adaptee {
public void adapteeMethod(){};
}
目标角色和源角色都未变,改变的是适配器角色:
适配器角色(Adaper):
public class Adapter{
private Adaptee adaptee ;
public Adapter(Adaptee adaptee){
this.adaptee = adaptee;
}
/**
* 源类Adaptee有方法adapeeMethod
* 因此适配器类直接委派即可
*/
public void adapeeMethod(){
this.adaptee.adapteeMethod();
}
/**
* 源类Adaptee没有方法specificMethod
* 因此由适配器类需要补充此方法
*/
public void specificMethod(){
// do something
}
}
可以看到,在这里,我们用了组合的模式,而在类适配器里,我们使用的是继承的模式。
3. 两种方式的比较
对于这两种方式的比较,我想用一段有趣的对话来说明:
4. 缺省适配模式
缺省适配模式为一个接口提供缺省实现,这样子类型就可以从这个缺省实现进行扩展。从而不必从原来的接口进行扩展。
缺省适配器的作用:当我们的接口设计得过大,而子类不需要实现某些方法时(由于java中类必须实现接口中的所有方法),就会用到缺省适配器模式。
public interface People {
public void say();
public void eat();
public void walk();
}
public class DefaultAdapter implements People {
@Override
public void say() {
}
@Override
public void eat() {
}
@Override
public void walk() {
}
}
public class Child extends DefaultAdapter {
public void say(){
System.out.println("ya ya");
};
public void eat(){
System.out.println("ba ji ba ji");
};
}
在这里,有一个People的接口,定义了三个方法 eat(), say(), walk(),现在有一个小孩子,由于小孩子是一个人,所以需要实现People接口,但是小孩子还不会走路,所以,这时候就需要缺省适配器,用来覆盖不需要的方法,而子类只需要继承适配器就行了。
5.结束语
最后,我们应该明确的一点就是:适配器模式是补救措施,所以在系统设计过程中不应该使用这个设计模式,这个模式只是在你无可奈何时的补救方式。