适配器模式
目的
将一个接口转换成用户希望的另一个接口,使接口不兼容的那些类可以一起工作,其别名为包装器(Wrapper)。
类图
角色
- Target:目标抽象类
- Adapter:适配器类
- Adaptee:适配者类
- Client:客户类
对象适配器
类适配器
-
在对象适配器模式中,适配器与适配者之间是关联关系;
-
在类适配器模式中,适配器与适配者之间是继承(或实现)关系,一般是指多重继承.
但 Java 等语言不支持多重继承,所以在实际开发中,大多是使用对象适配器。
实现
类适配器
//目标接口
interface Target
{
public void request();
}
//适配者接口
class Adaptee
{
public void specificRequest()
{
System.out.println("适配者中的业务代码被调用!");
}
}
//类适配器类
class ClassAdapter extends Adaptee implements Target
{
public void request()
{
specificRequest();
}
}
//客户端代码
public class ClassAdapterTest
{
public static void main(String[] args)
{
System.out.println("类适配器模式测试:");
Target target = new ClassAdapter();
target.request();
}
}
对象适配器
目标接口
先来个男孩、女孩。其中女孩可以嘤嘤嘤,男孩可以哈哈哈。但哪个男孩不想嘤嘤嘤呢,所以这里 Girl 就是咱们的目标类(接口)。
public interface Girl {
void yyy();
}
public interface Boy {
void hhh();
}
适配者类
男孩想嘤嘤嘤,那就需要女装,当一个女装大佬。
public class DressBoy implements Boy {
@Override
public void hhh() {
...
}
}
适配器类
接着就需要适配了,将男孩的哈哈哈适配成嘤嘤嘤
public class BoyAdapter implements Girl {
Boy boy;
public BoyAdapter(Boy boy) {
this.boy = boy;
}
@Override
public void yyy() {
boy.hhh();
}
}
调用类
public class Client {
public static void main(String[] args) {
Boy boy = new DressBoy();
Girl girl = new BoyAdapter(boy);
girl.yyy();
}
}
优缺点
优点
- 将目标类和适配者类解耦,引入一个适配器类来重用现有的适配者类,而无须修改原有代码。
- 增加了类的透明性和复用性,将具体的实现封装在适配者类中,对客户端类来说是透明的,提高了适配者的复用性。
- 灵活性和扩展性都很好,通过使用配置文件,可以方便地更换适配器,也可以在不改代码的基础上增加新适配器类,符合“开闭原则”。
除此之外
- 类适配器:适配器类是适配者类的子类,可以在适配器类中置换一些适配者的方法,使适配器更灵活。
- 对象适配器:一个对象适配器可以把多个不同的适配者适配到同一个目标,也就是说,同一个适配器可以把适配者类和它的子类都适配到目标接口。
缺点
- 类适配器:对于不支持多重继承的语言,一次最多只能适配一个适配者类,且目标抽象类只能为抽象类,不能为具体类,有一定局限,不能将一个适配者类和它的子类都适配到目标接口。
- 对象适配器模:置换适配者类的方法不容易。只能先做一个适配者类的子类,将适配者类的方法置换掉,然后再把适配者类的子类当做真正的适配者进行适配,较为复杂。
场景
- 系统需要使用现有的类,而这些类的接口不符合系统需要。
- 想建立一个可重用的类,与彼此间没太大关联的一些类,包括可能在将来引进的类一起工作。