`
runfeel
  • 浏览: 943667 次
文章分类
社区版块
存档分类
最新评论

请求发送者与接收者解耦——命令模式(五)

 
阅读更多

6 请求日志

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

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

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

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

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

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

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

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

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

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

//抽象命令类,由于需要将命令对象写入文件,因此它实现了Serializable接口
abstract class Command implements Serializable {
	protected String name; //命令名称
	protected String args; //命令参数
	protected ConfigOperator configOperator; //维持对接收者对象的引用
	
	public Command(String name) {
		this.name = name;
	}
	
	public String getName() {
		return this.name;
	}
	
	public void setName(String name) {
		this.name = name;
	}
	
	public void setConfigOperator(ConfigOperator configOperator) {
		this.configOperator = configOperator;
	}
	
    //声明两个抽象的执行方法execute()
	public abstract void execute(String args);
	public abstract void execute();
}

//增加命令类:具体命令
class InsertCommand extends Command {
	public InsertCommand(String name) {
		super(name);
	}
	
	public void execute(String args) {
		this.args = args;
		configOperator.insert(args);
	}
	
	public void execute() {
		configOperator.insert(this.args);
	}
}

//修改命令类:具体命令
class ModifyCommand extends Command {
	public ModifyCommand(String name) {
		super(name);
	}
	
	public void execute(String args) {
		this.args = args;
		configOperator.modify(args);
	}
	
	public void execute() {
		configOperator.modify(this.args);
	}
}

//省略了删除命令类DeleteCommand

//配置文件操作类:请求接收者。由于ConfigOperator类的对象是Command的成员对象,它也将随Command对象一起写入文件,因此ConfigOperator也需要实现Serializable接口
class ConfigOperator implements Serializable {
	public void insert(String args) {
		System.out.println("增加新节点:" + args);
	}
	
	public void modify(String args) {
		System.out.println("修改节点:" + args);
	}
	
	public void delete(String args) {
		System.out.println("删除节点:" + args);
	}
}

//配置文件设置窗口类:请求发送者
class ConfigSettingWindow {
    //定义一个集合来存储每一次操作时的命令对象
	private ArrayList<Command> commands = new ArrayList<Command>();
	private Command command; 

    //注入具体命令对象
	public void setCommand(Command command) {
		this.command = command;
	}
	
    //执行配置文件修改命令,同时将命令对象添加到命令集合中
	public void call(String args) {
		command.execute(args);
		commands.add(command);
	}
	
    //记录请求日志,生成日志文件,将命令集合写入日志文件
	public void save() {
		FileUtil.writeCommands(commands);
	}
	
    //从日志文件中提取命令集合,并循环调用每一个命令对象的execute()方法来实现配置文件的重新设置
	public void recover() {
		ArrayList list;
		list = FileUtil.readCommands();
		
		for (Object obj : list) {
			((Command)obj).execute();
		}
	}
}

//工具类:文件操作类
class FileUtil {
    //将命令集合写入日志文件
	public static void writeCommands(ArrayList commands) {
		try {
			FileOutputStream file = new FileOutputStream("config.log");
			//创建对象输出流用于将对象写入到文件中
    		ObjectOutputStream objout = new ObjectOutputStream(new BufferedOutputStream(file));
			//将对象写入文件
    		objout.writeObject(commands);
    		objout.close();
    		}
    	catch(Exception e) {
    			System.out.println("命令保存失败!");	
    			e.printStackTrace();
    	    }
	}
	
    //从日志文件中提取命令集合
	public static ArrayList readCommands() {
		try {
			FileInputStream file = new FileInputStream("config.log");
			//创建对象输入流用于从文件中读取对象
    		ObjectInputStream objin = new ObjectInputStream(new BufferedInputStream(file));
			
			//将文件中的对象读出并转换为ArrayList类型
    		ArrayList commands = (ArrayList)objin.readObject();
    		objin.close();
    		return commands;
    		}
    	catch(Exception e) {
    			System.out.println("命令读取失败!");
    			e.printStackTrace();
    			return null;	
    	    }		
	}
}

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

class Client {
	public static void main(String args[]) {
		ConfigSettingWindow csw = new ConfigSettingWindow(); //定义请求发送者
		Command command; //定义命令对象
		ConfigOperator co = new ConfigOperator(); //定义请求接收者
		
        //四次对配置文件的更改
		command = new InsertCommand("增加");
		command.setConfigOperator(co);
		csw.setCommand(command);
		csw.call("网站首页");
		
		command = new InsertCommand("增加");
		command.setConfigOperator(co);
		csw.setCommand(command);
		csw.call("端口号");
		
		command = new ModifyCommand("修改");
		command.setConfigOperator(co);
		csw.setCommand(command);
		csw.call("网站首页");
		
		command = new ModifyCommand("修改");
		command.setConfigOperator(co);
		csw.setCommand(command);		
		csw.call("端口号");
		
		System.out.println("----------------------------");
		System.out.println("保存配置");
		csw.save();
			
		System.out.println("----------------------------");	
		System.out.println("恢复配置");
		System.out.println("----------------------------");	
		csw.recover();	
	}
}

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

增加新节点:网站首页

增加新节点:端口号

修改节点:网站首页

修改节点:端口号

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

保存配置

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

恢复配置

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

增加新节点:网站首页

增加新节点:端口号

修改节点:网站首页

修改节点:端口号

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

分享到:
评论

相关推荐

    design-pattern-java.pdf

    请求发送者与接收者解耦——命令模式(二) 请求发送者与接收者解耦——命令模式(三) 请求发送者与接收者解耦——命令模式(四) 请求发送者与接收者解耦——命令模式(五) 请求发送者与接收者解耦——命令模式...

    c++-设计模式之命令模式(Command Pattern)

    命令模式通过将请求封装为对象,使得请求的发送者和接收者之间解耦。它提供了灵活的操作管理方式,支持可撤销操作、日志记录和宏命令等功能。在这个示例中,命令模式展示了如何通过遥控器对象控制灯的开启和关闭,...

    设计模式之命令模式

    总的来说,命令模式提供了一种方式,使得请求的发送者和接收者之间解耦,同时增强了系统的灵活性和可扩展性。通过这种方式,我们可以更加方便地管理和组织复杂的系统。在实际开发中,特别是在需要实现撤销操作或事务...

    Java设计模式课件命令模式.pptx

    命令模式是一种设计模式,属于对象行为型模式,其主要目的是将请求发送者和接收者解耦,使得两者之间没有直接的引用关系。这种模式通过引入命令对象,将一个请求封装成一个独立的对象,使得发送者只需关注如何发送...

    uml 文档 命令模式

    总结来说,命令模式通过引入命令对象,将请求的发送者与接收者解耦,增强了系统的灵活性和可扩展性。在Struts这样的Web框架中,这种模式使得我们可以更方便地管理和调度请求,同时也便于测试和维护。UML文档对于理解...

    [行为模式] head first 设计模式之命令模式(Command)

    命令模式的核心思想是将请求的发送者与接收者解耦。发送者不直接调用接收者的具体方法,而是通过命令对象来调用。这样,发送者和接收者之间就没有直接的依赖关系,可以独立变化。命令模式的关键在于定义一个命令接口...

    java 命令模式实例 (设计模式)

    总结一下,命令模式提供了一种方式来将请求封装为独立的对象,使得请求的发送者和接收者解耦。通过定义命令接口和具体命令类,我们可以轻松地添加新的命令,同时保持系统的灵活性和可扩展性。在Java中,命令模式是...

    设计模式_行为型_命令模式.md

    - 解耦调用者和接收者:命令模式将请求封装为对象,因此调用者不需要直接了解接收者的细节,降低了系统中各部分的耦合度。 - 支持撤销和重做操作:由于命令对象的历史状态可以被保存下来,因此可以实现命令的撤销和...

    设计模式之命令模式(Command Pattern)

    - **松耦合**:调用者与接收者之间的依赖关系被移除,调用者不再需要直接了解接收者的具体实现,只需要知道如何发送请求即可。 - **可扩展性**:添加新的命令只需创建新的具体命令类,不需修改原有系统。 - **可撤销...

    设计模式之命令模式源码示例

    命令模式是一种行为设计模式,它将请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。在软件工程中,这种模式广泛应用在各种场景中,以提高代码的灵活...

    设计模式-命令模式

    命令模式是一种行为设计模式,它将请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。在iOS开发中,命令模式尤其适用于处理事件驱动的编程场景,因为...

    命令模式.zip

    在C#编程中,命令模式常用于实现解耦发送者和接收者,提高代码的灵活性和可扩展性。 在"命令模式.zip"这个压缩包中,我们可能会找到以下几个关键部分: 1. **命令接口(Command Interface)**:这是所有具体命令类...

    23种设计模式(10)命令模式Java开发Java经验技巧

    1. **松耦合**:命令模式将请求者与接收者解耦,两者无需直接交互,降低了系统的复杂性。 2. **可扩展性**:添加新命令只需要实现新的具体命令类,无需修改已有代码。 3. **可撤销操作**:可以通过实现undo()方法来...

    第二十五讲:命令模式

    首先,命令模式的核心思想是"将命令的发送者与接收者解耦"。它包含四个角色:命令接口(Command)、具体命令(Concrete Command)、请求者(Invoker)和接收者(Receiver)。命令接口定义了执行操作的方法,具体命令...

    设计模式--命令模式java例子

    命令模式的核心是将请求者(Invoker)与执行者(Receiver)解耦,通过引入命令(Command)接口和具体命令(Concrete Command)类来实现。在该模式中,有四个主要角色: 1. **命令(Command)接口**:定义了一个接收...

    Head First 设计模式 (六) 命令模式(Command pattern) C++实现

    总的来说,命令模式是设计模式中的重要一环,它通过封装请求行为,使得请求发送者和接收者解耦,提高了系统的灵活性和可维护性。在C++中,利用面向对象特性,我们可以方便地实现和应用这一模式。

    设计模式之Command(命令)模式

    1. **解耦**:命令模式将请求发送者与接收者解耦,两者无需直接交互,降低了系统的耦合度。 2. **可扩展性**:容易添加新的命令而不影响现有代码,符合开闭原则。 3. **支持撤销操作**:通过实现命令的`undo()`方法...

    命令模式代码demo

    命令模式的核心思想是解耦调用者(Client)与接收者(Receiver),通过引入命令(Command)接口作为两者之间的桥梁。调用者不再直接调用接收者的具体方法,而是创建一个实现了命令接口的对象,并将该对象传递给接收...

Global site tag (gtag.js) - Google Analytics