命令模式(Command Pattern)是一种数据驱动的设计模式,它属于行为型模式。请求以命令的形式包裹在对象中,并传给调用对象。
调用对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,该对象执行命令。
意图:将一个请求封装成一个对象,从而使您可以用不同的请求对客户进行参数化。
主要解决:在软件系统中,行为请求者与行为实现者通常是一种紧耦合的关系.
何时使用:将"行为请求者"与"行为实现者"解耦,将一组行为抽象为对象,可以实现二者之间的松耦合。
如何解决:通过调用者调用接受者执行命令,顺序:调用者→命令→接受者。
关键代码:定义三个角色:1、received 真正的命令执行对象 2、Command 3、invoker 使用命令对象的入口
优点: 1、降低了系统耦合度。 2、新的命令可以很容易添加到系统中去。
缺点:使用命令模式可能会导致某些系统有过多的具体命令类。
使用场景:认为是命令的地方都可以使用命令模式,比如: 1、GUI 中每一个按钮都是一条命令。 2、模拟 CMD。
注意事项:系统需要支持命令的撤销(Undo)操作和恢复(Redo)操作,也可以考虑使用命令模式,见命令模式的扩展。
命令模式五个角色,它们分别是:
客户角色:发出一个具体的命令并确定其接受者。
命令角色:声明了一个给所有具体命令类实现的抽象接口
具体命令角色:定义了一个接受者和行为的弱耦合,负责调用接受者的相应方法。
请求者角色:负责调用命令对象执行命令。
接受者角色:负责具体行为的执行。
该实例基于WPF实现,直接上代码,下面为三层架构的代码。
一 Model
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 设计模式练习.Model.命令模式
{
//实际命令实现者
public class ConcreteCommand : MyCommand
{
public ConcreteCommand(Receiver receiver) : base(receiver)
{
}
public override void Action()
{
//调用接收的方法,因为执行命令的是学生
_receiver.Run();
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 设计模式练习.Model.命令模式
{
//实际命令实现者
public class ConcreteCommand2 : MyCommand2
{
public ConcreteCommand2(Receiver2 receiver) : base(receiver)
{
}
public override void Action()
{
//调用接收的方法,因为执行命令的是学生
_receiver.Lern();
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 设计模式练习.Model.命令模式
{
//实际命令实现者
public class ConcreteCommand3 : MyCommand3
{
public ConcreteCommand3(Receiver3 receiver) : base(receiver)
{
}
public override void Action()
{
//调用接收的方法,因为执行命令的是学生
_receiver.Swim();
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 设计模式练习.Model.命令模式
{
//实际命令实现者
public class ConcreteCommand4 : MyCommand4
{
public ConcreteCommand4(Receiver4 receiver) : base(receiver)
{
}
public override void Action()
{
//调用接收的方法,因为执行命令的是学生
_receiver.Sleep();
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 设计模式练习.Model.命令模式
{
//1,定义命令发送者
public class Invoke
{
private MyCommand _command;
public Invoke(MyCommand myCommand)
{
this._command = myCommand;
}
//执行命令
public void ExecuteCommand()
{
_command.Action();
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 设计模式练习.Model.命令模式
{
//1,定义命令发送者
public class Invoke2
{
private MyCommand2 _command;
public Invoke2(MyCommand2 myCommand)
{
this._command = myCommand;
}
//执行命令
public void ExecuteCommand()
{
_command.Action();
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 设计模式练习.Model.命令模式
{
//1,定义命令发送者
public class Invoke3
{
private MyCommand3 _command;
public Invoke3(MyCommand3 myCommand)
{
this._command = myCommand;
}
//执行命令
public void ExecuteCommand()
{
_command.Action();
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 设计模式练习.Model.命令模式
{
//1,定义命令发送者
public class Invoke4
{
private MyCommand4 _command;
public Invoke4(MyCommand4 myCommand)
{
this._command = myCommand;
}
//执行命令
public void ExecuteCommand()
{
_command.Action();
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 设计模式练习.Model.命令模式
{
//2,定义命令抽象类
public abstract class MyCommand
{
//命令需要知道接收者是谁,所以需要指定receiver
public Receiver _receiver;
public MyCommand(Receiver receiver)
{
this._receiver = receiver;
}
//命令执行方法
public abstract void Action();
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 设计模式练习.Model.命令模式
{
//2,定义命令抽象类
public abstract class MyCommand2
{
//命令需要知道接收者是谁,所以需要指定receiver
public Receiver2 _receiver;
public MyCommand2(Receiver2 receiver)
{
this._receiver = receiver;
}
//命令执行方法
public abstract void Action();
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 设计模式练习.Model.命令模式
{
//2,定义命令抽象类
public abstract class MyCommand3
{
//命令需要知道接收者是谁,所以需要指定receiver
public Receiver3 _receiver;
public MyCommand3(Receiver3 receiver)
{
this._receiver = receiver;
}
//命令执行方法
public abstract void Action();
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 设计模式练习.Model.命令模式
{
//2,定义命令抽象类
public abstract class MyCommand4
{
//命令需要知道接收者是谁,所以需要指定receiver
public Receiver4 _receiver;
public MyCommand4(Receiver4 receiver)
{
this._receiver = receiver;
}
//命令执行方法
public abstract void Action();
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 设计模式练习.Model.命令模式
{
//3,定义命令接收者
public class Receiver
{
public string CommandInfo { get; set; }
public void Run()
{
CommandInfo = "跑步命令被成功执行!!!";
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 设计模式练习.Model.命令模式
{
//3,定义命令接收者
public class Receiver2
{
public string CommandInfo { get; set; }
public void Lern()
{
CommandInfo = "学习命令被成功执行!!!";
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 设计模式练习.Model.命令模式
{
//3,定义命令接收者
public class Receiver3
{
public string CommandInfo { get; set; }
public void Swim()
{
CommandInfo = "游泳命令被成功执行!!!";
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 设计模式练习.Model.命令模式
{
//3,定义命令接收者
public class Receiver4
{
public string CommandInfo { get; set; }
public void Sleep()
{
CommandInfo = "睡觉命令被成功执行!!!";
}
}
}
二 View
<Window x:Class="设计模式练习.View.命令模式.CommandWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:设计模式练习.View.命令模式"
mc:Ignorable="d"
Title="CommandWindow" Height="450" Width="800">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock TextWrapping="Wrap" Grid.Column="0" Text="{Binding Txt}"/>
<Grid Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Button Content="发布跑步命令" Grid.Row="0" Command="{Binding runCommand}"/>
<Button Content="发布学习命令" Grid.Row="1" Command="{Binding studyCommand}"/>
<Button Content="发布游泳命令" Grid.Row="2" Command="{Binding swimCommand}"/>
<Button Content="发布睡觉命令" Grid.Row="3" Command="{Binding sleepCommand}"/>
</Grid>
</Grid>
</Window>
三 ViewModel
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using 设计模式练习.Model.命令模式;
namespace 设计模式练习.ViewModel.命令模式
{
partial class CommandWindow_ViewModel : ObservableObject
{
[ObservableProperty]
private string txt;
[RelayCommand]
private void run()
{
//实例化命令发送者、接收者、执行者
Receiver receiver = new Receiver();
MyCommand command =new ConcreteCommand(receiver);
Invoke invoke = new Invoke(command);
//发布命令
invoke.ExecuteCommand();
Txt = receiver.CommandInfo;
}
[RelayCommand]
private void study()
{
//实例化命令发送者、接收者、执行者
Receiver2 receiver = new Receiver2();
MyCommand2 command = new ConcreteCommand2(receiver);
Invoke2 invoke = new Invoke2(command);
//发布命令
invoke.ExecuteCommand();
Txt = receiver.CommandInfo;
}
[RelayCommand]
private void swim()
{
//实例化命令发送者、接收者、执行者
Receiver3 receiver = new Receiver3();
MyCommand3 command = new ConcreteCommand3(receiver);
Invoke3 invoke = new Invoke3(command);
//发布命令
invoke.ExecuteCommand();
Txt = receiver.CommandInfo;
}
[RelayCommand]
private void sleep()
{
//实例化命令发送者、接收者、执行者
Receiver4 receiver = new Receiver4();
MyCommand4 command = new ConcreteCommand4(receiver);
Invoke4 invoke = new Invoke4(command);
//发布命令
invoke.ExecuteCommand();
Txt = receiver.CommandInfo;
}
}
}