【问题标题】:factory pattern is it okay to use it this way?工厂模式可以这样使用吗?
【发布时间】:2023-03-23 20:34:01
【问题描述】:

在我的程序中,一些对象需要其他对象(依赖),我使用 Factory 作为我的创建模式。

现在,我该如何解决一个简单的依赖问题?

这是我为解决问题所做的一个示例。我想知道将所需的对象发送到 Create 方法是不是大错特错。

//AbstractBackground
// - SpecialBackground
// - ImageBackground
// - NormalBackground
class Screen{
    List<AbstractBackground> list;
    Cursor cursor;
    ContentManager content;

    public void load(string[] backgroundTypes){
        //is this okay? --------------->
        AbstractBackground background = BackgroundFactory.Create(backgroundTypes[0], cursor, content);
        list.add(background);
    }
}

class BackgroundFactory{
    static public AbstractBackground Create(string type, Cursor cursor, ContentManager content){

        if( type.Equals("special") ){
            return new SpecialBackground(cursor, content);
        }

        if( type.Equals("image") ){
            return new ImageBackground(content);
        }

        if( type.Equals("normal") ){
            return new NormalBackground();
        }
    }
}

【问题讨论】:

  • 为什么会出错?不是。
  • 我想知道这一点,因为我对现实生活中的工厂模式没有太多经验。

标签: c# design-patterns dependencies factory


【解决方案1】:

它是功能性的,但是如果添加更多类型,它可能会变得很麻烦。
根据我个人对简单工厂的偏好,实现将是:

enum BackgroundFactoryType
{
  Special,
  Image,
  Normal,
}

static class BackgroundFactory{

  static Dictionary<BackgroundFactoryType, Func<Cursor, ContentManager, AbstractBackground>> constructors;

  static BackgroundFactory()
  {
    //initialize the constructor funcs
    constructors = new Dictionary<BackgroundFactoryType, Func<Cursor, ContentManager, AbstractBackground>>();
    constructors.Add(BackgroundFactoryType.Special, (cursor, content) => new SpecialBackground(cursor, content));
    constructors.Add(BackgroundFactoryType.Image, (_, content) => new ImageBackground(content));
    constructors.Add(BackgroundFactoryType.Normal, (_, __) => new NormalBackground());
  }

  static public AbstractBackground Create(BackgroundFactoryType type, Cursor cursor, ContentManager content)
  {
    if (!constructors.ContainsKey(type))
      throw new ArgumentException("the type is bogus");

    return constructors[type](cursor, content);
  }
}

或者你可以简单地这样做:

static class BackgroundFactory{

  static public AbstractBackground Create(BackgroundFactoryType type, Cursor cursor, ContentManager content)
  {
    switch (type)
    {
      case BackgroundFactoryType.Special:
        return new SpecialBackground(cursor, content);
      case BackgroundFactoryType.Image:
        return new ImageBackground(content);
      case BackgroundFactoryType.Normal:
        return new NormalBackground();
      default:
        throw new ArgumentException("the type is bogus");
    }
  }
}

这种方法的一个很好的副作用是,只需一点点工作就可以使这个东西配置驱动而不是硬编码。

【讨论】:

  • 既然BackgroundFactory只有静态成员,不应该标记为static吗?
  • 是的,它应该,还有构造函数字典 :)
【解决方案2】:

在您的代码中没有什么比这更丑陋的了,除了如果您的依赖关系树增长,您创建的工厂方法将变得复杂。 为了分解具有各种和明确的依赖关系的类型,您最好选择基于IoC 的工厂。通过在容器中注册依赖项,您将拥有具有所需依赖项的自动注入构造函数。

【讨论】:

  • 我可以问一个例子吗?我遇到过很多例子,但有些例子似乎太复杂而无法解决一些简单的问题,或者我不知道它是否能解决我想做的事情的例子。
  • @user658091 如果您的架构应该保持简单,请保持不变。如前所述,您的代码目前没有任何问题。
【解决方案3】:

简单的答案,看起来不错。如果您抽象地考虑这一点,您就是通过 create 方法将对象注入到构造函数中。这种技术没有问题,我推荐它。

以后,如果需要更改实现,可以根据需要创建其他创建方法,而不会破坏任何内容。

【讨论】:

    猜你喜欢
    • 2011-04-20
    • 1970-01-01
    • 2020-12-27
    • 1970-01-01
    • 2012-03-08
    • 2012-10-29
    • 1970-01-01
    • 2022-01-03
    • 2020-09-05
    相关资源
    最近更新 更多