java中的工厂模式

发布于 2024-07-24 23:08:19 字数 976 浏览 7 评论 0 原文

我正在使用据称使用工厂模式的 java 代码,但我并不完全相信该模式。

我的代码是这样做的:

// the factory
class SomeFactoryImpl {
   Set<SomeClass> getSomeListOfObjects();
}

在代码中的某个地方:

{ ...
    SomeFactory factory = new SomeFactoryImpl();
    Set<SomeClass> list = factory.getSomeListOfObjects();
}

我正在思考的一点是,如果工厂类没有静态 create() 方法,那么将需要实例化一个工厂,这IMO 应该和实例化对象本身一样复杂。

我认为这样的工厂可以返回要生成的对象集合的论点还不够好。 我觉得如果在实际从工厂创建对象之前需要创建工厂实例,那么可以有更干净的解决方法。

我觉得create方法最好是工厂类的静态方法。 但我也确信我的观点并不完全“正确”。

那么 SO 社区能否举例说明实例化 Factory 对象比使用静态创建方法更好?

另外,我遇​​到了类似问题的答案,其中列出了这些链接和答案:所以我需要清楚地了解 FactoryMethodPatternFactoryMethodCreationMethod 以及代码示例。

I was working with java code that is supposedly using the Factory pattern, but I'm not completely convinced by the pattern.

My code does this:

// the factory
class SomeFactoryImpl {
   Set<SomeClass> getSomeListOfObjects();
}

And somewhere in the code:

{ ...
    SomeFactory factory = new SomeFactoryImpl();
    Set<SomeClass> list = factory.getSomeListOfObjects();
}

The point I'm pondering is, if factory classes don't have a static create() method, then one will need to instantiate a factory, which IMO should be just as complex as instantiating an object itself.

I don't consider the argument that such a factory can return collections of objects to be produced is good enough. I feel there can be cleaner workarounds, if a factory instance needs to be created before actually creating objects from the factory.

I feel that it is better if the create method a static method of the factory class. But I'm also sure that my opinion is not completely "correct".

So can the SO community give examples where instantiating a Factory object is better than using static create methods?

Also, I came across an answer to a similar question, which listed these links and the answer: so I need to know clearly the difference between FactoryMethodPattern, FactoryMethod and CreationMethod with code examples.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

一张白纸 2024-07-31 23:08:19

使用工厂实例与依赖注入结合使用可以带来真正的好处。

因此,在您的示例中,而不是:

{ ...
    SomeFactory factory = new SomeFactoryImpl();
    Set<SomeClass> list = factory.getSomeListOfObjects();
}

您将:

public ThisClass(SomeFactory someFactory) {
    this.factory = someFactory;
}   

然后稍后...

{ ...
    Set<SomeClass> list = factory.getSomeListOfObjects();
}

几点:

  • 在这种情况下,您的类没有对具体工厂的任何引用,并且不需要了解 SomeFactoryImpl,它只知道抽象的 SomeFactory。
  • 在这种情况下,可以在实例的基础上配置正在传递的工厂实例,而不是静态的基础上,这往往是(在我看来)更好的处理方法。 如果您可以使工厂实例不可变,那么您就可以真正减少多线程的担忧。
  • 通过静态调用来为您提供一个实例并不是真的更好,对创建它的类的引用仍然是一个具体的实现细节,它只是更高 - 尽管这可能使其足够高以解决您的问题。

我知道这只能解决你问题的一部分......

Using an instance of a factory shows the real benefits when combined with dependency injection.

So in your example, instead of:

{ ...
    SomeFactory factory = new SomeFactoryImpl();
    Set<SomeClass> list = factory.getSomeListOfObjects();
}

You would have:

public ThisClass(SomeFactory someFactory) {
    this.factory = someFactory;
}   

then later...

{ ...
    Set<SomeClass> list = factory.getSomeListOfObjects();
}

