文档章节

适配器模式 -- 转换匹配,复用功能

满风
 满风
发布于 2016/01/22 17:45
字数 1417
阅读 75
收藏 3

给小白举个例子:

大家都用过macbook pro(15款)笔记本, tmd没有网线端口!没有VGA 视频输出接口 !

tmd 用网线要买转换器!开会用投影仪要买视频输出转接口!

这里的转换器和转接口就是我今天要讲的主角:适配器。



这里 我举个项目中的案例,做说明:

我现在要做个日志系统,前期功能比较单一,这里我叫它第一版,就是把日志写入文件,这个ok?

1:先整个日志类

public class LogModel {

    private String logId;
    private String operateUser;
    private String operateTime;
    private String logContent;
 get / set 省略...



2: 日志操作接口,两个简单的方法定义

public interface LogFileService {

    List<LogModel> readLogFile();

    void writeLogFile(List<LogModel> list);
}



3:日志操作实现类,这里具体实现不写了,简单举例,意思一下

public class LogFileServiceImpl implements LogFileService {
    @Override
    public List<LogModel> readLogFile() {
        System.out.println("正在读文件日志");
        return null;
    }

    @Override
    public void writeLogFile(List<LogModel> list) {
        System.out.println("正在写入文件日志");
    }
}



4:写个main函数,就当客户端测试下

LogModel logModel =  new LogModel();
        LogFileService service = new LogFileServiceImpl();
        service.writeLogFile(null);
        service.readLogFile();
        System.out.println("第一版  将日志写入文件!测试完成!");



5:运行结果:


看上去很容易,是吧,别急,我们接着来!

日志写入文件系统用了一段时间,老板需求增加了,我们要做系统升级,现在我们要把日志记录到DB 数据库中,

6:于是我就把接口定义好了,日志写入DB 接口如下:(这里不与数据库交互, 意思下示例)

public interface LogDBService {

    void createDBLog(LogModel logModel);
    void updateDBLog(LogModel logModel);
    void deleteDBLog(String logId);
    void selectDBLog(LogModel logModel);

}



public class LogDBServiceImpl implements LogDBService {

    @Override
    public void createDBLog(LogModel logModel) {
        System.out.println("DB日志插入成功");
    }

    @Override
    public void updateDBLog(LogModel logModel) {
        System.out.println("DB日志更新成功");
    }

    @Override
    public void selectDBLog(LogModel logModel) {
        System.out.println("DB日志查询成功");
    }
}



7:这个时候,老板提出了,新版日志系统能不能兼容都版本,就是文件和DB都支持?

很多同学心里一下子又答案了,当然了!当然都能支持了,但是实现方式不一定想的是相同的!

有的同学先到继承 ,对,设计个新接口,然后继承老的和新的接口功能,

但是,java继承只能继承一个不能同时继承,若果使用继承在继承实现,就不符合面向对象的原则了,!这里不多说。

上图抛个问题给大家:

7:这里就用到了适配器模式,就是我们找个适配器,就能用新接口兼容老的接口了!

这里我代码示例,把旧版接口功能适配成新版接口功能:我们先设计个适配器如下:

public class Adapter implements LogDBService {

    //被适配的对象
    private LogFileService adaptee;

    //构造方法,传入要被适配的对象
    public Adapter(LogFileService adaptee) {
        this.adaptee = adaptee;
    }

    @Override
    public void createDBLog(LogModel logModel) {
        adaptee.writeLogFile(null);
    }

    @Override
    public void updateDBLog(LogModel logModel) {
        //1;先读取
        List<LogModel> list = adaptee.readLogFile();
        for (int i = 0; i < list.size(); i++) {
            //2:修改内容
        }
        //3:重新写入
        adaptee.writeLogFile(list);
    }


    @Override
    public void selectDBLog(LogModel logModel) {
        adaptee.readLogFile();
    }
}



8:我们客户端调用也要稍微调整下:

LogModel logModel =  new LogModel();
        LogFileService fileService = new LogFileServiceImpl();
        LogDBService dbService = new Adapter(fileService);
        dbService.createDBLog(null);
        dbService.selectDBLog(logModel);
        logFileClient();
        System.out.println("文件适配成DB ,测试完成!");



结果如下:

我们使用的是第二版的接口,但实现的却是是第一版的功能,因为中间我们用到了一个适配器Adaper,

就像我们网线转换器一样,用的是USB接口,我们用它确实实现网络连接!

9: 到此我们新的客户端通过新的接口(第二版接口) ,能使用新功能,也能使用老功能了,如图:


10:老板在这时候,有提出了个需求,老的项目也要使用新版日志系统和新版日志功能,

这里有个问题了,我们老的项目,旧的客户端怎么搞?旧的只有旧接口,没有新版接口啊(读到这里,想到复制代码自己实现的同学,可以先不用学设计模式了)

这里给大家介绍个双向适配器!(上面演示的是个单向适配器),双向适配器的作用就是双向兼容!

上图示例说明:

11:双向适配器代码示例:

public class TwoDirectAdapter implements LogDBService,LogFileService{
    private LogFileService logFileAdaptee;
    private LogDBService   logDBAdaptee;

