了解23种设计模式之命令模式

    技术2025-06-22  10

    了解23种设计模式之命令模式

    什么是命令模式命令模式的角色与特点代码实现模式应用实例 使用组合模式和命令模式命令模式的应用场景

    什么是命令模式

    在开发中,常常出现方法请求者与方法实现者之间存在之间存在紧密的耦合关系。这不利于软件功能的扩展与维护。 例如,想对行为进行“撤销、重做、记录”等处理都很不方便,因此“如何将方法的请求者与方法的实现者解耦?”变得很重要,命令模式能很好地解决这个问题。

    在现实生活中,这样的例子也很多,例如,电视机遥控器(命令发送者)通过按钮(具体命令)来遥控电视机(命令接收者),还有计算机键盘上的“功能键”等。 吃烧烤,你说要10串羊肉串(命令发送者) ,服务员记录(具体命令), 烧烤师傅(命令接收者)

    命令模式(Command):将一个请求封装成对象,使发出请求的责任和执行命令责任分割开。 这样两者通过命令对像进行沟通。这样方便将命令对象进行存储,传递,调用,增加与管理。

    命令模式的角色与特点

    优点: 1,降低系统的耦合度。命令模式能将调用操作的对象与实现该操作的对象解耦。 2,增加或删除命令非常方便。采用命令模式增加与删除命令不会影响其他类,它满足“开闭原则”,对扩展比较灵活。 3,可以实现宏命令。命令模式可以与组合模式结合,将多个命令装配成一个组合命令,即宏命令。 4,方便实现 Undo 和 Redo 操作。命令模式可以与,备忘录模式结合,实现命令的撤销与恢复。

    缺点:可能产生大量具体命令类。因为计对每一个具体操作都需要设计一个具体命令类,这将增加系统的复杂性。

    角色:可以将系统中的相关操作抽象成命令,使调用者与实现者相关分离

    抽象命令类(Command)角色:声明执行命令的接口,拥有执行命令的抽象方法 execute()。具体命令角色(Concrete Command)角色:是抽象命令类的具体实现类,它拥有接收者对象,并通过调用接收者的功能来完成命令要执行的操作。实现者/接收者(Receiver)角色:执行命令功能的相关操作,是具体命令对象业务的真正实现者。调用者/请求者(Invoker)角色:是请求的发送者,它通常拥有很多的命令对象,并通过访问命令对象来执行相关请求,它不直接访问接收者。

    结构图如下:

    代码实现

    抽象命令类:command 声明执行命令的接口,拥有执行命令的抽象方法 execute()。

    public abstract class Command { protected Receiver receiver; public Command(Receiver receiver) { this.receiver = receiver; } public abstract void execute(); }

    具体命令角色(Concrete Command)角色:是抽象命令类的具体实现类,它拥有接收者对象,并通过调用接收者的功能来完成命令要执行的操作。

    public class ConcreteCommand extends Command{ public ConcreteCommand(Receiver receiver) { super(receiver); } @Override public void execute() { receiver.Action(); } }

    接收者(Receiver)角色:执行命令功能的相关操作,是具体命令对象业务的真正实现者。

    public class Receiver { public void Action(){ System.out.println("执行请求"); } }

    请求者(Invoker)角色:是请求的发送者,它通常拥有很多的命令对象,并通过访问命令对象来执行相关请求,它不直接访问接收者。

    public class Invoke { private Command command; public void executeCommand(){ System.out.println("调用者执行命令command..."); command.execute(); } public Command getCommand() { return command; } public void setCommand(Command command) { this.command = command; } }

    测试结果

    public class MainClass { public static void main(String[] args) { //发出一个请求 Receiver receiver = new Receiver(); //将请求告诉接收者 Command command =new ConcreteCommand(receiver); //执行具体的命令 Invoke invoke = new Invoke(); invoke.setCommand(command); invoke.executeCommand(); } }

    模式应用实例 使用组合模式和命令模式

    我们通过吃烧烤来看:

    抽象出命令:并且拥有接收者 烧烤师傅的实例对象

    public abstract class Command { protected Barbecuer receiver; public Command(Barbecuer receiver) { this.receiver = receiver; } /** * 执行命令 */ public abstract void execute(); }

    树叶构件具体的命令: 烤鸡翅

    public class BakeChickenWingCommand extends Command{ public BakeChickenWingCommand(Barbecuer receiver) { super(receiver); } @Override public void execute() { receiver.BakeChickenWing(); } }

    树叶构件具体的命令:烤羊肉串

    public class BakeMuttonCommand extends Command{ public BakeMuttonCommand(Barbecuer receiver) { super(receiver); } @Override public void execute() { receiver.BakeMutton(); } };

    树枝构件服务员: 记录 命令,告诉烧烤师傅,需要烤什么东西

    public class Waiter { private ArrayList<Command> children = new ArrayList<Command>(); //设置订单:记录命令 public void add(Command c) { children.add(c); } public void remove(Command c) { children.remove(c); } public Command getChild(int i) { return children.get(i); } public void execute(){ for(Object obj:children) { ((Command)obj).execute(); } } }

    烧烤师傅,烤羊肉串,烤鸡翅

    public class Barbecuer { public void BakeMutton() { System.out.println("烤羊肉串"); } public void BakeChickenWing(){ System.out.println("烤吃鸡翅"); } }

    测试:执行结果,相当于我去烧烤店 吃东西 告诉服务员我要吃什么,然后烧烤师傅给我烤什么

    public class MainClass { public static void main(String[] args) { //让烧烤师傅准备好,烤鸡翅,烤羊肉串 Barbecuer receiver = new Barbecuer(); Command command = new BakeChickenWingCommand(receiver); Command command2 = new BakeMuttonCommand(receiver); //服务员知道我要吃什么,告诉 烧烤师傅制作 Waiter waiter = new Waiter(); System.out.println("-----增加命令------"); waiter.add(command); waiter.add(command2); waiter.execute(); System.out.println("------删除命令-----"); waiter.remove(command2); waiter.execute(); } }

    命令模式的应用场景

    1,当系统需要将请求调用者与请求接收者解耦时,命令模式使得调用者和接收者不直接交互。 2,当系统需要随机请求命令或经常增加或删除命令时,命令模式比较方便实现这些功能。 3,当系统需要执行一组操作时,命令模式可以定义宏命令来实现该功能。 4,当系统需要支持命令的撤销(Undo)操作和恢复(Redo)操作时,可以将命令对象存储起来,采用备忘录模式来实现。

    Processed: 0.009, SQL: 9