设计模式-适配器模式

 

适配器的插头

我们来看一下适配器的一个简单的代码案例

复制代码
package cn.javass.dp.adapter.example1;
/**
 * 已经存在的接口,这个接口需要被适配
 */
public class Adaptee {
    /**
     * 示意方法,原本已经存在,已经实现的方法
     */
    public void specificRequest() {
        //具体的功能处理
    }
}
复制代码

 

复制代码
package cn.javass.dp.adapter.example1;
/**
 * 适配器
 */
public class Adapter implements Target {
    /**
     * 持有需要被适配的接口对象
     */
    private Adaptee adaptee;
    /**
     * 构造方法,传入需要被适配的对象
     * @param adaptee 需要被适配的对象
     */
    public Adapter(Adaptee adaptee) {
        this.adaptee = adaptee;
    }

    public void request() {
        //可能转调已经实现了的方法,进行适配
        adaptee.specificRequest();
    }
}
复制代码
复制代码
package cn.javass.dp.adapter.example1;
/**
 * 定义客户端使用的接口,与特定领域相关
 */
public interface Target {
    /**
     * 示意方法,客户端请求处理的方法
     */
    public void request();
}
复制代码

 

复制代码
package cn.javass.dp.adapter.example1;
/**
 * 使用适配器的客户端
 */
public class Client {    
    public static void main(String[] args) {
        //创建需被适配的对象
        Adaptee adaptee = new Adaptee();
        //创建客户端需要调用的接口对象
        Target target = new Adapter(adaptee);
        //请求处理
        target.request();
    }
}
复制代码

 

本质上就是对已经存在的功能进行封装,满足客户端心得需求

我们现在使用一个下面的功能。将日志文件保存到文件中

复制代码
package cn.javass.dp.adapter.example2;

import java.io.*;

/**
 * 日志数据对象
 */
public class LogModel implements Serializable{
    /**
     * 日志编号
     */
    private String logId;
    /**
     * 操作人员
     */
    private String operateUser;
    /**
     * 操作时间,以yyyy-MM-dd HH:mm:ss的格式记录
     */
    private String operateTime;    
    /**
     * 日志内容
     */
    private String logContent;
    
    public String getLogId() {
        return logId;
    }
    public void setLogId(String logId) {
        this.logId = logId;
    }
    public String getOperateUser() {
        return operateUser;
    }
    public void setOperateUser(String operateUser) {
        this.operateUser = operateUser;
    }
    public String getOperateTime() {
        return operateTime;
    }
    public void setOperateTime(String operateTime) {
        this.operateTime = operateTime;
    }
    public String getLogContent() {
        return logContent;
    }
    public void setLogContent(String logContent) {
        this.logContent = logContent;
    }
    
    public String toString(){
        return "logId="+logId+",operateUser="+operateUser+",operateTime="+operateTime+",logContent="+logContent;
    }
}
复制代码

 

复制代码
package cn.javass.dp.adapter.example2;

import java.util.List;
/**
 * 日志文件操作接口
 */
public interface LogFileOperateApi {
    /**
     * 读取日志文件,从文件里面获取存储的日志列表对象
     * @return 存储的日志列表对象
     */
    public List<LogModel> readLogFile();
    /**
     * 写日志文件,把日志列表写出到日志文件中去
     * @param list 要写到日志文件的日志列表
     */
    public void writeLogFile(List<LogModel> list);
}
复制代码

 

复制代码
package cn.javass.dp.adapter.example2;

import java.io.*;
import java.util.*;

/**
 * 实现对日志文件的操作
 */
