在软件规划中,指令形式是一种非常重要的规划形式。随着软件体系的不断发展,体系中的各个组件之间的耦合度越来越高,这会导致体系的复杂度和保护难度不断添加。为了处理这个问题,规划形式供给了很多处理方案,其间指令形式就是其间之一。
指令形式将恳求操作封装成一个独立的目标,使得恳求的发送者和接纳者目标之间解耦。经过这种办法,指令形式能够进步体系的灵敏性、可保护性和可扩展性,然后降低了体系的耦合度。在实际的软件规划中,指令形式被广泛应用于各种应用场景,如图形界面开发、网络通信、电子商务体系等。它能够帮助开发人员快速地完结各种恳求操作,而且能够支撑吊销和重做操作,进步了体系的交互性和用户体验。
什么是指令形式
官方文档描述:
指令形式将恳求封装为一个目标,然后使得你能够经过不同的恳求参数化客户端,将恳求进行排队或记载,并支撑可吊销的操作。
The Command pattern encapsulates a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations.
指令形式的效果:
-
将恳求发送者和恳求接纳者进行解耦,然后削减它们之间的依赖联系,进步体系的灵敏性和可扩展性。
-
支撑吊销、重做和事务性操作,使得体系愈加强健和可靠。
-
支撑指令的排队和记载,然后能够更好地办理和操控恳求的履行次序和时刻。
-
使得代码更易于扩展和保护,因为每个指令目标都只封装了一次恳求操作,而不需求修正恳求发送者或恳求接纳者
的代码。
指令形式的结构
- 指令接口(Command):界说履行操作的接口。
- 详细指令(ConcreteCommand):完结指令接口,绑定接纳者和一个动作。
- 履行者(Invoker):调用指令目标以履行恳求。
- 接纳者(Receiver):履行与恳求相关的操作。
指令形式完结
一个常见的生活中的比如是运用遥控器操控电视机。遥控器能够被看做是一个指令目标,它封装了各种详细的恳求,例如翻开电视、封闭电视、切换频道等。电视机则是一个接纳者目标,它知道怎么履行这些恳求操作。
当我们按下遥控器上的按钮时,遥控器会将相应的恳求封装成一个指令目标,并将该目标发送给电视机进行处理。这样,电视机就不需求知道详细的恳求发送者是谁,也不需求知道怎么处理这些恳求。经过将恳求封装成一个独立的目标,我们能够愈加灵敏地办理和操控恳求的履行次序和时刻。
指令接口(Command):界说履行操作的接口
public interface Command {
void execute();
}
详细指令(ConcreteCommand):完结指令接口,绑定接纳者和一个动作
public class TurnOnCommand implements Command {
private Television tv;
// 结构函数,用于将接纳者目标传递给指令目标
public TurnOnCommand(Television tv) {
this.tv = tv;
}
// 履行翻开电视机指令
public void execute() {
tv.turnOn();
}
}
public class TurnOffCommand implements Command {
private Television tv;
// 结构函数,用于将接纳者目标传递给指令目标
public TurnOffCommand(Television tv) {
this.tv = tv;
}
// 履行封闭电视机指令
public void execute() {
tv.turnOff();
}
}
public class ChangeChannelCommand implements Command {
private Television tv;
private int channel;
// 结构函数,用于将接纳者目标和指令参数传递给指令目标
public ChangeChannelCommand(Television tv, int channel) {
this.tv = tv;
this.channel = channel;
}
// 履行切换频道指令
public void execute() {
tv.changeChannel(channel);
}
}
履行者(Invoker):调用指令目标以履行恳求
public class RemoteControl {
private Command[] commands;
public RemoteControl(Command[] commands) {
this.commands = commands;
}
public void pressButton(int index) {
if (index >= 0 && index < commands.length) {
commands[index].execute();
}
}
}
这个类是指令形式中的调用者(Invoker)类,它包含一个指令数组,能够经过调用指令目标的execute()办法来履行指令操作。在这个类中,经过调用pressButton()办法来履行详细的指令操作。它接纳一个整数参数index,表明要履行的指令目标的索引,然后经过索引获取对应的指令目标,然后调用该指令目标的execute()办法来履行指令操作。
接纳者(Receiver):履行与恳求相关的操作
public class Television {
private int currentChannel = 1;
private boolean isOn = false;
// 翻开电视机
public void turnOn() {
isOn = true;
System.out.println("电视机已翻开");
}
// 封闭电视机
public void turnOff() {
isOn = false;
System.out.println("电视机已封闭");
}
// 切换频道
public void changeChannel(int channel) {
if (isOn) {
currentChannel = channel;
System.out.println("已切换到频道 " + channel);
} else {
System.out.println("电视机未翻开");
}
}
// 获取当时频道
public int getCurrentChannel() {
return currentChannel;
}
// 判别电视机是否翻开
public boolean isOn() {
return isOn;
}
}
-
turnOn()
办法用于翻开电视机。 -
turnOff()
办法用于封闭电视机。 -
changeChannel(int channel)
办法用于切换频道。假如电视机现已翻开,则将当时频道设置为指定的频道,并输出一条提示信息;不然输出一条错误信息。 -
getCurrentChannel()
办法用于获取当时频道。 -
isOn()
办法用于判别电视机是否翻开。`
Client:调用代码
public class Client {
public static void main(String[] args) {
Television tv = new Television();
Command[] commands = new Command[] {
new TurnOnCommand(tv),
new TurnOffCommand(tv),
new ChangeChannelCommand(tv, 1),
new ChangeChannelCommand(tv, 2),
new ChangeChannelCommand(tv, 3)
};
RemoteControl remote = new RemoteControl(commands);
remote.pressButton(0); // 翻开电视机
remote.pressButton(2); // 切换到频道1
remote.pressButton(3); // 切换到频道2
remote.pressButton(4); // 切换到频道3
remote.pressButton(1); // 封闭电视机
}
}
指令形式的优缺点
指令形式的长处:
- 解耦:指令形式将恳求发送者和接纳者目标解耦,使得它们不需求了解互相的存在,然后降低了体系的耦合度。例如,在一个智能家居体系中,经过指令形式,用户能够运用一个统一的遥控器来操控多种家电设备,而无需为每种设备独自配置操控器。
解耦指的是在软件规划中,将不同的组件之间的依赖联系降低到最小程度,使得它们能够独立地进行修正、扩展和保护。这样,当体系中的一个组件发生变化时,不会对其他组件产生影响,然后进步了体系的灵敏性和可保护性。
比喻来说,就像是拼积木一样,把积木拼接成独立的小块,使得每个小块能够独立拆卸和组合,而不会影响到其他的小块,然后进步了灵敏性和可保护性。
-
可扩展性:指令形式支撑对恳求操作进行组合和分离,使得体系更容易扩展和保护。例如,在一个文本编辑器中,指令形式能够用于完结吊销、重做等功能。当需求添加新的文本操作时,只需创立一个新的指令类即可,无需修正现有代码。
-
可重用性:指令形式将恳求操作封装成一个独立的目标,使得这些目标能够被重复运用,然后进步了体系的可重用性。例如,在一个图形绘制程序中,能够运用指令形式来保存用户的绘图操作,以便在需求时重新履行或吊销这些操作。
-
安全性:指令形式能够将恳求操作的调用者和接纳者目标解耦,使得体系愈加安全可靠。例如,在一个在线付出体系中,能够运用指令形式来封装付出操作,然后保证付出恳求的正确性和安全性。
指令形式的缺点:
-
添加体系复杂度:指令形式需求界说多个类和目标来完结详细的恳求操作,这或许会添加体系的复杂度和了解难度。例如,在一个简单的应用程序中,引入指令形式或许会导致过度规划,添加了不必要的开发和保护成本。
-
指令类或许过多:当体系中需求完结大量的详细恳求操作时,或许会导致指令类过多,然后添加了体系的保护难度和开发成本。例如,在一个具有复杂功能的企业级应用程序中,或许需求完结数百个不同的指令类,这将大大添加代码的复杂性和办理难度。
-
功能问题:因为指令形式需求将恳求操作封装成目标,因此或许会对体系的功能产生必定的影响。特别是在需求频繁履行恳求操作时,或许会导致体系的功能下降。例如,在一个高并发的网络服务器中,运用指令形式或许会添加目标的创立和毁掉开支,然后降低服务器的响应速度
指令形式在源码中的体现
spring结构
JdbcTemplate
JdbcTemplate是Spring结构中的核心组件之一,它供给了对数据库的操作接口,包含查询、更新、删除等操作。在JdbcTemplate中,运用指令形式来封装对数据库的操作,详细完结是经过将SQL句子和操作参数封装成一个目标,然后经过履行这个目标来完结数据库操作。
在JdbcTemplate中,指令形式的完结主要是经过三个接口来完结的:PreparedStatementCreator
、PreparedStatementSetter
和RowMapper
。
首先是PreparedStatementCreator接口,它界说了一个用于创立PreparedStatement目标的办法createPreparedStatement(Connection con),其间con参数表明要运用的数据库衔接目标。这个接口代表了指令形式中的抽象指令,它封装了SQL句子和操作参数,而且经过createPreparedStatement办法将它们转化成一个PreparedStatement目标。
接下来是PreparedStatementSetter接口,它界说了一个用于设置PreparedStatement目标参数的办法setValues(PreparedStatement ps),其间ps参数表明要设置的PreparedStatement目标。这个接口代表了指令形式中的详细指令,它接纳一个PreparedStatement目标作为参数,而且经过setValues办法来设置PreparedStatement目标的参数。
最后是RowMapper接口,它界说了一个用于将ResultSet成果集转化成Java目标的办法mapRow(ResultSet rs, int rowNum),其间rs参数表明要转化的ResultSet成果集,rowNum参数表明成果集的当时行号。这个接口代表了指令形式中的接纳者,它接纳一个ResultSet目标作为参数,而且经过mapRow办法来将成果集转化成Java目标并回来。
在JdbcTemplate中,经过将详细指令(PreparedStatementSetter接口的完结类)和抽象指令(PreparedStatementCreator接口的完结类)作为参数传递给query办法,而且在办法内部调用它们的办法来完结详细的数据库操作。同时,也经过将RowMapper接口的完结类作为参数传递给query办法,而且在办法内部调用它的办法来将成果集转化成Java目标并回来。
经过这种办法,JdbcTemplate完结了对数据库操作的封装,而且将指令目标与详细操作解耦,使得代码愈加灵敏和可扩展。同时,也使得代码愈加易于保护和重构,进步了软件开发的功率。
总归,指令形式是一种非常有用的规划形式,经过将恳求封装为一个目标,使得体系愈加灵敏、可扩展和易于保护。