Some points:

  • In this circumstance your class does not have any reference to a concrete factory, and doesn't need to know about SomeFactoryImpl, it only knows about the abstracted SomeFactory.
  • In this case the factory instance that's being passed around can be configured on an instance basis, rather than a static basis, which tends to be (in my opinion) a nicer way to deal with it. If you can make the factory instance immutable then you can really cut down the multi-threading worries.
  • Having a static call to give you an instance isn't really much better, the reference to the class that creates it is still a concrete implementation detail, it's just higher up - though that may make it high enough to solve your problem.

I know this only addresses a subset of your question...

北斗星光 2024-07-31 23:08:19

我想,用于创建对象的静态方法是最流行的方法,但也有一些用例首先创建工厂实例是有意义的。 例如,如果您想将其与注册表结合起来(应允许多个注册表共存)。

另外,如果工厂依赖于一些动态上下文信息(数据库连接等),我认为最好让工厂实例来处理这个问题。

I guess, a static method for the object creation is the most popular approach, but there are also some use-cases where first creating a factory instance makes sense. For example if you want to combine it with a registry (where multiple registries should be allowed to co-exist).

Also if the factory relies on some dynamic context information (database connections, ...) it is in my opinion better to let a factory-instance handle this.

白云不回头 2024-07-31 23:08:19

首先你忘记了工厂模式的主要目的,我打开了四人帮的书,它写道:

“定义一个用于创建对象的接口,但让子类决定实例化哪个类。工厂方法让一个类将实例化推迟到子类。”

这意味着您实际上定义了一个接口,因此 SomeFactoryImpl 实际上应该实现在其他地方定义的接口。 当您有许多需要实例化的对象但您不想关心它们是什么类型的对象时,这会很方便。例如,我使用它们开发了一个远程 Swing 应用程序,其中客户端通过序列化下载客户端虚拟机中不存在的一些类的定义。 每个类都定义了 JPanel 的一个子类,它具有特定的视图,但是当到达客户端时,我必须找到一种方法来实例化这些类而不知道它们,所以我使用工厂模式来调用工厂类并让它实例化我的未知对象(尽管它正在扩展我定义的 JPanel 的子类)。
另一个例子是生成特定于案例的对象以满足您的需求。 例如(如与此设计模式相关的维基百科页面中所述),您可以认为一个工厂构建对象,然后是另一个构建同一类型对象的工厂,但用于生成“假对象”,这将无法通过某种单元测试。

但是,您也可以使用静态方法解决您的特定问题,但请考虑将生成项目的部分与在大项目中使用它们的部分分开。 当然,开发客户端部分的人应该只知道使用了哪个工厂接口,并且知道这一点才能使用其他部分中定义的所有对象。

创建模式是一种“工具”模式,仅用于定义构造函数的自定义版本,而不必担心使用标准定义(方法的名称等于类的名称),但它没什么特别的。 只是实例化对象的不同方式。创建模式实际上并不能解决任何类型的特定问题(不包括具有相同数量和类型参数的构造函数)。

First of all you are forgetting the main aim of the factory pattern, I opened the book of the gang of four and it states:

"Define an interface for creating an objet, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses."

This means that actually you define an interface, so SomeFactoryImpl should actually implement an interface defined somewhere else. This comes handy when you've got many objects that need to be instantiated but you don't want to care about which kind of object they are.. For example I used them to develop a remote swing application in which the client downloaded through serialization the definition of some classes that didn't exist in the client VM. Every class defined a subclass of JPanel which its specific view but when reaching the client I had to find a way to istantiate these classes without knowing them so I used a factory pattern to call the factory class and let it instantiate my uknown object (althrough it is extending a subclass of JPanel defined by me).
Another example would be the generation of case-specific object to suit your needs. For example (like stated in wikipedia page related to this design pattern) you can think a factory that builds object and then another factory for the same kind of object but used to generate "fake objects" that will fail some kind of unit testing.

However you can solve your specific problem with static methods too but think about splitting the part that generates items from the part that uses them in a big project. Of course who is developing the client part should just know which factory interface is used and know just this to use all the objects definet in the other part.

Creation Pattern is a sort of 'facility' pattern used just to define custom versions of constructors without worrying using standard definition (having the name of the method equal to the name of the class) but it's nothing special. Just a different way to istantiate objects.. the creation pattern actually doesn't solve any kind of specific problem (excluding constructors with same number and kind of arguments).