public class LogFileOperate implements LogFileOperateApi{
    /**
     * 日志文件的路径和文件名称,默认是当前classpath下的AdapterLog.log
     */
    private String logFilePathName = "AdapterLog.log";    
    /**
     * 构造方法,传入文件的路径和名称
     * @param logFilePathName 文件的路径和名称
     */
    public LogFileOperate(String logFilePathName) {
        //先判断是否传入了文件的路径和名称,如果是,
        //就重新设置操作的日志文件的路径和名称
        if(logFilePathName!=null && logFilePathName.trim().length()>0){
            this.logFilePathName = logFilePathName;
        }
    }
    public  List<LogModel> readLogFile() {
        List<LogModel> list = null;
        ObjectInputStream oin = null;
        try {
            File f = new File(logFilePathName);
            if(f.exists()){
                oin = new ObjectInputStream(
                        new BufferedInputStream(new FileInputStream(f))
                );
                list = (List<LogModel>)oin.readObject();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            try {
                if(oin!=null){
                    oin.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return list;
    }

    public void writeLogFile(List<LogModel> list){
        File f = new File(logFilePathName);
        ObjectOutputStream oout = null;
        try {
            oout = new ObjectOutputStream(
                    new BufferedOutputStream(new FileOutputStream(f))
            );
            oout.writeObject(list);            
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            try {
                oout.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
复制代码

 

客户端的使用

复制代码
package cn.javass.dp.adapter.example2;
import java.util.*;
public class Client {
    public static void main(String[] args) {
        //准备日志内容,也就是测试的数据
        LogModel lm1 = new LogModel();
        lm1.setLogId("001");
        lm1.setOperateUser("admin");
        lm1.setOperateTime("2010-03-02 10:08:18");
        lm1.setLogContent("这是一个测试");
        
        List<LogModel> list = new ArrayList<LogModel>();
        list.add(lm1);

        //创建操作日志文件的对象
        LogFileOperateApi api = new LogFileOperate(""); 
        //保存日志文件
        api.writeLogFile(list);
        
        //读取日志文件的内容
        List<LogModel> readLog = api.readLogFile();
        System.out.println("readLog="+readLog);
    }
}
复制代码

 

 

 

现在在后面的开发中,我们需要使用数据库的形式来保存日志,最新的保存的日志使用最新的数据库的增加

删除 更新等四个接口,所以现在存在了两个版本的日志系统,第一个版本是日志文件系统,第二个版本是数据库系统,我们需要实现操作数据库的接口能够实现操作日志

 

我们使用适配器的模式来解决下面的代码

复制代码
package cn.javass.dp.adapter.example3;
import java.util.*;
/**
 * 定义操作日志的应用接口,为了示例的简单,
 * 只是简单的定义了增删改查的方法
 */
public interface LogDbOperateApi {
    /**
     * 新增日志
     * @param lm 需要新增的日志对象
     */
    public void createLog(LogModel lm);
    /**
     * 修改日志
     * @param lm 需要修改的日志对象
     */
    public void updateLog(LogModel lm);
    /**
     * 删除日志
     * @param lm 需要删除的日志对象
     */
    public void removeLog(LogModel lm);
    /**
     * 获取所有的日志
     * @return 所有的日志对象
     */
    public List<LogModel> getAllLog();
}
复制代码

 

 

复制代码
package cn.javass.dp.adapter.example4;

import java.util.List;
/**
 * DB存储日志的实现,为了简单,这里就不去真的实现和数据库交互了,示意一下
 */
public class LogDbOperate implements LogDbOperateApi{

    public void createLog(LogModel lm) {
        System.out.println("now in LogDbOperate createLog,lm="+lm);
    }

    public List<LogModel> getAllLog() {
        System.out.println("now in LogDbOperate getAllLog");
        return null;
    }

    public void removeLog(LogModel lm) {
        System.out.println("now in LogDbOperate removeLog,lm="+lm);
    }

    public void updateLog(LogModel lm) {
        System.out.println("now in LogDbOperate updateLog,lm="+lm);
    }

}
复制代码

 

复制代码
package cn.javass.dp.adapter.example3;

import java.util.List;

/**
 * 适配器对象,把记录日志到文件的功能适配成第二版需要的增删改查的功能
 */
public class Adapter implements LogDbOperateApi{
    /**
     * 持有需要被适配的接口对象
     */
    private LogFileOperateApi adaptee;
    /**
     * 构造方法,传入需要被适配的对象
     * @param adaptee 需要被适配的对象
     */
    public Adapter(LogFileOperateApi adaptee) {
        this.adaptee = adaptee;
    }
    
    public void createLog(LogModel lm) {
        //1:先读取文件的内容
        List<LogModel> list = adaptee.readLogFile();
        //2:加入新的日志对象
        list.add(lm);
        //3:重新写入文件
        adaptee.writeLogFile(list);
    }

    public List<LogModel> getAllLog() {
        return adaptee.readLogFile();
    }

    public void removeLog(LogModel lm) {
        //1:先读取文件的内容
        List<LogModel> list = adaptee.readLogFile();
        //2:删除相应的日志对象
        list.remove(lm);
        //3:重新写入文件
        adaptee.writeLogFile(list);
    }

    public void updateLog(LogModel lm) {
        //1:先读取文件的内容
        List<LogModel> list = adaptee.readLogFile();
        //2:修改相应的日志对象
        for(int i=0;i<list.size();i++){
            if(list.get(i).getLogId().equals(lm.getLogId())){
                list.set(i, lm);
                break;
            }
        }
        //3:重新写入文件
        adaptee.writeLogFile(list);
    }
}
复制代码

 

 

客户端的调用

复制代码
package cn.javass.dp.adapter.example3;
import java.util.*;
public class Client {
    public static void main(String[] args) {
        //准备日志内容,也就是测试的数据
        LogModel lm1 = new LogModel();
        lm1.setLogId("001");
        lm1.setOperateUser("admin");
        lm1.setOperateTime("2010-03-02 10:08:18");
        lm1.setLogContent("这是一个测试");
        
        List<LogModel> list = new ArrayList<LogModel>();
        list.add(lm1);

        //创建操作日志文件的对象
        LogFileOperateApi logFileApi = new LogFileOperate("");
        
        //创建新版的操作日志的接口对象
        LogDbOperateApi api = new Adapter(logFileApi); 
        
        //保存日志文件
        api.createLog(lm1);
        
        //读取日志文件的内容
        List<LogModel> allLog = api.getAllLog();
        System.out.println("allLog="+allLog);
    }
}
复制代码

 

这样就是实现采用数据库的方式来适配第一版的日志系统

适配器的主要功能:

是复用已经存在的功能,被适配的对象adaptee和需要适配成新的对象Target接口,二者是毫无关系的

 

posted on   luzhouxiaoshuai  阅读(255)  评论(0编辑  收藏  举报

编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!

导航

< 2025年3月 >
23 24 25 26 27 28 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 28 29
30 31 1 2 3 4 5

统计

点击右上角即可分享
微信分享提示