[英]Realistic use case for static factory method?
I'm familiar with the idea and benefits of a static factory method, as described in Joshua Bloch's Effective Java : 我熟悉静态工厂方法的想法和好处,如Joshua Bloch的Effective Java中所述 :
Now I'm trying to explain static factory methods for someone who is learning Java and OO principles. 现在,我正在尝试为正在学习Java和OO原则的人解释静态工厂方法。 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? 你能帮我提出一个使用静态工厂方法的现实例子,它可以使它的好处变得清晰,但是它仍然足够简单,可以在介绍性的Java类中显示某些人吗?
This person does have programming experience in PL/SQL but never got around to learning OOP patterns. 这个人确实有PL / SQL的编程经验,但从来没有学过OOP模式。
Use javax.swing.BorderFactory
as an example of all three points. 使用
javax.swing.BorderFactory
作为所有三个点的示例。
This class is used to make borders for swing objects. 此类用于为swing对象创建边框。 These border objects can be easily re-used, and this factory method allows for this.
这些边框对象可以很容易地重复使用,这种工厂方法允许这样做。 Here is the javadoc .
这是javadoc 。 This factory is a great example of all three points:
这个工厂是所有三点的一个很好的例子:
createEmptyBorder()
and createEtchedBorder()
. createEmptyBorder()
和createEtchedBorder()
。 Border
itself is actually an interface, so all objects created through this factory are actually classes which implement this interface. Border
本身实际上是一个接口,因此通过此工厂创建的所有对象实际上是实现此接口的类。 The textbook example of your second point is Integer.valueOf(int)
(similar for Boolean
, Short
, Long
, Byte
). 第二个点的教科书示例是
Integer.valueOf(int)
(类似于Boolean
, Short
, Long
, Byte
)。 For parameter values -128 to 127, this method returns a cached instance instead of creating a new Integer
. 对于参数值-128到127,此方法返回缓存的实例,而不是创建新的
Integer
。 This makes (auto)boxing/unboxing much more performant for typical values. 这使得(自动)装箱/拆箱对于典型值更加高效。
You can't do that with new Integer()
since the JLS requires that new
create a new instance every time it is called. 你不能用
new Integer()
做到这一点,因为JLS要求new
在每次调用时都创建一个新实例 。
My current favorite example of this pattern is Guava 's ImmutableList . 我目前最喜欢的这种模式的例子是Guava的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 any public
or protected
constructors, it can be subclassed within the package while not allowing users to subclass it (and potentially break its immutability guarantee). ImmutableList
不公开任何public
或protected
构造函数,因此它可以在包中进行子类化,同时不允许用户对其进行子类化(并且可能会破坏其不变性保证)。 ImmutableList.of()
factory method returns a singleton instance of EmptyImmutableList
. ImmutableList.of()
工厂方法返回EmptyImmutableList
的单例实例。 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 of SingletonImmutableList
which is optimized because it will only ever hold exactly 1 element. ImmutableList.of(E)
方法返回一个SingletonImmutableList
实例,该实例经过优化,因为它只能保存1个元素。 RegularImmutableList
. RegularImmutableList
。 copyOf(Collection)
static factory method also does not always need to create a new instance... if the Collection
it is given is itself an ImmutableList
, it can just return that! copyOf(Collection)
静态工厂方法也并不总是需要创建一个新实例......如果给出它的Collection
本身就是一个ImmutableList
,它就可以返回它! Wouldn't Calendar.getInstance()
be a good exmaple? Calendar.getInstance()
不是一个很好的例子吗? It creates depending on the locale a BuddhistCalendar, JapaneseImperialCalendar or by default a GregorianCalendar. 它根据语言环境创建BuddhistCalendar,JapaneseImperialCalendar或默认为GregorianCalendar。
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:
我建立:
Card:
suit
rank
Deck:
card[]
I think what was the distinguishing factor is that there can only 52 cards at all times. 我认为区别的因素是,任何时候都只能有52张牌。 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.
所以我将Card()的构造函数设为私有,而是创建静态工厂valueOf(suit,rank)这允许我缓存52张卡并使其成为不可变的。 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.
我还为deck创建了一个名为newDeck()的辅助函数,因为我想显示一个实例,其中构造函数可能不需要是私有的,但是拥有一个帮助器静态工厂仍然很好。
I hope this helps! 我希望这有帮助!
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.
假设你有一个操作某种打印机的类,但它不关心它是epson,canon还是其他东西。 So, you just create an Interface
Printer
, create some implementations of it and create a class which has only one method: createPrinter. 因此,您只需创建一个接口
Printer
,创建它的一些实现并创建一个只有一个方法的类:createPrinter。
So, the code will be simple: 所以,代码很简单:
public interface Printer {
print();
}
class CanonPrinter implements Printer {
print() {
// ...
}
}
public PrinterFactory {
Printer createPrinter() {
if (... ) {
return new CanonPrinter();
} else {
return new EpsonPrinter();
}
}
}
client code: 客户代码:
Printer printer = PrinterFactory.createPrinter();
printer.print();
Here you abstract you clinet code from any details of what printers you can operate with or how they manage printing. 在这里,您可以从您可以操作的打印机的任何细节或管理打印的方式中抽象出clinet代码。 It's PrinterFactory who cares what printer to choose if one for example malfunctions.
它是PrinterFactory,如果一个例如出现故障,他会关心选择什么打印机。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.