灼疼热情 2024-07-31 23:08:19

这就是为什么我创建工厂对象的实例,

  1. 它允许我创建一个工厂,配置它(创建蓝色小部件与红色小部件等),然后让它可根据需要创建我的蓝色小部件、红色小部件。 请注意,这与 RedWidgetFactoryBlueWidgetFactory 不同。 该配置与所创建的对象类型正交,
  2. 它减少了在整个系统中使用一个工厂(通过静态方法访问)时可能遇到的线程问题。 这可能有点防御性,但我发现这是一个很好的心态(尤其是在大型系统中)。 当然,这取决于您的对象是如何创建的(例如,您的工厂是否创建共享的底层组件)

Here's why I create instances of factory objects

  1. it allows me to create a factory, configure it (to create blue widgets vs. red widgets etc.) and then have it available to create my blue widgets, red widgets on demand. Note that this is distinct from having a RedWidgetFactory, BlueWidgetFactory. The configuration is orthogonal to the type(s) of objects being created
  2. it reduces possible threading issues that you may encounter having one factory (accessed via a static method) used throughout your system. This is perhaps a little defensive, but I've found that's a good mindset to have (especially in sizable systems). Of course it depends how your objects are created (e.g. does your factory create underlying components that are shared)
泼猴你往哪里跑 2024-07-31 23:08:19

IMO,您拥有的代码确实是 GoF 的正确样本抽象工厂模式,即使它的使用并不完全优化。 如果我没记错的话,GoF 书描述了工厂(SomeFactory、SomeFactoryImpl)和产品(SomeClass)之间的关系,但没有提及实例化工厂的细节。

如果您拥有的是不会被广泛使用的内部 API,那么您拥有的可能就足够了。 否则,您可以:

  1. 让另一个类(可以说是“工厂管理器”)根据参数(例如 JDBC 中的 DriverManager)或其他上下文信息选择工厂实现。
  2. 使用某种依赖注入框架。

如果选择#1,我个人通常会尝试在 JDBC 之后对其进行建模,其中:

  • Driver 将是抽象工厂
  • ConnectionsStatements 等是products
  • DriverManager (GoF 书中未明确指定)是一个实用程序类,它根据传入的 JDBC URL 为您选择一个工厂

(在本例中,DriverManager 继续执行)并为您创建产品,如果您像大多数人一样使用 getConnection(...) 方法。)

为了将其与您的问题联系起来,可以通过调用

new OracleDriver().connect(...)

But 作为您的方法 来使用 JDBC指出,这是次优的,并且在某种程度上违背了使用抽象工厂模式的目的。

这个问题曾经也让我很困扰,直到有一天我意识到该模式实际上并没有明确谈论工厂是如何创建的。

我希望这回答了你的问题。

IMO, the code you have is indeed a proper specimen of the GoF Abstract Factory pattern, even if its use is not completely optimal. If I recall correctly, the GoF book describes the relationship between factories (SomeFactory, SomeFactoryImpl) and products (SomeClass) but leaves the specifics of instantiating factories open.

If what you have is an internal API that isn't going to be widely used, what you have is probably sufficient. Otherwise, you could:

  1. Have another class (a "factory manager" so to speak) select your factory implementation based on a parameter (e.g., the DriverManager in JDBC), or other context information.
  2. Use some sort of dependency injection framework.

If going with #1, I personally usually try and model it after JDBC, where:

  • Driver would be the abstract factory
  • Connections, Statements etc are products
  • DriverManager (not specified in GoF book explicitly) is the utility class that selects a factory for you based on the JDBC URL passed in

(In this case, the DriverManager goes ahead and creates the product for you also, if you use the getConnection(...) methods, as most do.)

To tie it back to your question, one could arguably use JDBC by calling

new OracleDriver().connect(...)

But as your pointed out, this is sub-optimal, and somewhat defeats the purpose of using the abstract factory pattern.

This problem used to bother me a lot too, until I realized one day that that pattern actually does not explicitly talk about how factories are created.

I hope this answers your question.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文