设计模式学习笔记------适配器模式

Posted 有悟还有迷

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式学习笔记------适配器模式相关的知识,希望对你有一定的参考价值。

              适配器模式

一、适配器模式

1.适配器模式结构图

                    

 

 2.适配器模式示例代码

 1 (1)先看看Target接口定义的示例代码如下
 2 /** 
 3  * 定义客户端使用的接口,与特定领域相关
 4  */
 5 public interface Target {
 6     /**
 7      * 示意方法,客户端请求处理方法
 8      */
 9     public void request();
10 }
11 (2)再看看需要被适配的对象定义。示例代码如下:
12 /**
13  * 已经存在的接口,这个接口需要配适配
14  */
15 public class Adaptee{
16     /**
17      * 示意方法,原本已经存在,已经实现的方法
18      */
19     public void specificRequest() {
20         //具体的功能处理
21     }
22 }
23 
24 (3)下面是适配器对象的基本实现。示例代码如下:
25 /**
26  * 适配器
27  */
28 public class Adapter implements Target {
29     /**
30      * 持有需要被适配的接口对象
31      */
32     private Adaptee adaptee;
33     
34     /**
35      * 构造方法,传入需要被适配的对象
36      * @param adaptee
37      */
38     public Adapter(Adaptee adaptee) {
39         this.adaptee = adaptee;
40     }
41     
42     @Override
43     public void request() {
44         //可能转调已经实现了的方法,进行适配
45         adaptee.specificRequest();
46     }
47     
48 }
49 
50 (4)再来看看使用适配器客户端的示例代码如下:
51 /**
52  * 使用适配器的客户端
53  */
54 public class Client {
55     public static void main(String[] args) {
56         //创建需要被适配的对象
57         Adaptee adaptee = new Adaptee();
58         //创建客户端需要调用的接口对象
59         Target target = new Adapter(adaptee);
60         //请求处理
61         target.request();
62     }
63 }

二、具体实现代码---日志管理

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

  1 /**
  2  * 日志数据对象
  3  * @author abc
  4  *
  5  */
  6 public class LogModel implements Serializable {
  7     private static final long serialVersionUID = 1L;
  8     
  9     /**
 10      * 日志编号
 11      */
 12     private String logId;
 13     /**
 14      * 操作人员
 15      */
 16     private String operateUser;
 17     /**
 18      * 操作时间,以yyyy-MM-dd HH:mm:ss的格式记录
 19      */
 20     private String operateTime;
 21     /**
 22      * 日志内容
 23      */
 24     private String logContent;
 25     public String getLogId() {
 26         return logId;
 27     }
 28     public void setLogId(String logId) {
 29         this.logId = logId;
 30     }
 31     public String getOperateUser() {
 32         return operateUser;
 33     }
 34     public void setOperateUser(String operateUser) {
 35         this.operateUser = operateUser;
 36     }
 37     public String getOperateTime() {
 38         return operateTime;
 39     }
 40     public void setOperateTime(String operateTime) {
 41         this.operateTime = operateTime;
 42     }
 43     public String getLogContent() {
 44         return logContent;
 45     }
 46     public void setLogContent(String logContent) {
 47         this.logContent = logContent;
 48     }
 49     @Override
 50     public String toString() {
 51         return "logId=" + logId + ", operateUser=" + operateUser + ", operateTime=" + operateTime
 52                 + ", logContent=" + logContent;
 53     }
 54     
 55     
 56 }
 57 
 58 /**
 59  * 日志文件操作接口
 60  * @author abc
 61  *
 62  */
 63 public interface LogFileOperate {
 64     
 65     /**
 66      * 读取日志文件,从文件里面获取存储的日志列表对象
 67      * @return 存储的日志列表对象
 68      */
 69     public List<LogModel> readLogFile();
 70     
 71     /**
 72      * 写日子文件,把日志列表写出到日志文件中
 73      * @param list 要写到日志文件的日志列表
 74      */
 75     public void writeLogFile(List<LogModel> list);
 76     
 77 }
 78 
 79 /**
 80  * 日志文件操作接口实现
 81  * @author abc
 82  *
 83  */
 84 public class LogFileOperateImpl implements LogFileOperate {
 85     
 86     /**
 87      * 日志文件的路径和文件名称,默认是当前项目根路劲下的AdapterLog.log
 88      */
 89     private String logFilePathName = "AdapterLog.log";
 90     
 91     /**
 92      * 构造方法,传入文件的路径和名称
 93      * @param logFilePathName 文件路径和名称
 94      */
 95     public LogFileOperateImpl(String logFilePathName) {
 96         if (logFilePathName != null && logFilePathName.trim().length() > 0) {
 97             //判断是否传入了文件的路径和名称,传入就重置路径和名称
 98             this.logFilePathName = logFilePathName;
 99         }
100     }
101 
102     @Override
103     public List<LogModel> readLogFile() {
104         List<LogModel> list = null;
105         ObjectInputStream oin = null;
106         try {
107             File f = new File(logFilePathName);
108             if (f.exists()) {
109                 oin = new ObjectInputStream(new BufferedInputStream(new FileInputStream(f)));
110                 list = (List<LogModel>)oin.readObject();
111             }
112         } catch (Exception e) {
113             // TODO Auto-generated catch block
114             e.printStackTrace();
115         } finally {
116             try{
117                 if (oin != null) {
118                     oin.close();
119                     oin = null;
120                 }
121             } catch (IOException e) {
122                 e.printStackTrace();
123             }
124         }
125         return list;
126     }
127 
128     @Override
129     public void writeLogFile(List<LogModel> list) {
130         File f = new File(logFilePathName);
131         ObjectOutputStream oos = null;
132         try {
133             oos = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(f)));
134             oos.writeObject(list);
135         }  catch (IOException e) {
136             // TODO Auto-generated catch block
137             e.printStackTrace();
138         } finally {
139             try {
140                 if (oos != null) {
141                     oos.close();
142                     oos = null;
143                 }
144             } catch (IOException e) {
145                 // TODO Auto-generated catch block
146                 e.printStackTrace();
147             }
148         }
149 
150     }
151 
152 }
153 
154 /**
155  * 客户端测试
156  * @author abc
157  *
158  */
159 public class Client {
160     public static void main(String[] args) {
161         //准备日志内容,测试的数据
162         LogModel model = new LogModel();
163         model.setLogId("002");
164         model.setOperateUser("admin1");
165         model.setOperateTime("2018-01-02 16:16:00");
166         model.setLogContent("这是一个测试");
167         
168         List<LogModel> list = new ArrayList<LogModel>();
169         list.add(model);
170         //创建操作日志文件的对象
171         LogFileOperate logFileOperate = new LogFileOperateImpl("");
172         //保存日志文件
173         logFileOperate.writeLogFile(list);
174         
175         //读取日子文件的内容
176         List<LogModel> readLog = logFileOperate.readLogFile();
177         System.out.println("readLog=" + readLog);
178         
179     }
180 }

  需求二:用户要求日志以数据库的形式管理日志。

