静态工厂方法的实际用例?
我熟悉静态工厂方法的想法和优点,如 Joshua Bloch 的 Effective 中所述Java:
- 工厂方法有名称,因此与构造函数不同,您可以拥有多个具有相同签名的工厂方法。
- 工厂方法不必创建新对象;他们可以返回先前创建的对象。这对于不可变对象或值对象很有用。
- 与构造函数不同,工厂方法可以返回其返回类型的任何子类型的对象。
现在我试图为正在学习 Java 和 OO 原理的人解释静态工厂方法。她从具体场景而不是抽象场景中学习得最好。如果她能看到工作中的模式并解决一些问题,她就会明白。但她发现阅读上述特征的抽象列表来理解如何应用该模式更困难。
您能否帮我想出一个使用静态工厂方法的实际示例,该示例清楚地表明了其优点,但仍然足够简单,可以在介绍性 Java 类中向其他人展示?
此人确实有 PL/SQL 编程经验,但从未抽出时间学习 OOP 模式。
I'm familiar with the idea and benefits of a static factory method, as described in Joshua Bloch's Effective Java:
- Factory methods have names, so you can have more than one factory method with the same signature, unlike constructors.
- Factory methods don't have to create a new object; they can return a previously-created object. This is good for immutable objects or value objects.
- Factory methods can return an object of any subtype of their return type, unlike constructors.
Now I'm trying to explain static factory methods for someone who is learning Java and OO principles. She learns best from concrete scenarios instead of abstractions. If she can see the pattern at work, solving some problem, she'll get it. But she finds it harder to read an abstract list of characteristics like the above to understand how to apply the pattern.
Can you help me come up with a realistic example of using a static factory method, that makes its benefits clear, but which is still simple enough to show someone in an introductory Java class?
This person does have programming experience in PL/SQL but never got around to learning OOP patterns.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
使用
javax.swing.BorderFactory
作为所有三个点的示例。此类用于为swing对象制作边框。这些边框对象可以轻松地重复使用,并且此工厂方法可以实现这一点。这是javadoc。这个工厂是所有三点的一个很好的例子:
createEmptyBorder()
和createEtchedBorder()
。Border
本身实际上是一个接口,因此通过这个工厂创建的所有对象实际上都是实现这个接口的类。Use
javax.swing.BorderFactory
as an example of all three points.This class is used to make borders for swing objects. These border objects can be easily re-used, and this factory method allows for this. Here is the javadoc. This factory is a great example of all three points:
createEmptyBorder()
andcreateEtchedBorder()
.Border
itself is actually an interface, so all objects created through this factory are actually classes which implement this interface.第二点的教科书示例是
Integer.valueOf(int)
(类似于Boolean
、Short
、Long
、字节
)。对于参数值 -128 到 127,此方法返回缓存的实例,而不是创建新的Integer
。这使得(自动)装箱/拆箱对于典型值具有更高的性能。您无法使用
new Integer()
执行此操作,因为 JLS 要求new
每次调用时都创建一个新实例。The textbook example of your second point is
Integer.valueOf(int)
(similar forBoolean
,Short
,Long
,Byte
). For parameter values -128 to 127, this method returns a cached instance instead of creating a newInteger
. This makes (auto)boxing/unboxing much more performant for typical values.You can't do that with
new Integer()
since the JLS requires thatnew
create a new instance every time it is called.我目前最喜欢的这种模式示例是 Guava 的 ImmutableList。它的实例只能由静态工厂或构建器创建。以下是这样做的一些优点:
ImmutableList
不公开任何public
或protected
构造函数,因此可以在包中对其进行子类化,同时不允许用户对其进行子类化(并可能破坏其不变性保证)。ImmutableList.of()
工厂方法返回EmptyImmutableList
的单例实例。这演示了静态工厂方法如何在不需要时不需要创建新实例。ImmutableList.of(E)
方法返回一个SingletonImmutableList
的实例,该实例经过优化,因为它只保存 1 个元素。RegularImmutableList
。copyOf(Collection)
静态工厂方法也并不总是需要创建一个新实例...如果它给出的Collection
本身就是一个ImmutableList
code>,它可以返回那个!My current favorite example of this pattern is Guava's ImmutableList. Instances of it can only be created by static factories or a builder. Here are some ways that this is advantageous:
ImmutableList
doesn't expose anypublic
orprotected
constructors, it can be subclassed within the package while not allowing users to subclass it (and potentially break its immutability guarantee).ImmutableList.of()
factory method returns a singleton instance ofEmptyImmutableList
. This demonstrates how a static factory method doesn't need to create a new instance if it doesn't have to.ImmutableList.of(E)
method returns an instance ofSingletonImmutableList
which is optimized because it will only ever hold exactly 1 element.RegularImmutableList
.copyOf(Collection)
static factory method also does not always need to create a new instance... if theCollection
it is given is itself anImmutableList
, it can just return that!Calendar.getInstance()
不是一个很好的例子吗?它根据区域设置创建BuddhistCalendar、JapanImperialCalendar 或默认的GregorianCalendar。
Wouldn't
Calendar.getInstance()
be a good exmaple?It creates depending on the locale a BuddhistCalendar, JapaneseImperialCalendar or by default a GregorianCalendar.
这是我不久前必须做的一个。在一次工作面试中,我被要求编写一副可以洗牌的纸牌。非常简单的问题。我创造了:
我认为区别因素是始终只能有 52 张牌。所以我将 Card() 的构造函数设为私有,并创建静态工厂 valueOf(suit,rank) 这允许我缓存 52 张牌并使其不可变。这些书中教授了许多重要的基础课程。
这与布尔和字节类似,只是我使用了一个常见的家庭作业示例来说明为什么控制实例很重要。我还为套牌创建了一个名为 newDeck() 的辅助函数,因为我想展示一个实例,其中构造函数可能不需要是私有的,但拥有一个辅助静态工厂仍然很好。
我希望这有帮助!
Here is one I had to do a while back. At a job interview, I was asked to program a deck of cards where they can be shuffled. Really simple problem. I created:
I think what was the distinguishing factor is that there can only 52 cards at all times. So I made the constructor for Card() private and instead create static factory valueOf(suit, rank) This allowed me to cache the 52 cards and make the immutable. It taught many important basic lessons in that books.
This is similar to Boolean and Byte, except I used a common homework example to show why its important to control the instances. I also created a helper function for deck called newDeck() because I wanted to show an instance where the constructor might not need to be private but it would still be nice to have a helper static factory.
I hope this helps!
简单的情况。假设您有一个操作某种打印机的类,但它并不关心它是爱普生、佳能还是其他打印机。因此,您只需创建一个接口
Printer
,创建它的一些实现并创建一个只有一个方法的类:createPrinter。因此,代码将很简单:
客户端代码:
在这里,您可以从可以操作的打印机或它们如何管理打印的任何细节中抽象出客户端代码。例如,如果一台打印机出现故障,则由 PrinterFactory 负责选择哪台打印机。
The simple case. Suppose you have a class which operates some sort of printer, but it doesn't care if it is epson, canon or something else. So, you just create an Interface
Printer
, create some implementations of it and create a class which has only one method: createPrinter.So, the code will be simple:
client code:
Here you abstract you clinet code from any details of what printers you can operate with or how they manage printing. It's PrinterFactory who cares what printer to choose if one for example malfunctions.