4.[研磨设计模式笔记]适配器模式

1.定义

将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的哪些类可以一起工作。

2.解决问题

——日志管理

不用模式的解决方案

版本一:用户要求日志以文件的形式记录

1
2
3
4
5
6
7
8
9
10
11
12
public  interface  LogFileOperateApi {
     /**
      * 读取日志文件,从文件里面获取存储的日志列表对象
      * @return 存储日志列表对象
      */
     public  List<LogModel> readLogFile();
     /**
      * 写日志文件,把日志列表写出到日志文件中去
      * @param List 要写到日志文件的日志李彪
      */
     public  void  writeLogFile(List<LogModel> List);
}

版本二:用户要求日志以数据库的形式记录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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();
}

使用适配器模式来解决问题

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
32
33
34
35
36
37
38
39
40
41
42
43
44
public  class  Adapter  implements  LogDbOperateApi {
     private  LogFileOperateApi adaptee;
     public  Adapter(LogFileOperateApi adaptee) {
         super ();
         this .adaptee = adaptee;
     }
     public  void  createLog(LogModel lm) {
         //读取文件内容
         List<LogModel> list = adaptee.readLogFile();
         //加入新日志
         list.add(lm);
         //重新写入文件
         adaptee.writeLogFile(list);
     }
     public  void  updateLog(LogModel lm) {
         //读取文件内容
         List<LogModel> list = adaptee.readLogFile();
         //修改相应日志
         //重新写入文件
         adaptee.writeLogFile(list);
     }
     public  void  removeLog(LogModel lm) {
         //读取文件内容
         List<LogModel> list = adaptee.readLogFile();
         //删除相应日志
         list.remove(lm);
         //重新写入文件
         adaptee.writeLogFile(list);
     }
     public  List<LogModel> getAllLog() {
         return  adaptee.readLogFile();
     }
}
public  class  Client {
     public  static  void  main(String[] args) {
         LogModel lml =  new  LogModel();
         // 创建操作日志文件的对象
         LogFileOperateApi logFileApi =  new  LogFileOperate( "" );
         // 创建新版操作日志的接口对象
         LogDbOperateApi api =  new  Adapter(logFileApi);
         // 保存日志文件
         api.createLog(lml);
     }
}

3.模式讲解

在第一版中采用的文件存储方式,它的操作方式和第二版不一样,这导致现在的客户端无法以同样的方式来直接使用第一版的实现。要想同时支持文件和数据库存储方式,需要额外地做一些工作。

一种很容易想到的方式是直接修改已有的第一版的代码,这种方式不太好,因为可能会导致其他依赖于这些实现的应用不能正常运行。

解决思路

上面的问题,根源在与接口不兼容,功能都是实现了的,即只要让两个接口匹配起来。按照适配器的方式,可以顶一个类来实现第二版的接口,然后在内部实现的时候,转调第一版已经实现了的功能,这样就可以通过对象组合的方式,既服用了第一版已有的功能,同时又在接口上满足了第二版调用的要求。

示例代码

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
32
33
34
35
36
37
38
39
40
41
public  interface  Target {
     /**
      * 客户端请求处理的方法
      */
     public  void  request();
}
public  class  Adaptee {
     /**
      * 原本已经存在,已经实现的方法
      */
     public  void  specificRequest() {
         // 具体功能处理
     }
}
public  class  Adapter  implements  Target {
     // 持有需要被是配的接口对象
     private  Adaptee adaptee;
                 
     /**
      * 构造函数,传入需要被适配的对象
      * @param adaptee 需要被是配的独享
      */
     public  Adapter(Adaptee adaptee) {
         super ();
         this .adaptee = adaptee;
     }
     public  void  request() {
         // 转调已经实现了的方法,进行适配
         adaptee.specificRequest();
     }
}
public  class  Client {
     public  static  void  main(String[] args) {
         // 创建需要被适配的对象
         Adaptee adaptee =  new  Adaptee();
         // 创建客户端需要调用的接口对象
         Target target =  new  Adapter(adaptee);
         // 请求处理
         target.request();
     }
}

应用范围

适配器模式的主要功能是进行转换匹配,目的是复用已有的功能,而不是来实现新的接口。即客户端需要的功能应该是已实现好的,不需要适配器模式来实现,适配器模式主要负责把不兼容的接口转换成客户端期望的样子。

Adaptee和Target的关系

适配器模式中被适配的接口Adaptee和适配称为接口的Target是没有关联系。

适配器模式调用顺序示意图

151402872.png

适配器模式的优缺点:

优点:更好的复用性,更好地可扩展性

缺点:过多的使用适配器,会让系统非常凌乱,不容易整体进行把握

4.思考

适配器模式的本质是:转换匹配,复用功能

适配器通过转换调用已有的实现,从而把已有的实现匹配成为需要的接口,使之能满足客户端的需求,即转换匹配是手段,复用功能才是目的。

何时选用适配器模式

如果想:使用一个已经存在的类,但是他的接口不符合你的需求,这种情况可以使用适配器模式,来把已有的实现转换成你需要的接口。

如果想:创建一个可以服用的类,这个类可能和一些不兼容的类一起工作,这种情况可以使用适配器模式。










本文转自 LinkedKeeper 51CTO博客,原文链接:http://blog.51cto.com/sauron/1229970,如需转载请自行联系原作者
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值