繁体   English   中英

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

[英]Realistic use case for static factory method?

我熟悉静态工厂方法的想法和好处,如Joshua Bloch的Effective Java中所述

  • 工厂方法具有名称,因此与构造函数不同,您可以使用多个具有相同签名的工厂方法。
  • 工厂方法不必创建新对象; 他们可以返回以前创建的对象。 这适用于不可变对象或值对象。
  • 与构造函数不同,工厂方法可以返回其返回类型的任何子类型的对象。

现在,我正在尝试为正在学习Java和OO原则的人解释静态工厂方法。 她从具体场景而不是抽象中学习得最好。 如果她能看到工作模式,解决一些问题,她就会明白。 但她发现更难以阅读上述特征的抽象列表来理解如何应用模式。

你能帮我提出一个使用静态工厂方法的现实例子,它可以使它的好处变得清晰,但是它仍然足够简单,可以在介绍性的Java类中显示某些人吗?

这个人确实有PL / SQL的编程经验,但从来没有学过OOP模式。

使用javax.swing.BorderFactory作为所有三个点的示例。

此类用于为swing对象创建边框。 这些边框对象可以很容易地重复使用,这种工厂方法允许这样做。 这是javadoc 这个工厂是所有三点的一个很好的例子:

  • 有多个静态方法具有不同的名称,如createEmptyBorder()createEtchedBorder()
  • 这些方法将尽可能返回先前创建的对象。 在整个应用程序中使用相同的边框非常频繁。
  • Border本身实际上是一个接口,因此通过此工厂创建的所有对象实际上是实现此接口的类。

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

你不能用new Integer()做到这一点,因为JLS要求new在每次调用时都创建一个新实例

我目前最喜欢的这种模式的例子是GuavaImmutableList 它的实例只能由静态工厂或构建器创建。 以下是一些有利的方法:

  • 由于ImmutableList不公开任何publicprotected构造函数,因此它可以在包中进行子类化,同时不允许用户对其进行子类化(并且可能会破坏其不变性保证)。
  • 鉴于此,它的工厂方法都能够返回它的专用子类而不暴露它们的类型。
  • 它的ImmutableList.of()工厂方法返回EmptyImmutableList的单例实例。 这演示了静态工厂方法如何不需要创建新实例。
  • 它的ImmutableList.of(E)方法返回一个SingletonImmutableList实例,该实例经过优化,因为它只能保存1个元素。
  • 它的大多数其他工厂方法都返回一个RegularImmutableList
  • 它的copyOf(Collection)静态工厂方法也并不总是需要创建一个新实例......如果给出它的Collection本身就是一个ImmutableList ,它就可以返回它!

Calendar.getInstance()不是一个很好的例子吗? 它根据语言环境创建BuddhistCalendar,JapaneseImperialCalendar或默认为GregorianCalendar。

这是我不得不做的一件事。 在一次求职面试中,我被要求编制一副卡片,在那里可以洗牌。 真的很简单的问题。 我建立:

Card:
  suit
  rank

Deck:
  card[]

我认为区别的因素是,任何时候都只能有52张牌。 所以我将Card()的构造函数设为私有,而是创建静态工厂valueOf(suit,rank)这允许我缓存52张卡并使其成为不可变的。 它教了很多重要的基础课程。

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

这类似于布尔和字节,除了我使用一个常见的作业示例来说明控制实例的重要性。 我还为deck创建了一个名为newDeck()的辅助函数,因为我想显示一个实例,其中构造函数可能不需要是私有的,但是拥有一个帮助器静态工厂仍然很好。

我希望这有帮助!

这个简单的案例。 假设你有一个操作某种打印机的类,但它不关心它是epson,canon还是其他东西。 因此,您只需创建一个接口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();

在这里,您可以从您可以操作的打印机的任何细节或管理打印的方式中抽象出clinet代码。 它是PrinterFactory,如果一个例如出现故障,他会关心选择什么打印机。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM