3

我第一次使用这种模式,并使用 C#。

我只是想检查这是正确的实现。
我在 Winform 上有一个按钮,当单击该按钮时,它将以特定格式输出一些数据,通过从下拉框中选择来定义。现在这可能会在未来发生变化,因此我使用策略模式来封装变化。

我有一个“策略接口”,它只公开一个方法:“显示数据()”。

在我的按钮上单击我使用以下代码:

private void ConfirmButton_Click(object sender, EventArgs e)
    {
        IViewData viewData;

        switch (outputMedia)
        {
            case "Excel":
                viewData = new ExcelOutput(operation, study);
                viewData.DisplayData();
                break;
            case "Spotfire":
                viewData = new SpotfireOutput(operation, study);
                viewData.DisplayData();
                break;
        }


    }

这是使用此模式的可接受方式吗?显然,如果识别出额外的输出媒体,那么我将简单地创建一个新的子类并在 switch 语句中添加一个额外的“case”。

谢谢。

4

3 回答 3

4

使用策略的正确方法是将IViewData对象的创建与其使用分开。创建本身可能由工厂方法处理。然后你可以IViewData在一个单独的位置使用created,它完全不知道对象的具体类。

例如

private IViewData CreateViewData()
{
    IViewData viewData;

    switch (outputMedia)
    {
        case "Excel":
            viewData = new ExcelOutput(operation, study);
            break;
        case "Spotfire":
            viewData = new SpotfireOutput(operation, study);
            break;
    }
    return viewData;
}

...

private void ConfirmButton_Click(object sender, EventArgs e)
{
    IViewData viewData = CreateViewData();

    viewData.DisplayData();
}

现在,您可以通过重构工厂方法进一步改进解决方案。您可以决定使用 aDictionary而不是 a switch,或者只创建一次视图数据对象并缓存它们,或者(如您所建议的)用依赖注入替换它......

于 2011-02-14T12:50:28.573 回答
2

首先,您可以移出viewData.DisplayData();开关。无需为每种情况重复。并且能够以DisplayData相同的方式调用它们是您首先介绍该接口的重点。

以相同的方式传递参数case看起来也有点重复。所以也许使用 aDictionary<string,Func<Operation,Study,IViewData>>代替。但是如果不同的类需要不同的构造函数,这是行不通的。

于 2011-02-14T12:51:51.447 回答
1

您应该将 switch 语句移到它自己的方法中,最好是在某个控制器类上。这意味着当您需要 IViewData 对象时,您不必再次重新编写开关代码。

private void ConfirmButton_Click(object sender, EventArgs e)
{
    IViewData viewData = ViewDataController.GetViewDataController(outputMedia, operation, study);

   viewData.DisplayData();

}

然后在你的控制器中:

 public class ViewDataController
 {
    public static IViewData GetViewDataController(string outputMedia, string operation, string study)
    {
      IViewData viewData = null;

      switch (outputMedia)
      {
        case "Excel":
            viewData = new ExcelOutput(operation, study);
            break;
        case "Spotfire":
            viewData = new SpotfireOutput(operation, study);
            break;
      }
      return viewData;
     }

这将允许您在整个应用程序中重用相同的代码,并且如果您需要在 switch 语句中添加任何条目,那么您只需在一个地方进行。

于 2011-02-14T13:00:44.193 回答