定义
将一个接口转换成客户希望的另一个接口,使接口不兼容的那些类可以一起工作,其别名为包装器(Wrapper)。适配器模式既可以作为类结构型模式,也可以作为对象结构型模式。
关于适配器模式的定义如上已经很清楚了,下面这幅图可以更清楚的帮助我们理解适配器模式。
适配器作为一个中间件,将两个不兼容的类链接起来。
根据适配器与被适配者类的关系不同,适配器模式可分为对象适配器和类适配器,在对象适配器模式中,适配器与适配者之间是关联关系,在类适配器模式中,适配器与适配者之间是继承(或实现)关系。
对象适配器模式
适配器模式主要有下面几个角色:
- 目标类(Target):目标类定义客户所需的接口,可以是一个接口、抽象类或者是一个具体类。
被适配者类(Adaptee):需要被适配的类,它有自己的方法,但不能被目标类直接调用,需要通过适配器进行适配。 - 适配器类(Adapter):通过适配器类对Target和Adaptee进行适配。
前面说过,对象适配器与类适配器之间的区别就是,适配器与被适配者之间的关系,这里对象适配器中,适配器与被适配者之间是关联关系。
适配器的主要代码如下:
public class Adapter implements Target {
private Adaptee adaptee;
public Adapter() {
this.adaptee = new Adaptee();
}
@Override
public void request() {
adaptee.specificRequest();
}
}
类适配器模式
可以看到这里与前面对象适配器的区别就是适配器与被适配者之间是继承(或实现)关系。
代码表示如下:
public class Adapter extends Adaptee implements Target {
@Override
public void request() {
specificRequest();
}
}
由于在Java中是单继承的,所以这种类适配器模式的使用会受到限制,如果Target不是接口,而是具体类,就无法使用类适配器模式了,所以在Java中大部分情况下还是使用对象适配器更多一点。
实例
还是通过一个实例来理解吧:
软件公司OA系统需要提供一个加密模块,将用户机密信息(如口令、邮箱等)加密之后再存储在数据库中,系统已经定义好了数据库操作类。为了提高开发效率,现需要重用已有的加密算法,这些算法封装在一些由第三方提供的类中,有些甚至没有源代码。试使用适配器模式设计该加密模块,实现在不修改现有类的基础上重用第三方加密方法。
根据需求我们可以规划结构图如下:
主要代码如下:
// 加密的工具类
public class EncryptUtils {
public String MD5Encrypt(String str) {
String encode = null;
try {
MessageDigest md5 = MessageDigest.getInstance("MD5");
BASE64Encoder base64Encoder = new BASE64Encoder();
encode = base64Encoder.encode(md5.digest(str.getBytes()));
return encode;
} catch (NoSuchAlgorithmException e) {
System.out.println("加密出错");
return null;
}
}
public String DESEncrypt(String str) {
String password = "01234567";
String encode = null;
try {
SecureRandom random = new SecureRandom();
DESKeySpec desKey = new DESKeySpec(password.getBytes());
//创建一个密匙工厂,然后用它把DESKeySpec转换成
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
SecretKey securekey = keyFactory.generateSecret(desKey);
//Cipher对象实际完成加密操作
Cipher cipher = Cipher.getInstance("DES");
//用密匙初始化Cipher对象
cipher.init(Cipher.ENCRYPT_MODE, securekey, random);
//现在,获取数据并加密
//正式执行加密操作
byte[] bytes = cipher.doFinal(str.getBytes());
BASE64Encoder base64Encoder = new BASE64Encoder();
encode = base64Encoder.encode(bytes);
return encode;
} catch (Throwable e) {
e.printStackTrace();
}
return null;
}
public String RSAEncrypt(String str) {
return "实现RSA加密返回 ->_->";
}
}
// 目标类
public abstract class EncryptModel {
abstract String userEncrypt(String str);
}
// 适配器类
public class EncryptAdapter extends EncryptModel {
private EncryptUtils encryptUtils;
public EncryptAdapter() {
this.encryptUtils = new EncryptUtils();
}
@Override
String userEncrypt(String str) {
return encryptUtils.MD5Encrypt(str);
}
}
客户端代码:
public class Client {
public static void main(String[] args) {
EncryptModel encryptModel;
encryptModel = new EncryptAdapter();
String encode = encryptModel.userEncrypt("userName");
System.out.println("加密后的数据为:" + encode);
}
}
运行结果:
加密后的数据为:Q14GSNY0F1xGvUCsNmVFqA==
成功通过适配器类使客户端调用加密工具类中的加密算法。
转载自:重学设计模式之适配器模式