代码之家  ›  专栏  ›  技术社区  ›  Pat O

寻找命令模式的替代方案

  •  2
  • Pat O  · 技术社区  · 14 年前

    我已经写了一个测试自动化框架。框架是围绕对象和操作构建的。对象可能是文本框。它的操作可能是set text、clear、verify text、verify enabled等。框架独立于acitons,因此我们可以随着时间的推移添加更多操作,而不必对框架本身负责。我考虑了两种行动方法。首先是使用命令模式。在这种情况下,我会有一个类似这样的界面:

    public interface IAction
    {
    void Execute(StringDictionary properties);
    }

    问题是我们最终会得到许多这样的命令类。

    public class SetTextAction : IAction
    {
    public void Execute(StringDictionary properties)
    {
    }
    }

    public class ClearAction : IAction
    {
    public void Execute(StringDictionary属性)
    {
    }
    }

    public class VerifyTextAction : IAction
    {
    public void Execute(StringDictionary属性)
    {
    }
    }

    public class VerifyEnabledAction : IAction
    {
    public void Execute(StringDictionary属性)
    {
    }
    }

    此外,任何共享代码都需要在另一个类中。它似乎增加了代码中的信噪比。

    我提出的另一种选择是使用一个实用程序类作为操作的类型和方法。结果是这样的:

    public class TextboxActions
    {
    public static void set-text(StringDictionary properties)
    {
    }
    public static void clear(StringDictionary properties)
    {
    }
    public static void verify-text(StringDictionary properties)
    {
    }
    public static void verify-enabled(StringDictionary properties)
    {
    }
    }

    这有一个优点,就是文本框的代码都在一起。此外,多个操作共用的任何代码都可以在同一个类中。不幸的是,这种方法要求我使用反射来“找到”操作方法。这显然不是类型安全的,而且可能非常耗时。它已经足够慢了,我已经添加了一个缓存,所以我不必再找到相同的动作两次,但是这增加了代码的复杂性。

    这两种解决方案中的任何一种都有效,但它们都具有不受欢迎的特性。有人能提出解决这个问题的另一种方法吗?

    2 回复  |  直到 11 年前
        1
  •  1
  •   Brent Arias    14 年前

    为什么不能使用委托?也就是说,遵循一级函数方法。如果您正在考虑使单个IAction成为具体实例,那么您可能只需要一个具体的函数指针。这样,您的代码可以继续看起来像上一个示例,但不使用反射。

        2
  •  0
  •   Vitalogy    14 年前

    委托方式会是这样的吗?

       public abstract class TestObject
    {
        public delegate void TestAction(StringDictionary properties);
    
        public void AddTestAction(TestAction action)
        {
        }
    
        public void Execute()
        {
            // foreach test action etc.
        }
    }
    
    public class TestTextBox : TestObject
    {
        TestTextBox()
        {
            Initialize();
        }
    
        private void Initialize()
        {
            AddTestAction(new TestObject.TestAction(this.SetText));
            AddTestAction(new TestObject.TestAction(this.Clear));
        }
    
        public void SetText(StringDictionary properties)
        {
        }
    
        public void Clear(StringDictionary properties)
        {
        }
    }