文章目录
概念
命令设计模式
(Command Pattern)是一种行为设计模式,它将请求的操作封装为一个对象,从而实现请求者和执行者之间的解耦。这样,请求者只需要知道如何发送请求,而无需关心请求的具体执行过程。命令模式在很多场景下都非常有用,例如撤销操作、延迟执行、记录操作日志等。
组成角色
- 抽象命令(Command):定义命令的接口,通常包含一个名为
execute()
的方法。 - 具体命令(ConcreteCommand):实现抽象命令接口,封装具体的操作逻辑。
- 请求者(Invoker):负责调用命令对象来执行请求,通常不需要知道命令的具体实现。
- 接收者(Receiver):负责执行具体的操作,通常是一个具体的类或对象。
相关图示
示例代码
// 抽象命令interfaceCommand{voidexecute();}// 具体命令classConcreteCommandimplementsCommand{privateReceiver receiver;publicConcreteCommand(Receiver receiver){this.receiver = receiver;}@Overridepublicvoidexecute(){
receiver.action();}}// 接收者classReceiver{voidaction(){System.out.println("执行具体操作");}}// 请求者classInvoker{privateCommand command;publicvoidsetCommand(Command command){this.command = command;}publicvoidinvoke(){
command.execute();}}// 客户端代码publicclassCommandPatternDemo{publicstaticvoidmain(String[] args){//**在这个示例中,我们定义了一个抽象命令Command接口和一个具体命令ConcreteCommand类。具体命令封装了接收者Receiver的操作逻辑。请求者Invoker负责调用命令对象来执行请求。客户端代码创建了接收者、具体命令和请求者,并通过调用请求者的invoke()方法来执行请求。这样,请求者和接收者之间实现了解耦,使得代码更加灵活、易于维护。**/// 创建接收者Receiver receiver =newReceiver();// 创建具体命令Command command =newConcreteCommand(receiver);// 创建请求者Invoker invoker =newInvoker();
invoker.setCommand(command);// 执行请求
invoker.invoke();}}
框架中的运用
在Dubbo框架中,命令模式被用于处理网络通信中的请求和响应。下面是相关流程中的简版代码
1、
org.apache.dubbo.remoting.exchange.ExchangeChannel
接口。这是Dubbo通信层中的一个关键接口,它代表了一个通信通道。其中,
request(Object request)
方法用于发送请求,而
send(Object message)
方法用于发送响应:
publicinterfaceExchangeChannelextendsChannel{CompletableFuture<Object>request(Object request)throwsRemotingException;CompletableFuture<Object>request(Object request,int timeout)throwsRemotingException;voidsend(Object message)throwsRemotingException;// 省略部分代码...}
2、当通道收到一个请求或响应时,它会将其封装为
org.apache.dubbo.remoting.exchange.Request
或
org.apache.dubbo.remoting.exchange.Response
对象。这两个类分别表示请求和响应,其中
Request
类包含请求的数据以及请求的ID,而
Response
类包含响应的数据、状态以及请求的ID:
publicclassRequest{privatefinallong id;privateString version;privateboolean twoWay =true;privateboolean event =false;privateObject data;// 省略部分代码...}publicclassResponse{privatefinallong id;privateString version;privateint status;privateboolean event =false;privateObject result;privateThrowable exception;// 省略部分代码...}
3、在通信层,有一个
org.apache.dubbo.remoting.Dispatcher
接口,它负责分发请求和响应。分发器会将收到的请求和响应封装为
ChannelHandler
对象,并调用相应的方法进行处理。例如,当分发器收到一个请求时,它会调用
ChannelHandler
的
received(Channel channel, Object message)
方法进行处理:
publicinterfaceChannelHandler{voidconnected(Channel channel)throwsRemotingException;voiddisconnected(Channel channel)throwsRemotingException;voidsent(Channel channel,Object message)throwsRemotingException;voidreceived(Channel channel,Object message)throwsRemotingException;voidcaught(Channel channel,Throwable exception)throwsRemotingException;}
4、对于请求的处理,通常会使用
org.apache.dubbo.remoting.exchange.support.header.HeaderExchangeHandler
类。这个类实现了
ChannelHandler
接口,并重写了
received(Channel channel, Object message)
方法。在这个方法中,它首先判断收到的消息是否为
Request
对象,然后根据请求的类型(如普通请求、心跳请求等)进行相应的处理:
publicclassHeaderExchangeHandlerimplementsChannelHandlerDelegate{//展示相关代码@Overridepublicvoidreceived(Channel channel,Object message)throwsRemotingException{if(message instanceofRequest){//省略部分代码// 处理请求handleRequest(channel,(Request) message);}elseif(message instanceofResponse){// 处理响应handleResponse(channel,(Response) message);}else{//省略部分代码// 对于其他类型的消息,调用父类的方法进行处理
handler.received(channel, message);}}}
适用场景
- 请求调用者与请求接收者需要解耦:命令模式将调用操作的对象与知道如何实现这些操作的对象分离开来,这有助于降低系统各部分之间的耦合。
- 需要抽象出待执行的操作以参数化其他对象:命令模式可以将请求封装为具体的命令对象,这些对象可以在运行时进行传递、组合和替换,实现了更高程度的灵活性。
- 需要支持撤销操作:命令模式可以在命令接口中添加一个名为
undo
的方法,以便在需要时撤销操作。具体命令类可以保存先前的状态,以便在执行undo
方法时能够恢复原始状态。 - 需要支持宏命令:命令模式允许将多个命令组合成一个宏命令对象,即一个命令序列。这个宏命令对象可以像单个命令一样被执行,从而实现对一组命令的统一管理。
- 需要将命令放入队列中进行排队执行:命令模式可以将命令对象放入队列中,然后逐个执行这些命令。这可以帮助实现后台任务队列、工作线程池等功能。
- 需要记录命令日志:命令模式可以用于记录命令的详细信息,这有助于实现日志记录、审计、事务等功能。
版权归原作者 力不竭!!!战不止!!! 所有, 如有侵权,请联系我们删除。