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

Java 静态工厂方法的实际用例?,java,oop,design-patterns,factory,static-methods,Java,Oop,Design Patterns,Factory,Static Methods,我熟悉静态工厂方法的思想和优点,如Joshua Bloch的: 工厂方法有名称,因此与构造函数不同,您可以有多个具有相同签名的工厂方法 工厂方法不必创建新对象;它们可以返回以前创建的对象。这适用于不可变对象或值对象 与构造函数不同,工厂方法可以返回其返回类型的任何子类型的对象 现在,我试图为学习Java和OO原理的人解释静态工厂方法。她从具体的场景中学习,而不是从抽象中学习。如果她能看到工作中的模式,解决一些问题,她会明白的。但她发现,要想理解如何应用这种模式,很难阅读上述特征的抽象列表 你

我熟悉静态工厂方法的思想和优点,如Joshua Bloch的:

  • 工厂方法有名称,因此与构造函数不同,您可以有多个具有相同签名的工厂方法
  • 工厂方法不必创建新对象;它们可以返回以前创建的对象。这适用于不可变对象或值对象
  • 与构造函数不同,工厂方法可以返回其返回类型的任何子类型的对象
现在,我试图为学习Java和OO原理的人解释静态工厂方法。她从具体的场景中学习,而不是从抽象中学习。如果她能看到工作中的模式,解决一些问题,她会明白的。但她发现,要想理解如何应用这种模式,很难阅读上述特征的抽象列表

你能帮我举出一个使用静态工厂方法的实际例子吗?这个例子清楚地说明了静态工厂方法的好处,但它仍然足够简单,可以在一个介绍性的Java类中展示给别人看


此人确实有PL/SQL编程经验,但从未学习过OOP模式。

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

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

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

    • 你第二点的教科书示例是(类似于
      布尔值
      字节
      )。对于参数值-128到127,此方法返回一个缓存实例,而不是创建一个新的
      整数。这使得(自动)装箱/取消装箱对于典型值更为有效


      使用
      new Integer()
      无法做到这一点,因为JLS要求每次调用
      new
      时都创建一个新实例。

      难道
      Calendar.getInstance()
      不是一个好的exmaple吗?
      它根据区域设置创建一个佛历、日本历法或默认的格里高利历法。

      这是我不久前不得不做的一个。在一次求职面试中,我被要求编写一副卡片,以便洗牌。非常简单的问题。我创建了:

      Card:
        suit
        rank
      
      Deck:
        card[]
      
      我认为区别在于,在任何时候只有52张牌。因此,我将Card()的构造函数设为private,并创建静态工厂值(suit,rank),这允许我缓存52张卡并使其不可变。它在那本书中教授了许多重要的基础课程

    • 不变的
    • 控件创建对象
    • 静态方法
    • 可能子类化并从另一个源返回卡片。(我没有这样做)
    • 这类似于Boolean和Byte,只是我使用了一个常见的家庭作业示例来说明为什么控制实例很重要。我还为deck创建了一个名为newDeck()的helper函数,因为我想显示一个实例,在这个实例中,构造函数可能不需要是私有的,但如果有一个helper静态工厂还是不错的


      我希望这有帮助

      简单的例子。假设您有一个操作某种打印机的类,但它不关心它是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会关心选择哪种打印机。

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

      • 由于
        ImmutableList
        不公开任何
        public
        protected
        构造函数,因此可以在包中对其进行子类化,同时不允许用户对其进行子类化(并可能破坏其不可更改性保证)
      • 考虑到这一点,它的工厂方法都能够返回它的专用子类,而不公开它们的类型
      • 它的
        ImmutableList.of()
        factory方法返回
        EmptyImmutableList
        的单例实例。这演示了静态工厂方法如何在不需要创建新实例的情况下不需要创建新实例
      • 它的
        ImmutableList.of(E)
        方法返回一个
        SingletonImmutableList
        的实例,该实例经过优化,因为它只会恰好包含1个元素
      • 它的大多数其他工厂方法返回一个
        regulammutablelist
      • 它的
        copyOf(Collection)
        静态工厂方法也不总是需要创建新实例。。。如果给它的
        集合
        本身就是一个
        不可变列表
        ,它就可以返回它
      检查过这个吗?在这个特定的例子中,我甚至可以使用枚举,因为它在编译时已知可以创建的类的每个实例!我做了两个,三个,四个…杰克,皇后,国王和王牌。我还创造了红心、梅花、黑桃和钻石。这非常有效,因为一切都是在编译时静态检查的,我的参数是valueOf(Rank-Rank,Suit-Suit)。