File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
The moose likes Developer Certification (SCJD/OCMJD) and the fly likes Combining State and Singleton design patterns Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


JavaRanch » Java Forums » Certification » Developer Certification (SCJD/OCMJD)
Bookmark "Combining State and Singleton design patterns" Watch "Combining State and Singleton design patterns" New topic
Author

Combining State and Singleton design patterns

John Cozens
Greenhorn

Joined: Jul 15, 2004
Posts: 10
Hi folks,

I'm using the State design pattern to handle state changes within my client-side UI. Most of the design pattern text books (including GoF) suggest that it makes sense:
a) to make each State an inner class (so that it can access variables within the parent "Context" class)
b) optionally, also to make each State class a Singleton

OK, I agree with them. But here's the problem...

A Singleton generally makes use of a static instance of itself, accessed via a static getInstance() method. BUT static declarations aren't allowed within an inner class. The immediately obvious solutions are:
1) don't use a Singleton for each State (but that loses some efficiency/encapsulation benefits that I'd like to retain)
2) make each State a stand-alone class (but then I've lost the benefits of access to the parent "Context" class)
3) make each State a static nested class (no obvious major benefit over option 2)

Anyone got any ideas? Am I missing an obvious solution?

Thanks in advance
Pedro Penna
Ranch Hand

Joined: Jun 05, 2004
Posts: 46

...static declarations aren't allowed within an inner class...


A singleton is a regular object accessed via its class' static method (getInstance).

Take a look at this piece of code I wrote:

mike acre
Ranch Hand

Joined: Sep 23, 2003
Posts: 197


You do not need to do this, a static member is initialised once on 1st access, so you can just do:


[ July 16, 2004: Message edited by: mike acre ]

SCJP 1.4, SCJD
John Cozens
Greenhorn

Joined: Jul 15, 2004
Posts: 10
Guys, thanks for your quick replies.

Pedro
=====
OK Pedro, that's a neat trick. So effectively you're using Inner to act as a "Singleton wrapper"? Which means that Inner can get access to Outer's members, although Singleton itself still can't (unless you use x to get values from Outer then mail them across to Singleton using a getXXX() method?). Hmm, so are there still a couple of issues:
i) for every Singleton I now have to create 2 classes - 1 original stand-alone (Singleton) and a "wrapper" (Inner) buried within the ultimate parent (Outer)? That doesn't seem ideal but, agreed, it does work;
ii) to keep as much encapsulation as possible, let's say I want to put lots of state-based methods in Singleton, which in turn need to set/un-set GUI components within Outer. As Singleton is outside the scope of Outer, it still doesn't have access to Outer's members. In this case, would you need to add all of the relevant GUI-changing methods to Inner instead? If that's so, have you then defeated the point of having a Singleton in the first place? Although your Singleton is a genuine Singleton, Inner is not.

So thanks for the solution, it's really interesting. Any further thoughts on these secondary issues would definitely be welcome


