The Singleton Design Pattern requires Constructors to be defined as private member of the class (Default constructor, Copy constructors and Overloaded Assignment operator should all be defined private in case of C++). This pattern is explained here..
If the programming language you are using does not allow you to define the constructor as private or protected (ex. Actionscript), then how will you implement the Singleton class?
There are few Object Oriented languages like Action script (Flex) where a constructor must be defined as public ?
/** Code in Actionscript (Flex) language. */ public class Singleton { private function singleton{} // ERROR. Constructor must be public }
Solution:
If the Constructor cannot be made private, it is not possible to implement the Singleton Design Patern in full capacity.
But there are cases, when you want only one object of a class to be created. In such a cases, the definition of the class, should clearly state such intentions (even if it is not able to restrict the user completely from creating multiple objects via codding).
At least the message should be conveyed clearly to the user who is trying to create an instance of the class, that not more than one object of this class should be created.
You should follow the following steps to indicate that your class is Singleton.:
1. Make a private static object inside the class to hold the only instance
/** FLEX CODE */ public class { // Static Instance to hold the object private static var _instance:Singleton = null; }
The object is initialized to null.
When a request for the object is made for the very first time, a new object will be created and assigned to _instance, and in all further requests, this instance (_instance) will be returned. (Hence only one instance of this class will be present).
2. Make a public static function returning the only object of the class
/** FLEX CODE */ public class { // Static Instance to hold the object private static var _instance:Singleton = null; public static function get instance():Singleton { if(_instance == null) _instance = new Singleton(new SingletonEnforcer()); return _instance; } }
When the function instance will be called (don’t bother about the get keyword before the function name, its an actionscript feature) for the first time it will call the constructor, create a new object and will assign it to _instance variable. In all further calls, the already created object (in _instance) will be returned.
3. Define the public constructor.
Since we cannot make the constructor private, lets create a public constructor.
/** FLEX CODE */ public class { // Static Instance to hold the object private static var _instance:Singleton = null; // Public Constructor public function Singleton() { ; } public static function get instance():Singleton { if(_instance == null) _instance = new Singleton(new SingletonEnforcer()); return _instance; } }
4. Try to restrict users to accidently create an object.
We will not be able to completely stop users from creating multiple objects of the Singleton class.
But for those obedient users who code according to the guidelines, we should write sufficient code to block creation of multiple objects of the class because of any side effect.
We can put two such checks.
4-(A) Throwing exception on multiple object creation
When user attempts to create more than one object, throw an Exception in the construtor.
// Public Constructor public function Singleton() { if (_instance != null) { throw new Error("Singleton can only be accessed through Singleton.instance"); } }
4-(A) Make constructor parameterized
Create a dummy class and change the Constructor to receive object of that class.
// Public Constructor public function Singleton(obj:SingletonEnforcer) { if (_instance != null) { throw new Error("Singleton can only be accessed through Singleton.instance"); } }
Where SingletonEnforcer is a dummy class defined in the same file
class SingletonEnforcer{}
Now, because there is no default constructor, hence object of the class Singleton can only be created by passing SingletomEnforcer class object in the constructor
var obj:Singleton = new Singleton(new SingletonEnforcer());
It cannot be an accident.
Plus, The above code will also throw an exception if _instance is already created.
Final Code (In Flex):
package com.ritambhara.examples.design { public class Singleton { // ... REST OF THE CODE ... // Static Instance to hold the object private static var _instance:Singleton = null; // Public Constructor public function Singleton(obj:SingletonEnforcer) { if (_instance != null) { throw new Error("Singleton can only be accessed through Singleton.instance"); } } public static function get instance():Singleton { if(_instance == null) _instance = new Singleton(new SingletonEnforcer()); return _instance; } } } class SingletonEnforcer{}
5 Comments
Hi,
I am not flex developer but i use java which allow me to define a constructor private. but the above approach with public constructor is not working in java.
Can you paste the code to see where exactly you are getting the problem..
Hi there,
I did not get any notification that you have replied on my comments. Any way below is the code for the same.
Singleton implementation as per your suggestion
————————————————————————
package com.test;
public class SingletonWithpublicCons {
private static SingletonWithpublicCons instance = null;
public SingletonWithpublicCons(SingletonEnforcer singletonEnforcer) {
if (instance != null) {
throw new RuntimeException(“more than one object”);
}
}
public static SingletonWithpublicCons getInstance() {
if (instance == null)
return instance = new SingletonWithpublicCons(new SingletonEnforcer());
else
return instance;
}
}
class SingletonEnforcer {
}
Client which is broking this approach
——————————————————-
package com.puzzler;
import com.test.SingletonWithpublicCons;
public class SingletonWithpublicConsTest {
public static void main(String[] args) {
System.out.println(new SingletonWithpublicCons(null)); // 😛
System.out.println(new SingletonWithpublicCons(null)); // 😛
System.out.println(SingletonWithpublicCons.getInstance());
}
}
Yes you are right.. this will not stop user from delegrately creating multiple objects of the class.. the constructor is change to take singletonEnforcer object, just to make sure that object does not get created accidently.. default constructor sometimes get called as a side effect (parameter passing, function returning obejct etc..).. but there is no fool-proff way.. unless you create constructor private..
Below code should work but i have not tested on multi-threaded Env.
public SingletonWithpublicCons(SingletonEnforcer singletonEnforcer) {
if (singletonEnforcer == null) {
throw new RuntimeException(“Null not allow…”);
}
if (instance != null) {
throw new RuntimeException(“more than one object”);
}
}