Java Forum / General / July 2006
Singleton VS Static Class
howachen@gmail.com - 09 Jul 2006 15:07 GMT Which one you prefer....
1.
public class Person {
private static String name; private static int age;
public static String getName() { return name; } public static void setName(String name) { Person.name = name; }
public static int getAge() { return age; } public static void setAge(int age) { Person.age = age; }
}
2.
public class Person2 {
private static Person2 person2Instance = null;
private String name; private int age;
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
private Person2() {
}
public static Person2 getInstance() {
if (person2Instance == null) person2Instance = new Person2(); return person2Instance; }
}
3.
public class Test {
/** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub
Person.setName("peter"); Person.setAge(11); System.out.println(Person.getName() + Person.getAge());
Person2 person2 = Person2.getInstance(); person2.setName("peter"); person2.setAge(11); System.out.println(person2.getName() + person2.getAge()); }
}
Timo Stamm - 09 Jul 2006 15:32 GMT howachen@gmail.com schrieb:
> public static Person2 getInstance() { > > if (person2Instance == null) > person2Instance = new Person2(); > return person2Instance; > } This is a broken Singleton. You can end up with more than one instance if you have more than one thread.
Timo
Frank van Schie - 10 Jul 2006 08:22 GMT > howachen@gmail.com schrieb: >> public static Person2 getInstance() { [quoted text clipped - 6 lines] > This is a broken Singleton. You can end up with more than one instance > if you have more than one thread. So I've read in a JSR-133 FAQ[1]. Can this be fixed with a static initializer block? Like:
public class OneInstance { private static OneInstance thisObject; static { thisObject = new OneInstance(); }
public OneInstance() { } ... }
A linked resource in that FAQ mentioned this should be possible, but it also had some info that made it seem as though they were talking of the old memory model, not the J2SE 1.5 one.
[1]: http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html
Timo Stamm - 10 Jul 2006 09:33 GMT Frank van Schie schrieb:
>> howachen@gmail.com schrieb: >>> public static Person2 getInstance() { [quoted text clipped - 9 lines] > So I've read in a JSR-133 FAQ[1]. Can this be fixed with a static > initializer block? It seems more natural to me to initialize the static field right away:
private static final Person2 p = new Person2()
public static Person2 getInstance() { return p; }
Timo
AndrewMcDonagh - 09 Jul 2006 15:38 GMT > Which one you prefer.... > > 1. snipped (MonoState is its correct name)
> 2. Snipped Singleton
For a good comparison see...
http://www.objectmentor.com/resources/articles/SingletonAndMonostate.pdf
Personally, I try hard never to create either. Instead I favour 'just create one instance'
http://butunclebob.com/ArticleS.UncleBob.SingletonVsJustCreateOne
If I find I'm wanting to create a singleton/monostate, just because there is only currently one instance required AND it would make it easier for the calling code to get access to it, then I would actually put the single instance within a Global Singleton container.
I.e. there is only one singleton in the system and it contains those things that I need.
code eg...
Toolbox.getInstance().getPerson();
YMMV
Timo Stamm - 09 Jul 2006 16:09 GMT AndrewMcDonagh schrieb:
>> Which one you prefer.... >> >> 1. >> > > snipped (MonoState is its correct name) Monostate would be:
public class Person {
private static String name;
public String getName() { return Person.name; }
... }
(methods are not static)
AndrewMcDonagh - 09 Jul 2006 17:22 GMT > AndrewMcDonagh schrieb: >>> Which one you prefer.... [quoted text clipped - 18 lines] > > (methods are not static) true, but as the object state is class bound, the static methods make no difference.
Chris Smith - 09 Jul 2006 17:52 GMT > true, but as the object state is class bound, the static methods make no > difference. I'd have to say that when people say "monostate", most of the time they are implying object semantics such that the state is shared. Static methods would syntactically fit in Java, but that's really a language design blunder. That is, if you used the class as:
Person p = new Person(); p.setName("Bob");
then it might reasonably called monostate, but it would also raise a compiler warning with my current Eclipse compiler settings, because it's abusing the language.
At this point, I am feeling the uncontrollable urge to point out that one should not mistake the assignment of the word "monostate" with any kind of endorsement of one design over another. Design patterns are (or could be) useful in that they provide practice in evaluating well- understood design decisions and understanding the effects of those decisions on the resulting code. When one is discriminating about which patterns are used, they can also collect wisdom from previous software designers. They are, however, not at all useful for choosing designs that have the largest possible number of design pattern names that may be applied to their parts, especially if one is insufficiently picky about patterns to use. Whether or not something is or is not a monostate is merely a terminology dispute, and in no way relates to whether something is a good idea or not.
In reading about a pattern, one should always ask: had anyone heard of this technique before design patterns became a buzzword, or has it been commonly used for some reason other than its author's promotion of it as a design pattern? In other words, is it really the kind of elegant solution that has tended to be invented again and again to solve a variety of problems, as it was once claimed patterns were, or is it instead just a clever trick that is the sole work of some author or small group of authors. If the latter, then this is an "invented design pattern". It is questionable to be whether invented design patterns ought to be called patterns at all. They are, in any case, antithetical to reasonable applications of patterns. Reasonable use of patterns attempts to organize and learn from the wisdom of collective experience. People had heard of factories long before design patterns, for example; they are worth paying attention to. By constrast, invented design patterns like monostate are more often a tribute to the cleverness of some blogger than they are a collection of wisdom from a long history of designs. They may or may not be a good idea, but I certainly don't want my software design to be dominated by the influence of clever bloggers.
 Signature Chris Smith - Lead Software Developer / Technical Trainer MindIQ Corporation
AndrewMcDonagh - 09 Jul 2006 20:13 GMT >> true, but as the object state is class bound, the static methods make no >> difference. > > I'd have to say that when people say "monostate", most of the time they snipped -
> At this point, I am feeling the uncontrollable urge to point out that > one should not mistake the assignment of the word "monostate" with any > kind of endorsement of one design over another. snipped
and seconded!
I have an inherent distaste for either of the design patterns (which lets face it - do nothing but make Global data seem like a good design - even when we know it sucks)
The only time I've ever used MonoState, is when performing a series of very small refactorings on a large code base, to remove a singleton. The singleton was wildly used and spread out all over the place.
By making the Singleton to be both that AND a MonoState, I was able to change...
public void doSomething() { Singleton s = Singleton.getInstance(); ... }
into....
public void doSomething() { Singleton s = new Singleton(); ... }
Then it was a case to change the above by pulling up the '..new Singleton()' into the calling method..something like....
public void doSomething(Singleton s) { ... }
Nothing has changed in the design, S is still the singleton . But now I'm removing or changing how the singleton is retrived.
Repeat & rinse....
and eventually (after a few hours) I had successfully removed any call to 'getInstance()' and replaced it with calls to 'new Singleton()'... where appropriate.
Leaving a final, simple and automated refactoring of renaming the Singleton class into something more appropriate.
By doing this in a series of small refactorings, I managed to fundamentally change the design of the system with out having to use a debugger or having any compile errors that lasted more than a few seconds (e.g. typos caused errors).
Keep in mind - I had a comprehensive suite of unit tests that I continuously ran during these refactorings to ensure I didn't break anything.
Chris Uppal - 10 Jul 2006 11:15 GMT > By doing this in a series of small refactorings, I managed to > fundamentally change the design of the system with out having to use a [quoted text clipped - 4 lines] > continuously ran during these refactorings to ensure I didn't break > anything. Given the second paragraph, why bother with all those tiny steps in the first ?
I dislike automated refactorings.
-- chris
Ed - 09 Jul 2006 22:50 GMT howachen@gmail.com skrev:
> Which one you prefer.... (snipped alternatives, which really negates this post without seeing the previous, but there we are...)
To quote the great Hollywood phrase: "Prefer," is such an ugly word. It's appreciated that you're asking for a preference, and that's fine, but from an engineering point of view what matters is what has the shortest distance on in the three-dimensional quality-productivity-punctuality space. (Oh, I can see the c.d.t-lobby loving that one.)
You've asked for a preference, however, that's what will be given.
The rules of encapsulation require that a client know as little as possible about a service as possible; the singleton requires a service to be especially instantiated (via getInstance()), the monostate does not (it looks like any other instantiated object): so for me, the monostate wins.
I will not attempt to evaluate the engineering consequences of this choice as I was merely asked for a preference, but I certainly second Andrew's first response concerning the comparison link, and I certainly endorse Chris's uncontrolable urges, but then I don't quite endorse Andrew's second response ("I have an inherent distaste for either of the design patterns") because Uncle Bob gave what I consider the best argument for or against global data that I've ever heard (I'm going to paraphrase this as I don't have his original post to hand): all global data is bad except the global data you need.
As a matter of interest to, I'm sure, no-one, and because I think there should be more source-code shown on these newsgroups, I use one global monostate in all my designs (where I can have the choice, which is very seldom as I work mainly on updating legacy systems rather than designing new ones) - never more and never less - and I don't use singletons (although I did, before reading about monostate, though I must admit that I've not yet seen a QPP improvement because of this decision except in very, "Soft," engineering): the monostate I use is always a domain-specific variation of the ConcreteRegistry referenced here: http://www.edmundkirwan.com/servlet/fractal/cs1/frac-cs40.html
.ed
 Signature www.EdmundKirwan.com - Home of The Fractal Class Composition
Chris Uppal - 10 Jul 2006 11:31 GMT > Which one you prefer.... Neither.
First off, it's very, very, unlikely that a class with a name like Person should have only one instance (or act as if it had only one instance).
Secondly, I dislike collecting complicated state into a class. If there is a coherent cluster of data in the system then it should be owned by a real object, not attatched to a class as static data. Still, at least your version uses explicit static methods, rather than the "monostate" pattern which has been discussed elsewhere in this thread -- and which is a total abomination IMO.
Thirdly, I dislike the classical version of the Singleton pattern. For too many people the emphasis is on there only being one instance permitted, and that is wrong IMO. The valuable thing about Singleton might better be expressed with a name like "Distinguished Instance" -- i.e. there is one (or maybe more than one) instance which is special in some way. Your code, then, follows the classic pattern in that it hard-wires the dangerous (and pointless) assumption that only one Person should ever be created. Now, if analysis of the problem had shown the need for a special instance which should be easiliy available to arbitrary callers (i.e. the equivalent of a global -- and there is nothing wrong with globals if handled correctly), then the method for getting that instance would not be the bland getInstance() but would be something meaningful -- getGlobalLogger() or getSystemOwner() or something like that. So, while I have nothing against my version of Singleton, the code you exhibit not something I would like to see in a real system.
-- chris
dsjoblom@abo.fi - 10 Jul 2006 15:30 GMT > > Which one you prefer.... > [quoted text clipped - 24 lines] > So, while I have nothing against my version of Singleton, the code you exhibit > not something I would like to see in a real system. I agree with everything said above. The main advantage of a Singleton over a class with static data is that the singleton is just a(nother) regular instance of the class. If there is later a need to create additional instances of the class with separate state, there is no requirement to change existing code using the original singleton. And in practice, this situation does come up from time to time.
However, I would only use a singleton if a class has state. Sometimes you see classes which have no state, but only a collection of utility methods implemented as singletons. In that case, I would use a class with static methods (although some braindead 'code improvement' tools suggest using a singleton instead).
Regards, Daniel Sjöblom
pranshu - 10 Jul 2006 15:47 GMT If we are talking about a clustered application - both the above implementations are not going to work. Both such implementations in that case would be used for read-only data.
A "set" method - probably will require use of a RDBMS, or a file system which permits locking.
The Get method is even more interesting. If we had an object - we would be returning an instance of the object there in case of above code. So the consumer can manipulate the value. Not very neat is it ? The get I would say is broken even in case of non-clustered applications.
It might be better to keep it static and simple and save some effort - rather than going all the way.
In the implementations I have done in the past: I have used static blocks / classes for read only information. The read/write are managed in the database. In case the amount of data in the database is too large, the same can be optimized by time based caching and also by using triggers in database to populate a very small table indicating that the value has changed - which can be checked for all invocation of Get methods, allowing the users to refresh from database only when needed.
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|