Mike
====
Thanks Mike. I reckon you and Pedro are both right - these are merely different solutions to achieving a Singleton. Yours is definitely more appropriate when you want to instantiate your Singleton up-front (say during initialisation while the user's looking at a dazzling splash screen ), while Pedro's is more appropriate when you want to use "lazy instantiation"...that means you want your Singleton built on a "Just in Time" basis, the first time that getInstance() is called, and not a moment sooner. That can be useful if say you've got 10 million potential Singleton Objects, of which you'll probably only ever need 50 during a typical program run, but you don't know which ones you'll need in advance.

Best

John
John Cozens
Greenhorn

Joined: Jul 15, 2004
Posts: 10
Sorry Pedro, I meant a setXXX() method, not getXXX(), for example using something like x.setState(outerVariableValue) as a mechanism for getting info about one of Outer's member variables to your Singleton instance.
Pedro Penna
Ranch Hand

Joined: Jun 05, 2004
Posts: 46
John,

I think you should use Inner Classes OR the Singleton pattern in this case.

You could also use something similar to the "Typesafe Enum"
pattern discussed in Joshua Bloch's book "Effective Java Guide".


[ July 16, 2004: Message edited by: Pedro Penna ]
mike acre
Ranch Hand

Joined: Sep 23, 2003
Posts: 197
Originally posted by John Cozens:

Mike
====
Thanks Mike. I reckon you and Pedro are both right - these are merely different solutions to achieving a Singleton. Yours is definitely more appropriate when you want to instantiate your Singleton up-front (say during initialisation while the user's looking at a dazzling splash screen ), while Pedro's is more appropriate when you want to use "lazy instantiation"...that means you want your Singleton built on a "Just in Time" basis, the first time that getInstance() is called, and not a moment sooner. That can be useful if say you've got 10 million potential Singleton Objects, of which you'll probably only ever need 50 during a typical program run, but you don't know which ones you'll need in advance.


To use a singleton you must get that instance
if you get that instance you access the class
if you access the class you cause any static member to be initialised
(if 1st access). The staic member won't be initialised sooner, since this is a singleton and the 1st access to the class will be to getInstance().
This is lazy instantiation. You can't be lazier with a singleton.
Eben Hewitt
Author
Ranch Hand

Joined: Apr 16, 2004
Posts: 36
Note that when using singletons it is important to make them thread safe. I think the best way to do this is like this:



This way the code is both thread-safe and lazy-loading. It doesn't use the common solution, which is to make a getInstance method, and make it synchronized. But that can hurt performance, especially since the call only needs to be synchronized the first time.


Eben Hewitt. SCJP, SCWCD, SCJD, SCJWSD for JEE 5, TOGAF 8 Certified Architect, author of Java SOA Cookbook (O'Reilly, 2009) and contributor to 97 Things Every Software Architect Should Know
John Cozens
Greenhorn

Joined: Jul 15, 2004
Posts: 10
Pedro, while experimenting last night I did end up with something not too different from your suggestion, so thanks for that. I have Joshua Bloch's book, so I'll definitely take a look at Item 21 on typesafe enums.


Mike, OK but what if you have a variable within some other class of type Singleton (which you don't plan to instantiate by using Singleton.getInstance() for the next few days). Given that the static variable "instance" in Singleton is, well, static, won't it get initialised during class-loading? So if you use this form:



...that's fine, 'instance' will remain null until another class calls getInstance() on it. But if you use this form instead:



...then 'instance' will actually become an object of type Singleton as a result of class-loading, regardless of whether another class ever calls getInstance() on it or not? I'm not sure we're actually disagreeing on this, I'm just trying to be totally clear in my own mind.


Eben, thanks, I hadn't seen that approach before. I'd pondered using double-checked locking, although opinion seems to vary widely on whether that's totally safe. I'll go away and experiment with the different alternatives.
mike acre
Ranch Hand

Joined: Sep 23, 2003
Posts: 197
Originally posted by John Cozens:

Mike, OK but what if you have a variable within some other class of type Singleton (which you don't plan to instantiate by using Singleton.getInstance() for the next few days). Given that the static variable "instance" in Singleton is, well, static, won't it get initialised during class-loading? So if you use this form:




'Of type Singleton' ?

So a subclass of Singleton?
How can you have a subclass if the default constructor is private?




...then 'instance' will actually become an object of type Singleton as a result of class-loading, regardless of whether another class ever calls getInstance() on it or not? I'm not sure we're actually disagreeing on this, I'm just trying to be totally clear in my own mind.



That is correct.
John Cozens
Greenhorn

Joined: Jul 15, 2004
Posts: 10
Hi Mike,


'Of type Singleton' ?

So a subclass of Singleton?
How can you have a subclass if the default constructor is private?


No, I agree with you, my fault for not explaining clearly. What I meant was that if you had some code like this...



...then if you ran MyMainClass, your Singleton class would be loaded immediately, before even the first line of main() was run, regardless of whether MyMainClass ever actually called Singleton.getInstance(). Therefore, if you used the second version of Singleton from my last post...



...Singleton.instance would exist as an Object as soon as your app ran, given that it's a class (static) variable within Singleton. Using the other method, this doesn't happen. Singleton.instance remains null until another class calls getInstance() for the first time. At least, this is what my debugger is telling me. So if you did have a million classes that used the above form of Singleton, I'd expect that you'd have constructed a million Objects on start-up, regardless of whether you ever called getInstance() on any of them during the course of the app. They'd just sit there, presumably consuming space on the heap.
mike acre
Ranch Hand

Joined: Sep 23, 2003
Posts: 197
So if you did have a million classes that used the above form of Singleton, I'd expect that you'd have constructed a million Objects on start-up, regardless of whether you ever called getInstance() on any of them during the course of the app. They'd just sit there, presumably consuming space on the heap.


No, you'd only have one, the constructor is private and the only instantiation of the object is within a static member, so there can only be one object. Whatever you do outside the class all references will point to that one object. I'm afraid there is NO advantage of doing the usual 'if null' construct for a Java singleton.
 
GeeCON Prague 2014
 
subject: Combining State and Singleton design patterns