3

While developing for Android, I came across a Bitmap class. I find it strange that this class has no public constructors, but instead offers the static createBitmap function with the exact same purpose.

Syntactically there's no advantage:

Bitmap bm = new Bitmap(10, 10);
Bitmap bm = Bitmap.createBitmap(10, 10);

I've seen other classes do this as well, where the equivalent static function is usually named newInstance. What is the reason for this?

Overv
  • 8,433
  • 2
  • 40
  • 70
  • 6
    This is the very [1st Item](http://my.safaribooksonline.com/book/programming/java/9780137150021/creating-and-destroying-objects/ch02lev1sec1) in the Effective Java book. You can go through it. – Rohit Jain Aug 01 '13 at 18:13
  • It just a design preference Static Factory, just like using camel case for method names. – Louis Ricci Aug 01 '13 at 18:14
  • @RohitJain I realise this is a dumb question for Java programmers now. It's just that I've never seen this pattern in other languages. With my limited knowledge of Java, it just seemed like another bloated language detail. – Overv Aug 01 '13 at 18:18

4 Answers4

6

What you're describing is called a Factory Method. It exists because it provides the ability to get an object that conforms to a particular interface, but which may have a different underlying implementation.

For (a completely arbitrary and trivial) example, the Factory Method may choose to hand you a LinkedList object instead of an ArrayList object, because the initial size you specified may have performance advantages in the LinkedList.

But both list implementations conform to the IList interface, so the resulting object is returned as an IList.

Robert Harvey
  • 178,213
  • 47
  • 333
  • 501
  • I understand now, I guess I'm too familiar with languages that don't really hide implementation details. – Overv Aug 01 '13 at 18:20
  • You mean languages that don't provide encapsulation? Even C has that capability. – Robert Harvey Aug 01 '13 at 18:21
  • 1
    The "Effective Java 2nd Edition" book linked in the comments of the question (http://my.safaribooksonline.com/book/programming/java/9780137150021/creating-and-destroying-objects/ch02lev1sec1) specifically states -- Note that a static factory method is not the same as the Factory Method pattern from Design Patterns [Gamma95, p. 107]. The static factory method described in this item has no direct equivalent in Design Patterns. -- – Louis Ricci Aug 01 '13 at 18:23
  • @RobertHarvey To me encapsulation has always been about implementation details in a class itself, like a hidden internal array for an ArrayList. It's never been about getting an object entirely different from the one requested. In C, if I want the behaviour of a linked list, I know to explicitly ask for it. – Overv Aug 01 '13 at 18:25
  • @LastCoder: I've modified my answer accordingly. But the book doesn't explain why they make that comment, and looking at the Factory Pattern, it appears to have many of the same motivations as a "static Factory Method" does. – Robert Harvey Aug 01 '13 at 18:25
  • @overv: Right. So if you have two classes that both conform to a particular interface, you can interchange them, provided you don't need capabilities that are specific to either. – Robert Harvey Aug 01 '13 at 18:26
1

In the first case, you need to instantiate a specific type. In the second you leave it to the implementer to decide which type to return.

I am not familiar with Bitmap, but another example is EnumSet. When you call:

EnumSet<SomeEnum> set = EnumSet.noneOf(SomeEnum.class);

the static factory method uses a different implementation depending on the number of items in your enum to be as efficient as possible in all situations.

The underlying code returns either a RegularEnumSet for small enums or a JumboEnumSet for large enums. That kind of contextual optimisation would not be possible with a constructor.

public static <E extends Enum<E>> EnumSet<E> noneOf(Class<E> elementType) {
    Enum[] universe = getUniverse(elementType);
    if (universe == null)
        throw new ClassCastException(elementType + " not an enum");

    if (universe.length <= 64)
        return new RegularEnumSet<>(elementType, universe);
    else
        return new JumboEnumSet<>(elementType, universe);
}
assylias
  • 321,522
  • 82
  • 660
  • 783
1

This is the factory method pattern.

There are two main reasons to do this:

  1. It allows for the possibility of in the future not always returning a new instance each time. For example Integer.valueOf(int) will re-use the same Integer objects it already created if the values are between -127 and 128. which are the most common Integer values used in code so we don't have the JVM making thousands of copies of identical instances (which each take up memory) and can just reuse the same instance.

  2. It allows for the static method to return a subclass without the caller knowing. This can be useful if combining the factory method with other Design Patterns like Proxy or Adapter to return modified versions of the class.

dkatzel
  • 31,188
  • 3
  • 63
  • 67
0

Edit: This question is some what covered:

Factory, Abstract Factory and Factory Method

Design Patterns: Factory vs Factory method vs Abstract Factory

That's the factory pattern. The whole point is to create classes from a static class, so you can hide the programmed details of the class (security measure).

Source:

http://www.oodesign.com/factory-pattern.html

Intent:

creates objects without exposing the instantiation logic to the client. refers to the newly created object through a common interface

Example:

public class ProductFactory{
    public Product createProduct(String ProductID){
        if (id==ID1)
            return new OneProduct();
        if (id==ID2) return
            return new AnotherProduct();
        ... // so on for the other Ids

        return null; //if the id doesn't have any of the expected values
    }
    ...
}

Another solid source:

http://sourcemaking.com/design_patterns/factory_method

Community
  • 1
  • 1