20

First of all please forgive me if its a really dumb question, I am just trying to learn this language to its core. I am reading Effective Java and the very first chapter talks about Static factory methods vs. Constructors. Their pros and cons. Few things that are confusing to me are:

  1. class of an object returned by static factory method is nonpublic - what exactly does it mean?
  2. unlike constructors static factory methods are not required to create a new object each time they are invoked - How does this happen? I am invoking factory method only to obtain a new object and do we put a check in factory method for checking if object already exists?

Thanks.

wattostudios
  • 8,666
  • 13
  • 43
  • 57
t0mcat
  • 5,511
  • 19
  • 45
  • 58
  • 2
    +1 for deep-diving into software design practice and asking a good question. – Brian Driscoll Nov 02 '10 at 15:55
  • +1 for asking WHY instead of just doing programming by wrote. Habit of a good coder. – TreyE Nov 02 '10 at 16:10
  • 2
    Knowing where to find some [real world examples](http://stackoverflow.com/questions/1673841/examples-of-gof-design-patterns) and cheking their source code may help in understanding design patterns better. – BalusC Nov 02 '10 at 16:23

5 Answers5

11

class of an object returned by static factory method is nonpublic - what exactly does it mean?

It means that the actual class of the objects returned by a static factory method can be a subclass of the declared type, and this subclass does not have to be public. It's just another implementation detail that client code should not care about.

unlike constructors static factory methods are not required to create a new object each > time they are invoked - How does this happen? I am invoking factory method only to obtain a new object and do we put a check in factory method for checking if object already exists?

Yes, that's one way this could be done. But really, anything is possible.

Michael Borgwardt
  • 342,105
  • 78
  • 482
  • 720
  • Hi Micheal, so it depends on the requirements? No hard and fast rule that factory methods should always check for an already present instance. – t0mcat Nov 02 '10 at 16:00
  • @t3ch: Yep, absolutely. The point is just that you _can_ do that with factory methods if it's useful and what you want to do... you don't have that option with `new`. – ColinD Nov 02 '10 at 16:06
  • wow thanks. At least now I know where it would be useful. Singletons can be better understood with this approach. – t0mcat Nov 02 '10 at 16:12
5

First off, kudos to you for your choice in Java-lit: Bloch's book is an excellent primer.

To answer your 2nd question ('unlike constructors static factory methods are not required to create a new object each time they are invoked'), it's important to realize that what Bloch is saying here is that with a static factory you have the option of either: returning a new object or returning a pre-existing one. It all depends on what you want to do.

For example, let's suppose you have a really simple value class of type Money. Your static factory method probably should return a new instance -- that is, a new object with a specific value for Money. So, like this:

public class Money { 

    private Money(String amount) { ... } /* Note the 'private'-constructor */

    public static Money newInstance(String amount) {
        return new Money(amount);
    }

}

But let's say you have some object that manages some resource and you want to synchronize access to that resource through some ResourceManager class. In that case you probably want your static factory method to return the same instance of itself to everyone -- forcing everyone to go through that same instance, so that that 1 instance can control the process. This follows the singleton-pattern. Something like this:

public ResourceManager {

    private final static ResourceManager me = new ResourceManager();

    private ResourceManager() { ... } /* Note the 'private'-constructor */

    public static ResourceManager getSingleton() {
        return ResourceManager.me;
    }
}

The above method forces your user to only ever be able to use a single instance, allowing you to precisely control who(and when) has access to whatever it is you are managing.


To answer your first question, consider this (admittedly not the best example, it's pretty ad-hoc):

public class Money {

    private Money(String amount) { ... }


    public static Money getLocalizedMoney( MoneyType localizedMoneyType, String amount ) { 
        switch( localizedMoneyType ) {
            case MoneyType.US:
                return new Money_US( amount );
            case MoneyType.BR:
                return new Money_BR( amount );
            default:
                return new Money_US( amount );
        }
    }
}

public class Money_US extends Money { ... }

public class Money_BR extends Money { ... }

Note how I can now do this:

Money money = Money.getLocalizedMoney( user_selected_money_type );
saveLocalizedMoney( money );

Again, a really contrived-example but hopefully it helps you see more or less what Bloch was getting at with that point.

The other answers were good -- I just think that, as a beginner, sometimes it helps to see some actual code.

Bane
  • 1,772
  • 3
  • 21
  • 28
  • > just think that, as a beginner, sometimes it helps to see some actual code. Thanks for considering this fact Bane. Your examples are really helpful esp the one where you are making a private instance and returning the same instance every time for ResourceManager. – t0mcat Nov 02 '10 at 16:28
  • np -- whenever learning a new concept, I always struggle with abstract/vague-answers -- hard-code coupled with a short explanation generally goes much further for me. BTW, "Item 3" in Bloch's book will give you a lot more to chew on regarding the singleton-factory approach. – Bane Nov 02 '10 at 16:31
  • Thanks Bane. looking forward to it. You folks are going to see tons of questions from me :) – t0mcat Nov 02 '10 at 16:37
  • As example you gave above, Why don't we need to use static factory method over public constructor for the first example? We can make it public constructor then use it, I really don't know why do we make constructor to private and create a static factory method to do the same thing with public constructor? – Shen Nov 28 '18 at 02:49
  • 1
    @Shen the answer is too long for an answer here; the author himself lists 5 reasons and it takes about 4 full pages to explain his reasoning. Please refer to "Effective Java" by Joshua Bloch, "Item 1: Consider static factory methods instead of constructors". The short answer, however, is that you don't strictly "have to do so" but using static factory methods gives you a lot more flexibility. Now, referring specifically to your question regarding "the first example", that example is a bit contrived and simplistic; not necessarily the most clear to convey a *why*. – Bane Nov 29 '18 at 22:29
  • 1
    @Shen that said, it could still be argued as a *foundation* for *future* improvements. If you just write using a constructor, you could be locked into that pattern later on when you want to introduce the "localize money type"-code I showed after the 1st example. If on the other hand you by default hide the constructor then your simplistic factory pattern can be used to call `getLocalizedMoneyType(DefaultMoneyTypeBasedOnLocale, amount)` -- and no pre-existing client code breaks because no one was already doing `new Money(amount)`. – Bane Nov 29 '18 at 22:33
  • @Bane thank you for your respond, based on your answer I know that we have many cases to use a static factory method instead constructor, in the `first-example` case we use static factory method because we want to use other type and improvement in the future, isn't it? – Shen Dec 05 '18 at 01:53
  • 1
    @Shen correct. For the simplest value-classes this is probably overkill. But for anything that you envision could get a bit more complicated-usage (think, for example, others using this code in an API-fashion; note, not necessarily REST-API; just general purpose API) then yes that's what I am saying: that we should use static factory methods in order to abstract-away from the end-user future changes in the underlying impl and leave us the developers a more flexible design. – Bane Dec 10 '18 at 18:29
2

When you use the new keyword then you as the developer know that the JDK will create a new instace of that object. What the author is saying, when you use a static method, the developer no longer knows if the method is creating a new instance or possibly doing something else. Something else can be, reusing cached data, object pooling, creating a private implementation and returning a subclass of the class.

Amir Raminfar
  • 33,777
  • 7
  • 93
  • 123
  • >> if the method is creating a new instance or possibly doing something else. Amir, if static method is not creating a new instance or returning new Object, then why do we need a static factory method? – t0mcat Nov 02 '10 at 16:03
  • 2
    You may not always need a new instance of something. Take for example, database connections: you do in java jdbc.newConnection(). But java doesn't create a new instance everytime. It first checks to see if a connection already exists. If not it will get a new instance. Another example might be that you want to create a singleton. (Singletons have their own problem) Which means there is a good read why there should be only once instance of a class. So again you would make your constructor private and only allow your api to be used through static classes. – Amir Raminfar Nov 02 '10 at 16:08
  • Also, I am not saying static factory methods are good in anyway! I am just saying sometimes you need it, but only use it if you have to. It must cleaner to use constructors than some confusing method that the developer has to look for. – Amir Raminfar Nov 02 '10 at 16:09
  • @t3ch: `Integer.valueOf(int)` is also a good example of a static factory method that doesn't always create a new object. New JVMs typically cache Integer objects for a configurable range (I think by default -128 to 127). This makes boxing much more efficient. – Mark Peters Nov 02 '10 at 16:11
  • Thanks Mark. So this goes for all wrapper classes? eg. Boolean.valueOf(boolean b)?? – t0mcat Nov 02 '10 at 16:14
  • @Amir: I disagree that you should only use static factory methods if you have to. As described in Effective Java, they have _numerous_ advantages over constructors and they're every bit as discoverable as constructors too... just type `ClassName.` and any IDE will list the static methods available to you. – ColinD Nov 02 '10 at 16:15
  • @t3ch: Not all. Double, for example, is very difficult to cache because it has floating point precision. Boolean does cache both values ( in `Boolean.TRUE` and `Boolean.FALSE`). A quick look at the others shows that Shorts and Longs are cached from -128 to 127 but that range isn't configurable, similarly all Byte objects are cached. – Mark Peters Nov 02 '10 at 16:16
  • @ColinD: I think static classes have their place. The book also talks about the disadvantages that might be important to you. I think when you need to control the creation of objects then static methods are the way to go. However, if every class in some api had newInstance(), then that would be not really java like. PS. Not everybody uses IDE's ;) – Amir Raminfar Nov 02 '10 at 16:21
  • 2
    @Amir: *It must cleaner to use constructors than some confusing method that the developer has to look for*...consistent naming conventions take care of that. It's much easier to browse static method names than try to figure out which of 100 constructors you want to use based on their arguments. It's way too easy to get it wrong with constructors ("oh, I wanted `new SomeType( int, int, String, int)`, not `new SomeType(int, int, int, String)`...") – Mark Peters Nov 02 '10 at 16:22
  • @t3ch: that caching of e.g. `Integer#valueOf(int)` is called [flyweight pattern](http://en.wikipedia.org/wiki/Flyweight_pattern) by the way. – BalusC Nov 02 '10 at 16:24
  • @BalusC: How so? It's not like different instances are sharing data. – Mark Peters Nov 02 '10 at 16:26
  • Here is a quote from the book: A second disadvantage of static factory methods is that they are not readily distinguishable from other static methods. They do not stand out in API documentation in the way that constructors do, so it can be difficult to figure out how to instantiate a class that provides static factory methods instead of constructors. To which point, I think again, if you must use them to keep things clean then do it, but don't create a public static factory for every single class you write! – Amir Raminfar Nov 02 '10 at 16:27
  • 2
    @Amir: That disadvantage is just there so that the argument seems balanced. Using annotations and proper naming can easily give you the static support you need to be able to distinguish them in Javadocs, etc. Simply not a good reason not to use them. – Mark Peters Nov 02 '10 at 16:28
  • @Mark: I don't get you. Those instances are immutable anyway. – BalusC Nov 02 '10 at 16:29
  • @Mark: So you are saying for every class you write, you also create a static method? Even if its just a simple class with one or two parameters? Couldn't also put those same proper naming you suggest on the constructor. – Amir Raminfar Nov 02 '10 at 16:31
  • @BalusC: I see where you're coming from with it, but the caching in itself isn't an example of the flyweight pattern. It would be flyweight if some class had hundreds of instances that referenced the same Integer. – Mark Peters Nov 02 '10 at 16:33
  • 1
    @Amir: you don't get to choose your constructor name in Java. And of course I don't do it for every class, but certainly not for lack of clarity. There are other valid reasons (for instance, it's basically impossible if the type is meant to be extended). – Mark Peters Nov 02 '10 at 16:34
  • @Amir: No, certainly not for every single class. Constructors are just fine if not better for many classes... particularly services for use with dependency injection and such. I still think they should be used more commonly than it seems you are implying they should, though. – ColinD Nov 02 '10 at 16:36
  • 1
    @Amir: I'm with Mark on this one -- solidly. Static factory methods are *the* way to go. That being said, if you are writing a simple value-class intended to be consumed by you and you alone, then (my rule of thumb) I don't worry about a static factory class -- I just use the constructor. But most of Bloch's book should be understood within the context of an *API DEVELOPER*. That is, if you are developing an api meant for someone else to consume, yes you should nearly always use the static factory method. – Bane Nov 02 '10 at 16:36
  • @Mark, I agree that in some cases it must cleaner to use static method. Like saying newInstanceFromFoo(Foo foo) is much easier to read than 4 constructor with different parameters. I just thought you were saying its always the case which is not. The most part I hate about these conversations is that some people take it away as black and white. Really it depends on the problem you are trying to solve. Like caching bytes makes sense. :) – Amir Raminfar Nov 02 '10 at 16:38
  • Folks, whats the best way to implement a static factory? Every class needs to define one?(where ever you feel the need). Or create one common static class and some how put the logic there for all required static methods used by your app. – t0mcat Nov 02 '10 at 16:41
  • @Bane, Hmm I disagree. Creating an API or not has nothing to do with it. Its what problem you are trying to solve. For example, the Intent class in the java android api. The api could have been only static methods for Intent. But they wisely chose constructors and static methods because sometimes it just doesn't make sense. – Amir Raminfar Nov 02 '10 at 16:42
  • 1
    @t3ch If you have one common class then that's called a factory. You can create a factory if all the classes are related to each other. I think its cleaner instead to have the relative static methods in the class it self. Again, sometimes though you want to separate the factory and the class which in this case you would create the factory. There isn't a one solution that will solve everything. Just see what's the best solution for your problem. – Amir Raminfar Nov 02 '10 at 16:45
  • @t3ch: _Generally_, you'll put static factory methods that return instances of a given class on that class. This isn't always possible, though, particularly if it's an _interface_ or a class that you have no control over that the factory methods need to return. Guava's `Predicates`, `Functions` and `Lists` classes are examples of collections of static factory methods in a different class. – ColinD Nov 02 '10 at 16:45
  • @Amir: the subject of 'static factory method' does indeed have applicability outside of creating an API. But if you step back and analyze Bloch's work as a whole I think one thing stands-out that is common to the entire work: *API*. Many of his rules don't apply, or are less applicable, when developing your own privately-consumed code but when viewed from an API-context they make much more sense. – Bane Nov 02 '10 at 16:49
  • @Amir: since I don't do android stuff, I can't comment on the Intent class; there are certainly times when a simple constructor works just fine, but I stand by the assertion that when producing an API, static factory methods will serve you better in most instances. Why??? For one thing, you can provide explicit naming conventions and you can return variants of what you constructed -- you can change the underlying implementation anyway you want provided that the end-result is the same. With pure-constructors you limit yourself. – Bane Nov 02 '10 at 16:53
  • @Bane I agree with you. If you need to control what is being constructed then this is the right thing to do. I guess I never thought of "Effective Java" just for APIs though. I always thought this is what a good programmer should think of regardless where the code is going to be. My point that I was trying to make is that sometimes, you want to keep things simple. But we tend to over complicate things. Sometimes you have to do static methods because you don't really have a cleaner model. I just take each problem and think of the right tools to solve the problem. – Amir Raminfar Nov 02 '10 at 17:10
  • @Amir: I don't think you are wrong to say that sometimes constructors are the simpler approach. And simpler is often better. Regarding "EJ" -- when I first read it in school there were often heated debates about Bloch's rules; too many exceptions to his rules, it seemed -- once I made the observation that his rules tend to hold much better when viewed from an API-context, everyone agreed they made much more sense -- after all, Bloch is an API-guy. Too many of his rules don't hold real well in all circumstances -- I mean, just consider this one topic. ;) – Bane Nov 02 '10 at 17:18
  • @Amir: just came across a real-world example that reminded me of another good use of static-factory methods; thought I'd share. Write a class that extends DefaultMutableTreeNode, taking a String into your constructor -- use that String to supply the title of your node by calling super(stringArg). Now try and check that the string isn't null/empty before building the object, throw an NPE if it is. Of course, you can't do it since super() has to be the first line in a constr. But you can achieve this with a static-fact. method. – Bane Nov 05 '10 at 14:27
  • Yes I agree. Actually I was thinking about this the other night myself. I think what I thought would be a better way to explain is that I don't think you should mark your constructors private. User should have the option to use static helpers or constructors. So as long the constructor is there and you have some additional helper functions, then its clean design. Of course if you need to control the number of instances, then you don't have a choice but make it private. – Amir Raminfar Nov 05 '10 at 14:39
1

class of an object returned by static factory method is nonpublic

Frequently a static factory method will return either an an object typed as an interface (most common), or sometimes some base class (less common). In either case, you don't know the exact class of the returned object.

The advantage of this is getting an object whose behaviour you know without worrying about the messy details of what class it instantiates.

unlike constructors static factory methods are not required to create a new object each time they are invoked

To understand this, consider the case of working with a singleton. You may call .getInstance() on some factory classes to get the singleton instance of an certain object. Typically, what this does is create an instance of the object if it doesn't already exist, or give you the existing instance if it already does. In either case, you get back a copy of the object. But you don't (and won't) know if this singleton had to be created, or if one had already been constructed previously.

The advantage of this is that the lifecycle of the object and when it is created is managed for you.

TreyE
  • 2,649
  • 22
  • 24
0

Both of your questions can be answered by looking at some code that makes use of both of these properties of static factory methods. I suggest looking at Guava's ImmutableList.

Note how the no-arg factory method of() always returns the same instance (it doesn't create a new instance each time). If you look carefully, you'll also notice that its copyOf(Iterable) factory method actually returns the object that is passed to it if that object is itself an ImmutableList. Both of these are taking advantage of the fact that an ImmutableList is guaranteed to never change.

Notice also how various factory methods in it return different subclasses, such as EmptyImmutableList, SingletonImmutableList and RegularImmutableList, without exposing the types of those objects. The method signatures just show that they return ImmutableList, and all subclasses of ImmutableList have package-private (default) visibility, making them invisible to library users. This gives all the advantages of multiple implementation classes without adding any complexity from the user's perspective, since they are only allowed to view ImmutableList as a single type.

In addition to ImmutableList, most instantiable classes in Guava utilize static factory methods. Guava also exemplifies a lot of the principles set forth in Effective Java (not surprising, given that it was designed by those principles and with guidance from Josh Bloch himself), so you may find it useful to take a look at it more as you're working through the book.

ColinD
  • 108,630
  • 30
  • 201
  • 202