研磨设计模式day04适配器模式

目录

理解  

场景

问题思考

解决方案

定义​编辑

解决思路

操作方法

代码示例

 使用适配器模式来实现示例

适配器模式的调用顺序

适配器优缺点

​编辑适配器本质

何时选用 


理解  

转换头/转接线

场景

我现在有个接口,对一个日志文件进行读写操作并保存在本地,使用了一段时间后,我又新增了一个版本,这个版本的功能是增删改查并且把日志存储到数据库。   

我现在想能不能让第二版实现  同时支持数据库存储和文件存储两种方式呢?

问题思考

1.如果在第二版的代码上重写文件存储方法,这样做确实可以,但是何必要重新做已经完成的功能呢?应该想办法复用,而不是重新实现

2.将两种合并起来不就可以了?  问题在于现在的业务使用的是第二版的接口,但对于第一版文件存储方式,操作接口和第二版不一样,无法以同样的方式来直接使用第一版的实现

解决方案

采用适配器

定义
解决思路

分析上面的问题,根源在于接口的不兼容,功能是基本实现了的,也就是说想办法让两边的接口匹配起来,就可以复用第一版的功能了

操作方法

定义一个类来实现第二版的接口,在内部实现的时候,转调第一版已经实现的功能,这样就可以通过对象组合的方式,既复用了第一版已有的功能,又满足了第二版调用的要求。

代码示例

1.定义数据对象

package day03适配器模式;

import java.io.Serializable;

/**
 * 日志数据对象
 */
public class LogModel implements Serializable {
    /**
     * 日志编号
     */
    private  String logId;
    /**
     * 操作人
     */
    private String operateUser;
    /**
     * 日志内容
     */
    private String logData;

    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 getLogData() {
        return logData;
    }

    public void setLogData(String logData) {
        this.logData = logData;
    }

    @Override
    public String toString() {
        return "LogModel{" +
                "logId='" + logId + '\'' +
                ", operateUser='" + operateUser + '\'' +
                ", logData='" + logData + '\'' +
                '}';
    }
}

2.定义原接口

package day03适配器模式;

import java.util.List;

/**
 * 操作日志文件的接口
 */
public interface LogFileOperateApi {
    /**
     * 读取日志文件,从文件里面获取存储的日志列表对象
     * @return
     */
    public List<LogModel> readLogFile();

    /**
     * 写日志文件,把日志列表写出到日志文件中去
     * @param list
     */
    public void writeLogFile(List<LogModel> list);
}

3.定义原实现

package day03适配器模式;

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

/**
 * 实现对日志文件的操作
 */
public class LogFileOperateImpl implements LogFileOperateApi{
    /**
     * 日志文件的路径和文件名称,默认是当前项目根下的zsp.log
     */
    private String logFilePathName = "zsp.log";

    /**
     * 构造方法,传入文件的路径和名称
     * @param logFilePathName 文件的路径和名称
     */
    public LogFileOperateImpl(String logFilePathName){
        if (logFilePathName != null && logFilePathName.trim().length() > 0){
            this.logFilePathName = logFilePathName;
        }
    }
    @Override
    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;
    }

    @Override
    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 (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (oout != null) {
                    oout.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

4.客户端实现

package day03适配器模式;

import java.util.ArrayList;
import java.util.List;

public class Client {
    public static void main(String[] args) {
        LogModel lml = new LogModel();
        lml.setLogId("001");
        lml.setOperateUser("admin");
        lml.setLogData("这是日志内容");
        List<LogModel> list = new ArrayList<>();
        list.add(lml);
        // 创建操作日志文件的对象
        LogFileOperateApi api = new LogFileOperateImpl("");
        // 保存日志文件
        api.writeLogFile(list);

        //读取日志文件的内容
        List<LogModel> readLog = api.readLogFile();
        System.out.println("readLog = " + readLog);
    }
}
 使用适配器模式来实现示例

第二版接口

package day03适配器模式;

import java.util.List;

/**
 * 定义第二版的接口
 */
public interface LogDBDBApi {
    /**
     * 增
     */
    public void createLog(LogModel lm);
    /**
     * 删
     */
    public void removeLog(LogModel lm);
    /**
     * 查所有
     */
    public List<LogModel> getAllLog();
}

新建一个适配器对象,实现第二版的接口,你要想实现第一版的接口,还需要持有这个第一版的接口对象,在适配器对象的有参构造里面将第一版的接口传进去。在方法里进行补充

package day03适配器模式;

import java.util.List;

public class Adapter implements LogDBDBApi{
    //需要持有被适配的接口对象
    private LogFileOperateApi adaptee;
    
    public Adapter(LogFileOperateApi adaptee){
        this.adaptee = adaptee;
    }

    /**
     * 新增日志
     * @param lm
     */
    @Override
    public void createLog(LogModel lm) {
        // 这里不做第二版的实现,只做第一版怎么加入第二版里面
        // 1.先读取文件的内容
        List<LogModel> list = adaptee.readLogFile();
        // 2.加入新的日志对象
        list.add(lm);
        // 3.重新写入文件
        adaptee.writeLogFile(list);
    }

    @Override
    public void removeLog(LogModel lm) {
        // 这里不做第二版的实现,只做第一版怎么加入第二版里面
        // 1.先读取文件的内容
        List<LogModel> list = adaptee.readLogFile();
        // 2.删除对应的日志对象
        list.remove(lm);
        // 3.重新写入文件
        adaptee.writeLogFile(list);
    }

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

客户端

package day03适配器模式;

import java.util.ArrayList;
import java.util.List;

public class Client {
    //    public static void main(String[] args) {
//        LogModel lml = new LogModel();
//        lml.setLogId("001");
//        lml.setOperateUser("admin");
//        lml.setLogData("这是日志内容");
//        List<LogModel> list = new ArrayList<>();
//        list.add(lml);
//        // 创建操作日志文件的对象
//        LogFileOperateApi api = new LogFileOperateImpl("");
//        // 保存日志文件
//        api.writeLogFile(list);
//
//        //读取日志文件的内容
//        List<LogModel> readLog = api.readLogFile();
//        System.out.println("readLog = " + readLog);
//    }
    public static void main(String[] args) {
        LogModel lml = new LogModel();
        lml.setLogId("002");
        lml.setOperateUser("admin");
        lml.setLogData("这是日志内容");

        // 创建操作日志文件的对象 (第一版)
        LogFileOperateApi logFileApi = new LogFileOperateImpl("");

        // 创建新版操作日志的接口对象
        Adapter adapter = new Adapter(logFileApi);

        // 保存日志文件
        adapter.createLog(lml);
        //读取日志文件的内容
        List<LogModel> allLog = adapter.getAllLog();
        System.out.println("allLog = " + allLog);
    }
}

适配器模式的调用顺序

适配器优缺点

适配器本质

何时选用 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值