65.9K
CodeProject 正在变化。 阅读更多。
Home

弥合菜单控件与命令模式之间的差距

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.50/5 (3投票s)

2008年6月28日

CPOL

3分钟阅读

viewsIcon

34621

downloadIcon

241

本文阐述了一个将命令模式应用于 ASP.NET 菜单控件的案例

CommandMenuDemo

引言

将设计模式应用于实际软件开发非常有趣,只有当你尝试应用时,才能掌握教科书中所述的优点。本文阐述了一个将命令模式应用于 ASP.NET 菜单控件的案例。我还演示了使用 Delegate 的通用命令的实现,这样开发人员就可以“重用”它来实现他们的实现,而无需创建新的命令类。

问题描述

所有 ASP.NET 菜单控件最常用于显示网站的超链接结构(即站点地图)。但是,您可能希望使用它来实现以下场景:在用户单击客户端上的一个菜单项后,您的程序将根据单击的菜单项(例如 MenuItem.Text)在服务器端做出反应。让我们以 RadMenu(在 TelerikRadControls 中)为例;您不需要知道 RadMenu 的内部细节即可继续(下面讨论的思想可以应用于各种菜单控件)。最直观的解决方案通常会导致如下所示的 “if---else” 结构的实现

protected void DefaultRadMenu_ItemClick(object sender, Telerik.Web.UI.RadMenuEventArgs e)
{
             RadMenuItem selItem = e.Item;

             if(selItem.Text == "Apple")
             {
                 doApple();
             }
             else if(selItem.Text == "Orange")
             {
                 doOrange();
             }
             else
             {
                 // do something
             }
}

DefaultRadMenu_ItemClick 是任何被点击的菜单项的处理程序 (postback=true)。如果您看过讨论设计模式或代码可维护性的文章,您应该已经闻到了问题的气味:一旦出现一个名为 lemon 的新项,您不仅需要实现 doLemon(),还必须修改 “ifelse” 结构。此外,如果您的应用程序包含许多页面,这些页面分别使用 RadMenu 来做不同的事情,您必须在整个应用程序中单调地重复这种代码模式。这时,命令模式就能派上用场。

将命令模式应用于菜单控件

命令模式 是 OOP 中一种非常流行的设计模式。如果您不熟悉它,请自行 Google!在本文中,命令模式被设计为一个接口 IMenuItemCommand(如下所示),我们提供了一个默认的通用命令:稍后描述的 BaseMenuItemCommand 类;当然,您可以通过应用程序实现您的 IMenuItemCommand 具体类来进行救援。IMenuItemCommand 简单地定义了一个命令的行为,如下所示

public interface IMenuItemCommand
{
   // Execute Command
   void Execute();

   // Describe the command
   string Text { get; set;}
}

Execute() 是服务器端反应由您自定义的地方。使用命令模式,我们可以实现一个通用的 ItemClicked 处理程序,可以在任何地方重用

protected void DefaultRadMenu_ItemClicked
    (object sender, Telerik.Web.UI.RadMenuEventArgs e)
{
             RadMenuItem selItem = e.Item;
             IMenuItemCommand itemCmd = selItem.DataItem as IMenuItemCommand;

             if (itemCmd != null)
             {
                 itemCmd.Execute();
             }
}

请注意,为了让前面的 DefaultRadMenu_ItemClicked 工作,我们必须在构建 RadMenu 时将一个具体的 IMenuItemCommand 对象(即 BaseMenuItemCommand)分配到 RadMenuItem.DataItem

RadMenuItem item1 = new RadMenuItem("Hello");

item1.DataItem = new BaseMenuItemCommand (
delegate {
//do something on server-side;
});

RadMenu1.Items.Add(item1);

上面的代码片段也演示了通用命令 BaseMenuItemCommand 的使用。构造函数中的参数是一个 delegate(即以下代码中的 ToDoDelegate),它在 BaseMenuItemCommand.Execute() 中执行,如下所示

    public void Execute()
    {
        if(ToDo != null)
        {
            ToDo();
        }
    }

    …

    private ToDoDelegate _toDo;

    public ToDoDelegate ToDo
    {
        get { return _toDo; }
        set { _toDo = value; }
    }

    public delegate void ToDoDelegate();

BaseMenuItemCommand 的目的是让您重用这个类来实现各种命令。想象一下,如果您有 10 个菜单项,它们的命令无法在其他地方重用。您是否愿意实现 10 个单独的 IMenuItemCommand 类来使您的系统复杂化?

总之,将命令模式应用于菜单控件消除了使用菜单的页面中的 “if-else” 结构。此外,命令可以通过其他菜单控件重用。更重要的是,使用命令模式的代码比没有使用命令模式的代码更加一致,从而产生更具可维护性的代码。

结论

我希望这个代码示例可以帮助您减少重复的代码,当您决定使用菜单控件来实现本文中描述的场景时。虽然我们专门使用 RadMenu 来演示命令模式的应用,但这个概念绝对可以应用于其他菜单控件。

历史

  • 2008 年 6 月 24 日:提交了初始文章
© . All rights reserved.