0%

适配器模式

适配器模式主要解决当客户端需要使用一个已有的目标类时,该目标类的功能可以满足客户端的需要,但是该目标类所提供的接口无法让客户端直接使用,因此需要对目标类进行转换适配,使得无需改变其结构方法即可被客户端直接使用;如何实现不改变目标类的方法,而同时又能满足现有客户端的要求呢;解决办法就是引入一个适配器类,让适配器类提供客户端需要的接口,同时适配器内部依赖目标类,客户端只需要耦合适配器类,这样当客户端调用适配器方法时,实际上是去委托给目标类进行处理,而在此过程中,客户端与目标类没有发生耦合;适配器模式主要有依赖和继承两种方式,而又继承之间的需要强烈的”is a”的关系,因此实际使用中以依赖委托的方式居多;下面看一个案例:
系统中包含AdvancedUser和Admin两个不同权限的用户类,AdvancedUser具有一个login登录的方法, Admin具有一个更高优先级的删除用户deleteUser的方法:

1
2
3
4
5
6
7
8
9
10
11
public class AdvancedUser {
public void login() {
System.out.println("login system");
}
}

public class Admin {
public void deleteUser(){
System.out.println("delete user a");
}
}

突然某一天我们要给AdvancedUser扩大权限,使其也具有删除用户的权限,因为当前已存在删除用户的功能在Admin用户中,因此我们提供接口适配器类IPremAdapter:

1
2
3
public interface IPremAdapter {
void deleteUser();
}

同时我们基于继承让AdvancedUser继承Admin实现适配器类IPremAdapter:

1
2
3
4
5
6
7
8
9
10
public class AdvancedUser extends Admin implements IPremAdapter {
public void login() {
System.out.println("login system");
}

@Override
public void deleteUser() {
super.deleteUser();
}
}

对应的类图如下:

这样我们既没有没有修改目标类Admin,同时又把删除用户的功能适配给了AdvancedUser,通过继承把功能委托给父类去实现,这就是继承适配器模式;这种方式的的缺点就是继承带来的代码耦合,同时客户端类和目标类的关系也不一定是继承关系,设计不当会使将来系统的扩展性降低,因此实际通常使用依赖关系是客户端类委托给适配器类,而适配器类又把最终的功能委托给目标类来实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class PremAdapter {
private Admin admin;

public PremAdapter() {
admin = new Admin();
}

public void deleteUser(){
admin.deleteUser();
}
}

public class AdvancedUser {
private PremAdapter adapter;

public AdvancedUser(PremAdapter adapter) {
this.adapter = adapter;
}

public void login() {
System.out.println("login system");
}

public void deleteUser() {
adapter.deleteUser();
}
}

对应类图如下:

案例分析