    public TwoDirectAdapter(LogFileService logFileAdaptee, LogDBService logDBAdaptee) {
        this.logFileAdaptee = logFileAdaptee;
        this.logDBAdaptee = logDBAdaptee;
    }

    @Override
    public void createDBLog(LogModel logModel) {
        logFileAdaptee.writeLogFile(null);
    }

    @Override
    public void updateDBLog(LogModel logModel) {
        //1;先读取
        List<LogModel> list = logFileAdaptee.readLogFile();
        for (int i = 0; i < list.size(); i++) {
            //2:修改内容
        }
        //3:重新写入
        logFileAdaptee.writeLogFile(null);
    }


    @Override
    public void selectDBLog(LogModel logModel) {
        logFileAdaptee.readLogFile();
    }

    @Override
    public List<LogModel> readLogFile() {
        logDBAdaptee.selectDBLog(null);
        return null;
    }

    @Override
    public void writeLogFile(List<LogModel> list) {
        logDBAdaptee.createDBLog(null);
    }
}



12:旧客户端调整代码:
//双向兼容,双向适配器
System.out.println("===========双向适配器测试开始============");
        //创建操作日志文件对象
        LogFileService fileSer = new LogFileServiceImpl();
        LogDBService dbSer = new LogDBServiceImpl();

        //创建经过双向适配器后的操作日志的接口对象
        LogFileService logFileSer =  new TwoDirectAdapter(fileSer,dbSer);
        LogDBService dbFileSer =  new TwoDirectAdapter(fileSer,dbSer);

        //调用第一版,实际是第二版实现
        logFileSer.readLogFile();
        logFileSer.writeLogFile(null);

        //调用第二版,实际是第一版实现
        dbFileSer.createDBLog(null);
        dbFileSer.selectDBLog(null);
        System.out.println("===========双向适配器测试完成============");

13:测试结果如下:利用双向适配器,旧系统也能使用新版日志系统包括其所有功能了。

15:什么场景下使用适配器?

  1. 如果你想要使用已经存在的类,但是它的接口不符合你的需求。
  2. 如果你想创建一个可复用的类,但是这个类可能和一些不兼容的类一起工作。
  3. 如果你想使用一些已存的子类,但是不可能对每个子类都进行适配。



© 著作权归作者所有

共有 人打赏支持
满风

满风

粉丝 91
博文 170
码字总数 174366
作品 0
杭州
技术主管
私信 提问
3、适配器模式

定义: 将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以在一起工作。 角色: 目标角色(Target):就是所期待得到的接口,也就是这...

晚天吹凉风
2018/02/23
0
0
学了那么多年设计模式依然不会用!那可真蠢!

什么是设计模式? 设计模式(Design Pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。 设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决...

GitChat技术杂谈
2018/10/26
0
0
设计模式----适配器模式UML和实现代码(5个必须掌握的设计模式)

一、什么是适配器模式? 适配器模式定义: 将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。 类型:结构型模式 顺口溜...

amosli
2015/11/20
0
0
设计模式之适配器模式学习

适配器模式:将一个类的接口转换成客户希望的另外一个接口,使原本由于接口不兼容不能一起工作的那些类可以一起工作。适配器就是是一个东西适合另外一个东西。 在软件开发中,系统的数据和行...

长平狐
2012/10/08
46
0
Happy 设计模式之适配器模式(JAVA)

设计模式-适配器模式 适配器模式定义 适配器模式,将一个类的的接口转换成客户或者产品希望的接口形式,就是原本不兼容或者甚至不相干的接口不能一起工作的接口一起工作,完成需求或者客户的...

豆芽菜橙
2018/07/03
0
0

没有更多内容

加载失败,请刷新页面

加载更多

mysql 系统设置SQL

打开、关闭日志 SET GLOBAL general_log = 'Off'; SET GLOBAL general_log = 'On'; 查看日志是否打开 show variables like '%general%';...

jingshishengxu
44分钟前
2
0
转行学大数据,如何选择如何学习大数据开发?

大数据火了几年了,但是今年好像进入了全民大数据时代,本着对科学的钻(zhun)研(bei)精(tiao)神(cao),我在17年年初开始自学大数据,后经过系统全面学习,于这个月跳槽到现任公司。 现在已经...

董黎明
44分钟前
4
0
RadosClient OSDC

RadosClient.h class librados::RadosClient : public Dispatcher//继承自Dispatcher(消息分发类){public: using Dispatcher::cct; md_config_t *conf;//配置文件private: ......

banwh
今天
2
0
如果让你写一个消息队列,该如何进行架构设计?

面试题 如果让你写一个消息队列,该如何进行架构设计?说一下你的思路。 面试官心理分析 其实聊到这个问题,一般面试官要考察两块: 你有没有对某一个消息队列做过较为深入的原理的了解,或者...

李红欧巴
今天
6
0
错题

无知的小狼
今天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部