静态工厂方法的实际用例?

发布于 2024-10-02 23:15:48 字数 534 浏览 3 评论 0原文

我熟悉静态工厂方法的想法和优点,如 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 技术交流群。

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

发布评论

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

评论(6

醉城メ夜风 2024-10-09 23:15:48

使用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:

  • There are multiple static methods with different names like createEmptyBorder() and createEtchedBorder().
  • These methods will return previously created objects when possible. It's quite frequent that the same border would be used throughout an application.
  • Border itself is actually an interface, so all objects created through this factory are actually classes which implement this interface.
-柠檬树下少年和吉他 2024-10-09 23:15:48

第二点的教科书示例是 Integer.valueOf(int) (类似于 BooleanShortLong字节)。对于参数值 -128 到 127,此方法返回缓存的实例,而不是创建新的 Integer。这使得(自动)装箱/拆箱对于典型值具有更高的性能。

您无法使用 new Integer() 执行此操作,因为 JLS 要求 new 每次调用时都创建一个新实例

The textbook example of your second point is Integer.valueOf(int) (similar for Boolean, Short, Long, Byte). For parameter values -128 to 127, this method returns a cached instance instead of creating a new 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.

星星的軌跡 2024-10-09 23:15:48

我目前最喜欢的这种模式示例是 GuavaImmutableList。它的实例只能由静态工厂或构建器创建。以下是这样做的一些优点:

  • 由于 ImmutableList 不公开任何 publicprotected 构造函数,因此可以在包中对其进行子类化,同时不允许用户对其进行子类化(并可能破坏其不变性保证)。
  • 鉴于此,它的工厂方法都能够返回它的专门子类,而无需暴露它们的类型。
  • 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:

  • Since 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).
  • Given that, its factory methods are all able to return specialized subclasses of it without exposing their types.
  • Its ImmutableList.of() factory method returns a singleton instance of EmptyImmutableList. This demonstrates how a static factory method doesn't need to create a new instance if it doesn't have to.
  • Its ImmutableList.of(E) method returns an instance of SingletonImmutableList which is optimized because it will only ever hold exactly 1 element.
  • Most of its other factory methods return a RegularImmutableList.
  • Its 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!
旧竹 2024-10-09 23:15:48

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.

沒落の蓅哖 2024-10-09 23:15:48

这是我不久前必须做的一个。在一次工作面试中,我被要求编写一副可以洗牌的纸牌。非常简单的问题。我创造了:

Card:
  suit
  rank

Deck:
  card[]

我认为区别因素是始终只能有 52 张牌。所以我将 Card() 的构造函数设为私有,并创建静态工厂 valueOf(suit,rank) 这允许我缓存 52 张牌并使其不可变。这些书中教授了许多重要的基础课程。

  1. 不可变的
  2. 控制对象
  3. 静态方法
  4. 的创建可能会子类化并从另一个源返回卡片。 (我没有这样做)

这与布尔和字节类似,只是我使用了一个常见的家庭作业示例来说明为什么控制实例很重要。我还为套牌创建了一个名为 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:

Card:
  suit
  rank

Deck:
  card[]

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.

  1. immutable
  2. control creation of object
  3. static methods
  4. possibly subclassing and return a card from another source. ( I didn't do this)

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!

尾戒 2024-10-09 23:15:48

简单的情况。假设您有一个操作某种打印机的类,但它并不关心它是爱普生、佳能还是其他打印机。因此,您只需创建一个接口Printer,创建它的一些实现并创建一个只有一个方法的类:createPrinter。

因此,代码将很简单:

   public interface Printer {
       print();
    }

    class CanonPrinter implements Printer {
       print() {
    // ...
       }
    }


    public PrinterFactory {

    Printer createPrinter() {
   if (... ) {
      return new CanonPrinter();
   } else {
      return new EpsonPrinter();
   }
}
}

客户端代码:

Printer printer = PrinterFactory.createPrinter();
printer.print();

在这里,您可以从可以操作的打印机或它们如何管理打印的任何细节中抽象出客户端代码。例如,如果一台打印机出现故障,则由 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:

   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. It's PrinterFactory who cares what printer to choose if one for example malfunctions.

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