适配器模式-类、对象、双向适配器详解+代码

1. 适配器模式动机定义

1.1 适配器模式动机

在软件开发中,存在一些不一致的情况,例如在某个加密模块中已经写好了的数据库操作类。为了提高开发效率,可以重用已有的加密算法,这些算法封装在一些第三方的类中,需要实现的是不修改现有类的基础上重用第三方加密方法。

1.2 适配器模式定义

将一个接口转换成客户希望的另一个接口,适配器模式使接口不兼容的那些类可以一起工作,其别名包装器。

2. 适配器模式结构与分析

2.1 类适配器结构

在这里插入图片描述

2.2 对象适配器结构

在这里插入图片描述

2.3 适配器模式结构

  • Target(目标抽象类)

目标抽象定义客户要用特定领域的接口,可以是抽象类或者接口,也可以是具体类;在类适配器中,由于Java语句不支持多重继承,他只能是接口。(或者使用抽象类定义后用对象适配器实现)

  • Adaptee(适配者类)

适配者即被适配的角色,它定义了一个已经存在的接口,这个接口需要适配。适配者类一般是一个具体的类,它包含了客户希望使用的业务方法,在某些情况下甚至没有适配者类的源码。

  • Adapter(适配器类)

适配器类可调用另一个接口,作为转换器,对Adaptee和Target进行适配。

  • Client(客户类)

在客户类中针对目标抽象类进行编程,调用目标抽象中定义的业务方法。

3. 类适配器

适配者类

public class Adaptee {
    public void specificRequest(){
        System.out.println("适配者的实现的方法!");
    }
}

适配器类

public class Adapter extends Adaptee implements TargetInterface{

    // 通过类适配器模式可以直接调用适配者的方法
    public void request(){
        System.out.print("适配器模仿:");
        super.specificRequest();
    }
}

目标抽象类

public interface TargetInterface {
    public void request();
}

客户类

public class Client {
    public static void main(String[] args) {
        Adapter a = new Adapter();
        a.request();
    }
}

4. 对象适配器

目标抽象类

public abstract class DataOperation {
    private String password;

    public void setPassword(String password){
        this.password = password;
    }

    public String getPassword(){
        return this.password;
    }

    public abstract String doEncrypt(int key, String ps);
}

适配者类

/**
 * 数据加密类
 */
public final class Caesar {
    public String doEncrypt(int key, String ps){
        String es = "";
        for (int i = 0; i < ps.length(); i++) {
            char c = ps.charAt(i);
            if(c >= 'a' && c <= 'z'){
                c += key % 26;
                if(c > 'z') c -= 26;
                if(c < 'a') c += 26;
            }
            if(c >= 'A' && c <= 'Z'){
                c += key % 26;
                if(c > 'Z') c -= 26;
                if(c < 'A') c += 26;
            }
            es += c;
        }
        return es;
    }
}

适配器类

/**
 * 第一种加密适配器
 */
public class CipherAdapter extends DataOperation {

    private Caesar caesar;

    public CipherAdapter(){
        caesar = new Caesar();
    }
    
    @Override
    public String doEncrypt(int key, String ps) {
        return caesar.doEncrypt(key, ps);
    }
    
}

扩展新的加密算法

/**
 * 新的加密算法
 */
public final class NewCipher{
    public String doEncrypt(int key, String ps){
        String es = "";
        for (int i = 0 ; i < ps.length(); i++) {
            String c = String.valueOf(ps.charAt(i) % key);
            es += c;
        }
        return es;
    }
}

新加密算法的的适配器

public class NewCipherAdapter extends DataOperation {
    private NewCipher newCipher;

    public NewCipherAdapter(){
        newCipher = new NewCipher();
    }
    
    @Override
    public String doEncrypt(int key, String ps) {
        return newCipher.doEncrypt(key, ps);
    }
}

客户端

/**
 * 加密适配器客户端测试
 */
public class Client {
    public static void main(String[] args) {
        DataOperation dao = (DataOperation)XMLUtil.getClassName();

        dao.setPassword("sun");
        String ps = dao.getPassword();
        String es = dao.doEncrypt(6, ps);
        System.out.println("明文:"  + ps);
        System.out.println("密文:" + es);
    }
}

XMLUtil

public class XMLUtil {
    public static Object getClassName(){
		
		try{
			// 单例获取文档工厂对象
			DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();
			// 使用工厂对象创建构建文档对象
			DocumentBuilder builder = dFactory.newDocumentBuilder();
			// 文档对象
			Document doc;
			// 通过文档构建对象读取xml文件并创建文档对象
			doc = builder.parse(new File("/workspace/demo/adapter/objAdapter/config.xml"));
			// 根据节点名获取节点集
			NodeList nl = doc.getElementsByTagName("className");
			// 获取第一个节点集的第一个节点
			Node firstChild = nl.item(0).getFirstChild();
			// 获取节点对象的值去除头尾空格
			String className = firstChild.getNodeValue().trim();
			
            return Class.forName(className).getDeclaredConstructor().newInstance();
		}catch (Exception e){
			e.printStackTrace();
			return null;
		}
	}
}

``

## config.xml

```xml
<?xml version="1.0"?>
<config>
    <className>adapter.objAdapter.NewCipherAdapter</className>
</config>

5. 双向适配器

  • 目标抽象
public interface Target {
	public void request();
}
  • 适配者
public interface Adaptee {
	public void specificRequest();
}
  • 具体目标抽象
public class ConcreteTarget implements Target {
	public void request(){
		System.out.println("目标抽象具体实现类 实现方法!");
	}
}
  • 具体适配者
public class ConcreteAdaptee implements Adaptee {
	public void specificRequest(){
		System.out.println("具体适配者类实现的方法!");
	}
}
  • 双向适配器
public class Adapter {
	private Adaptee adaptee;
	private Target target;
	
	public void setAdaptee(Adaptee adaptee) {
		this.adaptee = adaptee;
	}
	public void setTarget(Target target) {
		this.target = target;
	}
	
	public void specificRequest(){
		target.request();
	}
	public void request(){
		adaptee.specificRequest();
	}
}
  • 客户端
public class Client {
	public static void main(String[] args) {
		Adapter doubleAdapter = new Adapter();
		doubleAdapter.setAdaptee(new ConcreteAdaptee());
		doubleAdapter.setTarget(new ConcreteTarget());
		
		doubleAdapter.request();
		doubleAdapter.specificRequest();
	}
}

版权声明:本文为weixin_43629889原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。