zoukankan      html  css  js  c++  java
  • 请求发送者与接收者解耦—命令模式(五)

    6 请求日志

           请求日志就是将请求的历史记录保存下来,通常以日志文件(Log File)的形式永久存储在计算机中。很多系统都提供了日志文件,例如Windows日志文件、Oracle日志文件等,日志文件可以记录用户对系统的一些操作(例如对数据的更改)。请求日志文件可以实现很多功能,常用功能如下:

           (1) “天有不测风云”,一旦系统发生故障,日志文件可以为系统提供一种恢复机制,在请求日志文件中可以记录用户对系统的每一步操作,从而让系统能够顺利恢复到某一个特定的状态;

           (2) 请求日志也可以用于实现批处理,在一个请求日志文件中可以存储一系列命令对象,例如一个命令队列;

           (3) 可 以将命令队列中的所有命令对象都存储在一个日志文件中,每执行一个命令则从日志文件中删除一个对应的命令对象,防止因为断电或者系统重启等原因造成请求丢 失,而且可以避免重新发送全部请求时造成某些命令的重复执行,只需读取请求日志文件,再继续执行文件中剩余的命令即可。

           在实现请求日志时,我们可以将命令对象通过序列化写到日志文件中,此时命令类必须实现java.io.Serializable接口。下面我们通过一个简单实例来说明日志文件的用途以及如何实现请求日志:

           Sunny软件公司开发了一个网站配置文件管理工具,可以通过一个可视化界面对网站配置文件进行增删改等操作,该工具使用命令模式进行设计,结构如图6所示:

    网站配置文件管理工具结构图

           现在Sunny软件公司开发人员希望将对配置文件的操作请求记录在日志文件中,如果网站重新部署,只需要执行保存在日志文件中的命令对象即可修改配置文件。

           本实例完整代码如下所示:

    1. import java.io.*;  
    2. import java.util.*;  
    3.   
    4. //抽象命令类,由于需要将命令对象写入文件,因此它实现了Serializable接口  
    5. abstract class Command implements Serializable  
    6.     protected String name; //命令名称  
    7.     protected String args; //命令参数  
    8.     protected ConfigOperator configOperator; //维持对接收者对象的引用  
    9.       
    10.     public Command(String name)  
    11.         this.name name;  
    12.      
    13.       
    14.     public String getName()  
    15.         return this.name;  
    16.      
    17.       
    18.     public void setName(String name)  
    19.         this.name name;  
    20.      
    21.       
    22.     public void setConfigOperator(ConfigOperator configOperator)  
    23.         this.configOperator configOperator;  
    24.      
    25.       
    26.     //声明两个抽象的执行方法execute()  
    27.     public abstract void execute(String args);  
    28.     public abstract void execute();  
    29.  
    30.   
    31. //增加命令类:具体命令  
    32. class InsertCommand extends Command  
    33.     public InsertCommand(String name)  
    34.         super(name);  
    35.      
    36.       
    37.     public void execute(String args)  
    38.         this.args args;  
    39.         configOperator.insert(args);  
    40.      
    41.       
    42.     public void execute()  
    43.         configOperator.insert(this.args);  
    44.      
    45.  
    46.   
    47. //修改命令类:具体命令  
    48. class ModifyCommand extends Command  
    49.     public ModifyCommand(String name)  
    50.         super(name);  
    51.      
    52.       
    53.     public void execute(String args)  
    54.         this.args args;  
    55.         configOperator.modify(args);  
    56.      
    57.       
    58.     public void execute()  
    59.         configOperator.modify(this.args);  
    60.      
    61.  
    62.   
    63. //省略了删除命令类DeleteCommand  
    64.   
    65. //配置文件操作类:请求接收者。由于ConfigOperator类的对象是Command的成员对象,它也将随Command对象一起写入文件,因此ConfigOperator也需要实现Serializable接口  
    66. class ConfigOperator implements Serializable  
    67.     public void insert(String args)  
    68.         System.out.println("增加新节点:" args);  
    69.      
    70.       
    71.     public void modify(String args)  
    72.         System.out.println("修改节点:" args);  
    73.      
    74.       
    75.     public void delete(String args)  
    76.         System.out.println("删除节点:" args);  
    77.      
    78.  
    79.   
    80. //配置文件设置窗口类:请求发送者  
    81. class ConfigSettingWindow  
    82.     //定义一个集合来存储每一次操作时的命令对象  
    83.     private ArrayList commands new ArrayList();  
    84.     private Command command;   
    85.   
    86.     //注入具体命令对象  
    87.     public void setCommand(Command command)  
    88.         this.command command;  
    89.      
    90.       
    91.     //执行配置文件修改命令,同时将命令对象添加到命令集合中  
    92.     public void call(String args)  
    93.         command.execute(args);  
    94.         commands.add(command);  
    95.      
    96.       
    97.     //记录请求日志,生成日志文件,将命令集合写入日志文件  
    98.     public void save()  
    99.         FileUtil.writeCommands(commands);  
    100.      
    101.       
    102.     //从日志文件中提取命令集合,并循环调用每一个命令对象的execute()方法来实现配置文件的重新设置  
    103.     public void recover()  
    104.         ArrayList list;  
    105.         list FileUtil.readCommands();  
    106.           
    107.         for (Object obj list)  
    108.             ((Command)obj).execute();  
    109.          
    110.      
    111.  
    112.   
    113. //工具类:文件操作类  
    114. class FileUtil  
    115.     //将命令集合写入日志文件  
    116.     public static void writeCommands(ArrayList commands)  
    117.         try  
    118.             FileOutputStream file new FileOutputStream("config.log");  
    119.             //创建对象输出流用于将对象写入到文件中  
    120.             ObjectOutputStream objout new ObjectOutputStream(new BufferedOutputStream(file));  
    121.             //将对象写入文件  
    122.             objout.writeObject(commands);  
    123.             objout.close();  
    124.              
    125.         catch(Exception e)  
    126.                 System.out.println("命令保存失败!");    
    127.                 e.printStackTrace();  
    128.              
    129.      
    130.       
    131.     //从日志文件中提取命令集合  
    132.     public static ArrayList readCommands()  
    133.         try  
    134.             FileInputStream file new FileInputStream("config.log");  
    135.             //创建对象输入流用于从文件中读取对象  
    136.             ObjectInputStream objin new ObjectInputStream(new BufferedInputStream(file));  
    137.               
    138.             //将文件中的对象读出并转换为ArrayList类型  
    139.             ArrayList commands (ArrayList)objin.readObject();  
    140.             objin.close();  
    141.             return commands;  
    142.              
    143.         catch(Exception e)  
    144.                 System.out.println("命令读取失败!");  
    145.                 e.printStackTrace();  
    146.                 return null     
    147.                     
    148.      
    149.  

           编写如下客户端测试代码:

    1. class Client  
    2.     public static void main(String args[])  
    3.         ConfigSettingWindow csw new ConfigSettingWindow(); //定义请求发送者  
    4.         Command command; //定义命令对象  
    5.         ConfigOperator co new ConfigOperator(); //定义请求接收者  
    6.           
    7.         //四次对配置文件的更改  
    8.         command new InsertCommand("增加");  
    9.         command.setConfigOperator(co);  
    10.         csw.setCommand(command);  
    11.         csw.call("网站首页");  
    12.           
    13.         command new InsertCommand("增加");  
    14.         command.setConfigOperator(co);  
    15.         csw.setCommand(command);  
    16.         csw.call("端口号");  
    17.           
    18.         command new ModifyCommand("修改");  
    19.         command.setConfigOperator(co);  
    20.         csw.setCommand(command);  
    21.         csw.call("网站首页");  
    22.           
    23.         command new ModifyCommand("修改");  
    24.         command.setConfigOperator(co);  
    25.         csw.setCommand(command);          
    26.         csw.call("端口号");  
    27.           
    28.         System.out.println("----------------------------");  
    29.         System.out.println("保存配置");  
    30.         csw.save();  
    31.               
    32.         System.out.println("----------------------------");   
    33.         System.out.println("恢复配置");  
    34.         System.out.println("----------------------------");   
    35.         csw.recover();    
    36.      
    37.  

           编译并运行程序,输出结果如下:

    增加新节点:网站首页

    增加新节点:端口号

    修改节点:网站首页

    修改节点:端口号

    ----------------------------

    保存配置

    ----------------------------

    恢复配置

    ----------------------------

    增加新节点:网站首页

    增加新节点:端口号

    修改节点:网站首页

    修改节点:端口号

    【作者:刘伟   http://blog.csdn.net/lovelion

  • 相关阅读:
    题目1202:排序------注意每个数字的后面都有空格
    题目1178:复数集合------------结构体的的比较,cmp()函数的错误让我WA了多次
    题目1041:Simple Sorting-------注意最后一个数字的处理
    题目1034:寻找大富翁---用了sort()函数,注意头文件;
    题目1415:不一样的循环队列------注意细节小地方循环队列注意%M;还有为什么M要加一!!!!!!!!!!!!!
    题目1342:寻找最长合法括号序列II---注意:不要求就近匹配,只要求( 在 )前面的任一个位置即可
    题目1398:移动次数-----最少移动的次数,那么相同的最大值越靠后越好,相同的最小值越靠前越好
    题目1375:陈博的完美主义(25分)----------------题目中对输入数字的长度有要求,所以输入字符串,用atoi()转换函数
    题目1363:欢乐斗地主------用数组计数的应用,注意1和2得排在最后,表示最大
    题目1174:查找第K小数-------qsort()可以直接对数组用;还有用unique(a,a+n);的,服!
  • 原文地址:https://www.cnblogs.com/luckForever/p/7254879.html
Copyright © 2011-2022 走看看