命令模式(Command):
将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持科撤销的操作。
你写过信吗?你去邮局寄过信吗?你写的第一封信是寄给谁的呢?日常生活中的邮局,可能已经成为人们眼中的一道风景线,现在已经很少有人使用信件交流传递感情。然而邮局作为一个发信人和收信人的中转机构,它的作用不容小觑,省去了发信人与收信人的直接交流,为发信人和收信人传递消息。今天我们就来重温一下信纸、邮局时代...
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Command { //信件接收者接口 public interface IReceiver { //收件人收到信件读取 void readMail(String message); } //信件接收者 public class Receiver : IReceiver { public void readMail(String message) { Console.WriteLine("收件人读取信件:" + message); } } //邮局接口 public interface IPost { //邮局发送信件 void sendMail(String message); } public class Post : IPost { private IReceiver receiver; public Post(IReceiver receiver) { this.receiver = receiver; } public void sendMail(string message) { Console.WriteLine("邮局将信件发给收信人..."); this.receiver.readMail(message); } } //发信人 public class Invoker { private IPost post; public void setPost(IPost post) { this.post = post; } //发信人发送信件 public void postMail(string message) { Console.WriteLine("发信人投递信件给邮局..."); this.post.sendMail(message); } } class Program { static void Main(string[] args) { Receiver receiver = new Receiver(); IPost post = new Post(receiver); Invoker invoker = new Invoker(); invoker.setPost(post); invoker.postMail("您好,好久不见,最近工作忙吗?"); } } }
类图:
命令模式包含如下几个角色:
Command(抽象命令角色):声明命令执行操作的接口。
Concrete Command(具体命令角色):在具体的命令角色中绑定命令接收者,命令调用接收者做出相应的操作,从而实现命令角色声明的执行操作的接口行为。
Invoker(请求者角色):命令的启动者角色,调用命令对象执行请求。
Receiver(接收者角色):具体命令执行时的行为对象,任何类都可能作为一个接收者。
Client(客户角色):创建一个具体命令对象,并分配命令的接收者。
主要优点:
1.降低系统的耦合度。
2.可以比较容易地设计一个命令队列或宏命令(组合命令)。
3.为请求的撤销(Undo)和恢复(Redo)操作提供了一种设计和实现方案。
主要缺点:
使用命令模式可能会导致某些系统有过多的具体命令类。因为针对每一个对请求接收者的调用操作都需要设计一个具体命令类,因此在某些系统中可能需要提供大量的具体命令类,这将影响命令模式的使用。
使用场合:
1.抽象出待执行的动作以参数化某对象。类似于过程设计中的回调机制,而命令模式正是回调机制的一个面向对象的替代品。
2.在不同的时刻指定、排列和执行请求。
3.需要支持可撤销的操作。
4.需要支持修改日志功能,这样当系统崩溃时,这些修改可以被重做一遍。
相关模式:
1.组合:在使用宏命令时,我们会用到组合模式。
2.备忘录:可以用来存储命令的效果状态信息,用于命令的撤销和恢复功能。