/**
 * 定义操作的应用接口
 * @author abc
 *
 */
public interface LogDbOperate {
    
    /**
     * 新增日志
     * @param model 需要新增的日志对象
     */
    public void createLog(LogModel model);
    /**
     * 修改日志
     * @param model 需要修改的日志对象
     */
    public void updateLog(LogModel model);
    /**
     * 删除日志
     * @param model 需要删除的日志对象
     */
    public void removeLog(LogModel model);
    /**
     * 获取所有的日志
     * @return 所有日志对象集合
     */
    public List<LogModel> getAllLog();
}

/**
 * 定义操作的应用接口实现类
 * @author abc
 */
public interface LogDbOperateImpl {
        //具体实现内容      
}

/**
 * 客户端测试
 * @author abc
 *
 */
public class Client {
    public static void main(String[] args) {
        //准备日志内容,测试的数据
        LogModel model = new LogModel();
        model.setLogId("002");
        model.setOperateUser("admin1");
        model.setOperateTime("2018-01-02 16:16:00");
        model.setLogContent("这是一个测试");
        
        List<LogModel> list = new ArrayList<LogModel>();
        list.add(model);
        //创建操作日志文件的对象
        LogFileOperate logFileOperate = new LogFileOperateImpl("");
        
        LogDbOperate logDbOperate  = new Adapter(logFileOperate);
        //保存日志文件
        logDbOperate.createLog(model);
        //读取日志文件的内容
        List<LogModel> allLog = logDbOperate.getAllLog();
        System.out.println("allLog=" + allLog);
    }
}

思路总结:

1.原有存取日志的方式

 

2.现在有了新的基于数据库的实现,新的实现由自己的接口

 

3.现在想要在第二版的实现里面,能够同时兼容第一版的功能,那么就应有一个类来实现第二版的接口,然后在这个类里面去调用已有的功能实现,这个类就是适配器

 

 

整体结构

 

三、认识适配器模式

  1.模式的功能

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

    但这并不是说,在适配器里面就不能实现功能。适配器里面可以实现功能,称这种适配器为智能适配器。再说了,在接口匹配和转换的过程中,也有可能需要额外实现一定的功能,才能转换过来,比如需要调整参数以进行匹配等。

  2.Adaptee 和 Target 的关系

    适配器模式中被适配的接口Adaptee和适配成为的接口Target是没有关联的,也就是说,Adaptee和Target中的方法既可以相同,也可以不同。极端情况下两个接口里面方法可能完全不同的,当然这种情况下也可以完全相同。

    这里所说的相同和不同,是指方法定义的名称、参数列表、返回值,以及方法本省的功能都可以相同或不同。    

  3.对象组合

    根据前面的实现,你会发现,适配器的实现方式其实是依靠对象组合的方式。通过给适配器对象组合被适配的对象,然后当客户端调用Targer的时候,适配器会吧相应的功能委托给适配的对象去完成。

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

   

 

