行为模式:在 C# 中实现命令模式






3.38/5 (16投票s)
用 C# 编写命令模式(真实示例)。
引言
本文展示了如何在实际案例中使用 C# 2.0 和 .NET 实现行为型命令模式。
什么是设计模式?
设计模式是软件设计中常见问题的通用可重用解决方案。设计模式不是可以直接转换为代码的完整设计。它是用于解决可在许多不同情况下使用的问题的描述或模板。
什么是行为型设计模式?
行为型设计模式是识别对象之间常见通信模式并实现这些模式的设计模式。 通过这样做,这些模式提高了执行通信的灵活性。
目的
命令模式是一种设计模式,其中对象用于表示动作。 命令对象封装一个动作及其参数。
结构
- 命令,声明一个用于执行操作的接口。
- 具体命令,定义 Receiver 对象和操作之间的绑定。 通过调用 Receiver 上的相应操作来实现 Execute。
- 客户端,创建具体命令对象并设置其接收者。
- 调用者,要求命令执行请求。
- 接收者,知道如何执行与执行请求相关的操作。
真实案例
此示例演示了如何使用命令模式填充不同的控件。 每个控件的来源是自定义资源文件。
注意:每个控件都实现不同的绑定逻辑,但在命令模式中,这对客户端是隐藏的。
让我们编写命令的代码
- 编写命令。
- 编写具体命令。
- 编写“通用接收者”。
- 编写“调用者”。
此接口包含调用以执行 Receiver 代码的方法
// Command
public interface ICommand    
{
    void Execute();
}
此类定义了 Receiver 和 Execute 命令操作之间的绑定
// Concrete Command
public class ConcreteCommand: ICommand
{
    private IFiller _filler;
    public ConcreteCommand(IFiller filler)
    {
        _filler = filler;
    }
    public void Execute()
    {
        _filler.Fill();
    }
}
此接口包含所有控件绑定的通用方法。 此接口为所有想要使用命令的控件提供了一个通用方面。
public interface IFiller
{
    void Fill();
}
此类允许为每个实现 IFiller 的项目调用 Execute 方法。
// Invoker
public class Invoker
{
    private IFiller[] _filler;
    public Invoker(IFiller[] filler)
    {
        _filler = filler;
    }
    public void Execute()
    {
        ICommand command;
        foreach (IFiller item in _filler)
        {
            command = new ConcreteCommand(item);
            command.Execute();
        }
    }
}
让我们编写客户端的代码
- 编写接收者。
- 编写客户端。
以下自定义控件(CustomLabel、CustomListBox、CustomListView)是从 Label、ListBox 和 ListView 控件派生的控件。
这些控件实现了“通用接收者”接口来实现绑定逻辑
// Receiver
public class CustomLabel: Label, IFiller
{
    public void Fill()
    {
        this.Text = Resources.ResourceManager.GetString(this.Name);
    }
}
// Receiver
public class CustomListBox: ListBox, IFiller
{
    public void Fill()
    {
        this.Items.Clear();
        int index=1;
        string item = Resources.ResourceManager.GetString(
            string.Format("{0}{1}{2}", 
            this.Name, 
            "_", 
            index.ToString()));
        while (item != null)
        {
            this.Items.Add(item);
            index++;
            item = Resources.ResourceManager.GetString(
            string.Format("{0}{1}{2}",
            this.Name,
            "_",
            index.ToString()));
        }
    }
}
// Receiver
public class CustomListView: ListView, IFiller
{
    public void Fill()
    {
        this.Columns.Clear();
        int index = 1;
        string item = Resources.ResourceManager.GetString(
             string.Format("{0}{1}{2}",
             this.Name,
             "_",
             index.ToString()));
        while (item != null)
        {
            this.Columns.Add(item);
            index++;
            item = Resources.ResourceManager.GetString(
            string.Format("{0}{1}{2}",
            this.Name,
            "_",
            index.ToString()));
        }
    }
}
客户端调用调用者,调用者调用命令。
在表单中插入自定义控件后,我编写了递归函数来查找实现 IFiller 的控件,然后我在 IFiller 控件的 List 上调用 Invoker。
public partial class Form1 : Form
{
    private List<ifiller> _filler;
    public Form1()
    {
        InitializeComponent();
    }
    private void Form1_Load(object sender, EventArgs e)
    {
        _filler = new List();
        searchControl(this.Controls);
        
        // Client
        Invoker invoker = new Invoker(_filler.ToArray());
        invoker.Execute();
    }
    private void searchControl(Control.ControlCollection ctrCollection)
    {
        foreach (Control ctr in ctrCollection)
        {
            IFiller fctr = ctr as IFiller;
            if (fctr != null)
                _filler.Add(fctr);
            if (ctr.Controls.Count > 0)
                searchControl(ctr.Controls);
        }
    }
} 
历史
这是此代码的第一次迭代。 请提供任何反馈,说明您是否使用过它,或者有人发现它有任何问题!


