【问题标题】:Is it still factory method?还是工厂方法吗?
【发布时间】:2014-09-16 04:49:16
【问题描述】:

我发现的所有示例通常都基于枚举,它提供了返回正确的类。我需要一些对类的类型有一般反应的东西,并且通过在每次调用时给它新的参数来控制新对象的构造函数。

还是工厂方法吗?是很好的解决方案吗?我可以这样玩设计模式吗?也许有更好的解决方案可以提供?

using System;

namespace ConsoleApplication1
{
  public abstract class Strategy
  {
    protected int Init;
    private static int _initA = 3;
    private static int _initB = 42;

    public static Strategy StrategyFactory(Strategy strategyType)
    {
      var tempStrategyA = strategyType as StrategyA;
      if (tempStrategyA != null)
      {
        _initA++;
        return new StrategyA(_initA);
      }

      var tempStrategyB = strategyType as StrategyB;
      if (tempStrategyB != null)
      {
        _initB = _initA * 2;
        return new StrategyB(_initB);
      }

      throw new ArgumentException();
    }
  }

  public class StrategyA : Strategy
  {
    public StrategyA(int init)
    {
      Init = init*2;
    }
  }

  public class StrategyB : Strategy
  {
    public StrategyB(int init)
    {
      Init = init*3;
    }
  }
}

【问题讨论】:

  • 虽然这技术上是一种工厂方法,但它结合了一个很好的ick案例。考虑让策略本身处理特定于策略的操作;虽然特定类型的调度并不总是坏事,但在这个例子中它确实没有位置。
  • 错了?我试图将其分离,并将这种责任转移到战略本身。但经过多次尝试,我失败了,我发现这可能是最好的解决方案。
  • 对我来说,工厂返回与其接受的类型相同的类型是没有意义的。我使用工厂方法的唯一一次是返回调用者不知道的类型。
  • 为什么需要工厂?你到底想完成什么?
  • 这有点太抽象了。

标签: c# design-patterns factory-pattern


【解决方案1】:

在我看来,您实际上希望为每种策略建立一个不同的工厂。如果您想管理工厂创建的对象的生命周期,或者管理用于构建各种类型的依赖项/参数,工厂是很好的选择。

战略工厂的定义

interface IStrategyFactory
{
    public Strategy Create(int value);
}

class StrategyAFactory : IStrategyFactory
{
    public Strategy Create(int value)
    {
        return new StrategyA(value);
    }
}

class StrategyBFactory : IStrategyFactory
{
    public Strategy Create(int value)
    {
        return new StrategyB(value);
    }
}

用法

class MyController : ApiController
{
    private IStrategyFactory _factory;

    public MyController(IStrategyFactory factory)
    {
        _factory = factory;
    }

    public HttpResponseMessage Get(int value)
    {
        // here we don't care what exact strategy is used, this is good!
        var strategy = _factory.Create(value);

        var newValue = strategy.Calculate();

        return new HttpResponseMessage(newValue);
    }
}

【讨论】:

  • 或者如果所有策略的创建方式都相同,请使用 Matías Fidemraizer 的答案 (Activator.CreateInstance)。
  • 好的,我试试这个。我需要带参数的构造函数。
【解决方案2】:

这是一个很奇怪的工厂方法。查看您的工厂方法签名:

// "strategyType"? It's not a type, but an object reference
public static Strategy StrategyFactory(Strategy strategyType)

在 .NET 中有一个名为 Type 的类,它表示某些给定类型的类型元数据。您可以使用typeof 运算符或Object.GetType() 方法获得它。

你的工厂方法应该是:

public static Strategy StrategyFactory(Type strategyType)

你可以使用反射来实例化一个类型:

Activator.CreateInstance(strategyType);

还有一个CreateInstance 重载到give constructor arguments

泛型呢?

自从 .NET 2.0(我们谈论很多年前!)以来,.NET 就有了泛型。总之,它们提供了一种方法来指定没有具体类型的参数,直到某个方法或类型在某处实际声明或使用,并提供了哪个实际类型将具有整个参数。

例如,这将是一种现代工厂方法:

// "where ..." is a generic constraint which defines that the given generic
// argument must be Strategy or a derived class of Strategy, and it must
// have a public parameterless constructor
public TStrategy Create<TStrategy>() where TStrategy : Strategy, new()
{
    TStrategy strategy = new TStrategy();

    // more stuff

    return strategy;
}

现在你可以这样使用它了:

MyStrategy strategy = StrategyFactory.Create<MyStrategy>();

我可以给你一个泛型大师班,但这超出了你的问题范围。无论如何,我给了你一个关于如何使用正确的工具来建造工厂的线索/提示。 You can learn more about generics in MSDN.

【讨论】:

  • @user2864740 这是一个非常糟糕的主意,不是吗?我的意思是,使用实例的状态......这很丑
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-07-20
  • 1970-01-01
  • 1970-01-01
  • 2011-05-16
  • 2011-01-05
  • 2019-08-23
  • 1970-01-01
相关资源
最近更新 更多