内部工厂的静态工厂方法网关 - 代码味道?

时间:2023-02-02 22:26:23

Say I had a class that has a static factory method, like this:

假设我有一个具有静态工厂方法的类,如下所示:

 public class Table
 {
    public static Table OpenTable(string path)
    {
        ITableFactory fac = IoC.Resolve<ITableFactory>();
        return fac.OpenTable(path);
    }
 }

and a factory class that looks like this:

和一个看起来像这样的工厂类:

internal class TableFactory : ITableFactory
{
    internal Table OpenTable(string path)
    {
      //Check the path
      //Do some other stuff
      //return a new Table.
    }
}

Does this code smell bad to you?

这段代码对你来说味道不好吗?

EDIT: Another question: Is it a good idea to have a static method on the type that just forwards calls to the factory?

编辑:另一个问题:在只调用工厂调用的类型上有一个静态方法是一个好主意吗?

Some background: I used to have the TableFactory as public and make the user create a new one every time they needed to open a table but it felt like a long hall just to open a table. So I thought that I would make a static factory method on the Table class and make the factory class internal and just resolve it using IoC.

一些背景:我曾经将TableFactory作为公共场所,并让用户每次需要打开一张桌子时都会创建一个新的,但感觉就像打开桌子一样长的大厅。所以我认为我会在Table类上创建一个静态工厂方法,并使工厂类内部化,并使用IoC解决它。

4 个解决方案

#1


I don't think it's bad, per se, but perhaps a little unusual.

我认为这本身并不坏,但也许有点不寻常。

I would, however, present the table factory as a separate object to the user, and use that to create tables. Why ? It's a little more conventional, and it allows you the capability to be able to configure your factory in advance and use it for creating more than one table e.g.

但是,我会将表工厂作为单独的对象呈现给用户,并使用它来创建表。为什么?它更传统,它允许您能够提前配置工厂并使用它来创建多个表格,例如

TableFactory tf = new TableFactory();
tf.setWhatever();
tf.setWhatever2();
// ...etc...

// now create your tables based on the above.

Your code need not (necessarily) know anything about the table creation, other than the fact that it's been given a TableFactory (built and configured elsewhere)

您的代码不需要(必然)了解有关表创建的任何信息,除了它已被赋予TableFactory(在其他地方构建和配置)的事实

That may be overkill for what you're doing. But I've found it's a useful pattern to follow.

对于你正在做的事情,这可能有点过头了。但我发现这是一个有用的模式。

#2


That looks fine. I would however move fac out:

看起来很好。然而,我会移出:

 public class Table
 {
    private static readonly ITableFactory fac = IoC.Resolve<ITableFactory>();
    public static Table OpenTable(string path)
    {
        return fac.OpenTable(path);
    }
 }

#3


I don't think this is too bad... it's just a shortcut method that introduces no new dependencies.

我不认为这太糟糕了......它只是一种不会引入新依赖关系的快捷方法。

I know in ninject you could possibly do Kernel.Get<Table>(path) and avoid all this juggling.

我知道在ninject你可以做Kernel.Get

(路径)并避免所有这些杂耍。

#4


As far as I can tell, what you have here is an instance of the Service Locator pattern, since I assume that IoC is a type name, and Resolve is a static method on the IoC type. Whether your TableFactory is internal or not is of less concern.

据我所知,这里有一个服务定位器模式的实例,因为我假设IoC是一个类型名称,而Resolve是IoC类型的静态方法。您的TableFactory是否内部是不太重要的。

I consider Service Locator to be an anti-pattern, since it is totally opaque to the user of the API which dependencies need to be in place; thus, one could easily invoke Table.OpenTable in a context where the call to IoC.Resolve would throw, and the API gives you absolutely no clue that this is the case. You also get no compile-time checking.

我认为Service Locator是一个反模式,因为它对API的用户完全不透明,需要依赖于它们;因此,可以在调用IoC.Resolve的上下文中轻松调用Table.OpenTable,并且API绝对不会让您知道这种情况。您也没有编译时检查。

I know Martin Fowler originally described the Service Locator pattern, so it's a pretty harsh thing to call it an anti-pattern, but I know I'm not alone in this. YMMV.

我知道Martin Fowler最初描述了Service Locator模式,所以将它称为反模式是一件相当苛刻的事情,但我知道我并不孤单。因人而异。

#1


I don't think it's bad, per se, but perhaps a little unusual.

我认为这本身并不坏,但也许有点不寻常。

I would, however, present the table factory as a separate object to the user, and use that to create tables. Why ? It's a little more conventional, and it allows you the capability to be able to configure your factory in advance and use it for creating more than one table e.g.

但是,我会将表工厂作为单独的对象呈现给用户,并使用它来创建表。为什么?它更传统,它允许您能够提前配置工厂并使用它来创建多个表格,例如

TableFactory tf = new TableFactory();
tf.setWhatever();
tf.setWhatever2();
// ...etc...

// now create your tables based on the above.

Your code need not (necessarily) know anything about the table creation, other than the fact that it's been given a TableFactory (built and configured elsewhere)

您的代码不需要(必然)了解有关表创建的任何信息,除了它已被赋予TableFactory(在其他地方构建和配置)的事实

That may be overkill for what you're doing. But I've found it's a useful pattern to follow.

对于你正在做的事情,这可能有点过头了。但我发现这是一个有用的模式。

#2


That looks fine. I would however move fac out:

看起来很好。然而,我会移出:

 public class Table
 {
    private static readonly ITableFactory fac = IoC.Resolve<ITableFactory>();
    public static Table OpenTable(string path)
    {
        return fac.OpenTable(path);
    }
 }

#3


I don't think this is too bad... it's just a shortcut method that introduces no new dependencies.

我不认为这太糟糕了......它只是一种不会引入新依赖关系的快捷方法。

I know in ninject you could possibly do Kernel.Get<Table>(path) and avoid all this juggling.

我知道在ninject你可以做Kernel.Get

(路径)并避免所有这些杂耍。

#4


As far as I can tell, what you have here is an instance of the Service Locator pattern, since I assume that IoC is a type name, and Resolve is a static method on the IoC type. Whether your TableFactory is internal or not is of less concern.

据我所知,这里有一个服务定位器模式的实例,因为我假设IoC是一个类型名称,而Resolve是IoC类型的静态方法。您的TableFactory是否内部是不太重要的。

I consider Service Locator to be an anti-pattern, since it is totally opaque to the user of the API which dependencies need to be in place; thus, one could easily invoke Table.OpenTable in a context where the call to IoC.Resolve would throw, and the API gives you absolutely no clue that this is the case. You also get no compile-time checking.

我认为Service Locator是一个反模式,因为它对API的用户完全不透明,需要依赖于它们;因此,可以在调用IoC.Resolve的上下文中轻松调用Table.OpenTable,并且API绝对不会让您知道这种情况。您也没有编译时检查。

I know Martin Fowler originally described the Service Locator pattern, so it's a pretty harsh thing to call it an anti-pattern, but I know I'm not alone in this. YMMV.

我知道Martin Fowler最初描述了Service Locator模式,所以将它称为反模式是一件相当苛刻的事情,但我知道我并不孤单。因人而异。