四、双向适配器

 

  1 /**
  2  * 定义操作的应用接口实现
  3  * @author abc
  4  *
  5  */
  6 public class LogDbOperateImpl implements LogDbOperate {
  7 
  8     @Override
  9     public void createLog(LogModel model) {
 10         System.out.println("新增日志:" + model);
 11     }
 12 
 13     @Override
 14     public void updateLog(LogModel model) {
 15         System.out.println("修改日志:" + model);
 16     }
 17 
 18     @Override
 19     public void removeLog(LogModel model) {
 20         System.out.println("删除日志:" + model);
 21     }
 22 
 23     @Override
 24     public List<LogModel> getAllLog() {
 25         System.out.println("获取所有日志");
 26         return null;
 27     }
 28 
 29 }
 30 
 31 /**
 32  * 双向适配器
 33  * @author abc
 34  *
 35  */
 36 public class TwoDirectAdater implements LogDbOperate, LogFileOperate {
 37     
 38     /**
 39      * 持有需要被适配的文件存储日志的接口对象
 40      */
 41     private LogFileOperate logFileOperate;
 42     
 43     /**
 44      * 持有需要被适配的DB存储日志的接口对象
 45      */
 46     private LogDbOperate logDbOperate;
 47     
 48     /**
 49      * 构造方法,传入需要被适配的对象
 50      * @param logFileOperate 持有需要被适配的文件存储日志的接口对象
 51      */
 52     public TwoDirectAdater(LogFileOperate logFileOperate) {
 53         this.logFileOperate = logFileOperate;
 54     }
 55     
 56     /**
 57      * 构造方法,传入需要被适配的对象
 58      * @param logDbOperate 持有需要被适配的DB存储日志的接口对象
 59      */
 60     public TwoDirectAdater(LogDbOperate logDbOperate) {
 61         this.logDbOperate = logDbOperate;
 62     }
 63     
 64     /**
 65      * 构造方法,传入需要被适配的对象
 66      * @param logFileOperate 持有需要被适配的文件存储日志的接口对象
 67      * @param logDbOperate 持有需要被适配的DB存储日志的接口对象
 68      */
 69     public TwoDirectAdater(LogFileOperate logFileOperate, LogDbOperate logDbOperate) {
 70         this.logFileOperate = logFileOperate;
 71         this.logDbOperate = logDbOperate;
 72     }
 73     
 74     /*------------------DB操作的范式适配为文件实现方式的接口---------------------*/
 75     @Override
 76     public List<LogModel> readLogFile() {
 77         return logDbOperate.getAllLog();
 78     }
 79 
 80     @Override
 81     public void writeLogFile(List<LogModel> list) {
 82         //1.删除所有数据库中的数据
 83         //2.循环把现在的数据加入到数据库中
 84         for (LogModel lm : list) {
 85             logDbOperate.createLog(lm);
 86         }
 87     }
 88     
 89     /*-----------------文件操作的方式适配成为DB实现方式的接口---------------------*/
 90     @Override
 91     public void createLog(LogModel model) {
 92         //1.读取文件内容
 93         List<LogModel> list = logFileOperate.readLogFile();
 94         //2.加入新得日志队形
 95         list.add(model);
 96         //3.重新写入文件
 97         logFileOperate.writeLogFile(list);
 98     }
 99 
100     @Override
101     public void updateLog(LogModel model) {
102         //1.读取文件的内容
103         List<LogModel> list = logFileOperate.readLogFile();
104         //2.修改相对应的日志对象
105         for (int i = 0; i < list.size(); i++) {
106             if (list.get(i).getLogId().equals(model.getLogId())) {
107                 list.set(i, model);
108                 break;
109             }
110         }
111     }
112 
113     @Override
114     public void removeLog(LogModel model) {
115         //1.读取文件的内容
116         List<LogModel> list = logFileOperate.readLogFile();
117         //2.删除相对应的日志对象
118         list.remove(model);
119     }
120 
121     @Override
122     public List<LogModel> getAllLog() {
123         return logFileOperate.readLogFile();
124     }
125 
126 }
127 
128 /**
129  * 客户端测试
130  * @author abc
131  *
132  */
133 public class Client {
134     public static void main(String[] args) {
135         //准备日志内容,测试的数据
136         LogModel model = new LogModel();
137         model.setLogId("003");
138         model.setOperateUser("admin2");
139         model.setOperateTime("2018-01-03 16:16:00");
JAVA学习笔记--策略设计模式与适配器模式

设计模式:学习笔记(10)——适配器模式

设计模式学习笔记-适配器模式(对象适配器)

java/android 设计模式学习笔记---适配器模式

设计模式学习笔记之适配器模式

适配器模式——HeadFirst设计模式学习笔记