Realistic use case for static factory method?

前端 未结 6 901
爱一瞬间的悲伤
爱一瞬间的悲伤 2021-02-02 17:01

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 mo
相关标签:
6条回答
  • 2021-02-02 17:28

    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!
    0 讨论(0)
  • 2021-02-02 17:38

    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.

    0 讨论(0)
  • 2021-02-02 17:39

    Wouldn't Calendar.getInstance() be a good exmaple? It creates depending on the locale a BuddhistCalendar, JapaneseImperialCalendar or by default a GregorianCalendar.

    0 讨论(0)
  • 2021-02-02 17:43

    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.

    0 讨论(0)
  • 2021-02-02 17:50

    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.
    0 讨论(0)
  • 2021-02-02 17:53

    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!

    0 讨论(0)
提交回复
热议问题