Singleton: Difference between revisions
No edit summary |
Added PHP implementation - forgot the header last time, like the idiot that I am. |
||
Line 399: | Line 399: | ||
}</lang> |
}</lang> |
||
=={{header|PHP}}== |
|||
<lang PHP>class Singleton { |
<lang PHP>class Singleton { |
||
protected static $instance = null; |
protected static $instance = null; |
Revision as of 15:36, 6 December 2009
You are encouraged to solve this task according to the task description, using any language you may know.
A Global Singleton is a class of which only one instance exists within a program. Any attempt to use non-static members of the class involves performing operations on this one instance.
ActionScript
<lang actionscript>package {
public class Singleton {
private static var instance:Singleton; // ActionScript does not allow private or protected constructors. public function Singleton(enforcer:SingletonEnforcer) { }
public static function getInstance():Singleton { if (instance == null) instance = new Singleton(new SingletonEnforcer()); return instance; } }
}
internal class SingletonEnforcer {}</lang>
Ada
Non Thread Safe
<lang ada>package Global_Singleton is
procedure Set_Data (Value : Integer); function Get_Data return Integer;
private
type Instance_Type is record -- Define instance data elements Data : Integer := 0; end record; Instance : Instance_Type;
end Global_Singleton;</lang>
<lang ada>package body Global_Singleton is
-------------- -- Set_Data -- --------------
procedure Set_Data (Value : Integer) is begin Instance.Data := Value; end Set_Data;
-------------- -- Get_Data -- --------------
function Get_Data return Integer is begin return Instance.Data; end Get_Data;
end Global_Singleton;</lang>
Thread Safe
<lang ada>package Protected_Singleton is
procedure Set_Data (Value : Integer); function Get_Data return Integer;
private
protected Instance is procedure Set(Value : Integer); function Get return Integer; private Data : Integer := 0; end Instance_Type;
end Protected_Singleton;</lang>
<lang ada>package body Protected_Singleton is
-------------- -- Set_Data -- --------------
procedure Set_Data (Value : Integer) is begin Instance.Set(Value); end Set_Data;
-------------- -- Get_Data -- --------------
function Get_Data return Integer is begin return Instance.Get; end Get_Data;
-------------- -- Instance -- --------------
protected body Instance is
--------- -- Set -- ---------
procedure Set (Value : Integer) is begin Data := Value; end Set;
--------- -- Get -- ---------
function Get return Integer is begin return Data; end Get;
end Instance;
end Protected_Singleton;</lang>
C++
Thread-safe
Operating System: Microsoft Windows NT/XP/Vista
<lang cpp>class Singleton { public:
static Singleton* Instance() { // We need to ensure that we don't accidentally create two Singletons HANDLE hMutex = CreateMutex(NULL, FALSE, "MySingletonMutex"); WaitForSingleObject(hMutex, INFINITE);
// Create the instance of the class. // Since it's a static variable, if the class has already been created, // It won't be created again. static Singleton myInstance;
// Release our mutex so that other application threads can use this function ReleaseMutex( hMutex );
// Free the handle CloseHandle( hMutex );
// Return a pointer to our mutex instance. return &myInstance; }
// Any other public methods
protected:
Singleton() { // Constructor code goes here. } ~Singleton() { // Destructor code goes here. }
// And any other protected methods.
}</lang>
Non-Thread-Safe
This version doesn't require any operating-system or platform-specific features, but it is not safe in a multi-threaded environment.
<lang cpp>class Singleton { public:
static Singleton* Instance() { // Since it's a static variable, if the class has already been created, // It won't be created again. static Singleton myInstance;
// Return a pointer to our mutex instance. return &myInstance; }
// Any other public methods
protected:
Singleton() { // Constructor code goes here. } ~Singleton() { // Destructor code goes here. }
// And any other protected methods.
}</lang>
Common Lisp
Since Common Lisp uses generic functions for dispatch, creating a class is not necessary. If the superclasses of the singleton are not important, the simplest thing to do is to use a particular symbol; methods use eql specializers to be applicable to only that object.
For a simple example, the following program constructs English sentences without worrying about extra space occurring at points where no text (the-empty-phrase
, our singleton) is inserted.
<lang lisp>(defgeneric concat (a b)
(:documentation "Concatenate two phrases."))
(defclass nonempty-phrase ()
((text :initarg :text :reader text)))
(defmethod concat ((a nonempty-phrase) (b nonempty-phrase))
(make-instance 'nonempty-phrase :text (concatenate 'string (text a) " " (text b))))
(defmethod concat ((a (eql 'the-empty-phrase)) b)
b)
(defmethod concat (a (b (eql 'the-empty-phrase)))
a)
(defun example ()
(let ((before (make-instance 'nonempty-phrase :text "Jack")) (mid (make-instance 'nonempty-phrase :text "went")) (after (make-instance 'nonempty-phrase :text "to fetch a pail of water"))) (dolist (p (list 'the-empty-phrase (make-instance 'nonempty-phrase :text "and Jill"))) (dolist (q (list 'the-empty-phrase (make-instance 'nonempty-phrase :text "up the hill"))) (write-line (text (reduce #'concat (list before p mid q after))))))))</lang>
Thread safety is irrelevant since the singleton is created at load time, not first access.
D
<lang d>module singleton ; import std.stdio ; import std.thread ; import std.random ; import std.c.time ;
class Dealer {
private static Dealer me ; static Dealer Instance() { writefln(" Calling Dealer... ") ; if(me is null) // Double Checked Lock synchronized // this part of code can only be executed by one thread a time if(me is null) me = new Dealer ; return me ; } private static string[] str = ["(1)Enjoy", "(2)Rosetta", "(3)Code"] ; private int state ; private this() { for(int i = 0 ; i < 3 ; i++) { writefln("...calling Dealer... ") ; msleep(rand() & 2047) ; } writefln(">>Dealer is called to come in!") ; state = str.length - 1 ; } Dealer nextState() { synchronized(this) // accessed to Object _this_ is locked ... is it necessary ??? state = (state + 1) % str.length ; return this ; } string toString() { return str[state] ; }
}
class Coder : Thread {
private string name_ ; Coder hasName(string name) { name_ = name ; return this ; } override int run() { msleep(rand() & 1023) ; writefln(">>%s come in.", name_) ; Dealer single = Dealer.Instance ; msleep(rand() & 1023) ; for(int i = 0 ; i < 3 ; i++) { writefln("%9s got %-s", name_, single.nextState) ; msleep(rand() & 1023) ; } return 0 ; }
}
void main() {
Coder x = new Coder ; Coder y = new Coder ; Coder z = new Coder ; x.hasName("Peter").start() ; y.hasName("Paul").start() ; z.hasName("Mary").start() ;
x.wait ; y.wait ; z.wait ;
}</lang> Sample Output:
>>Mary come in. Calling Dealer... ...calling Dealer... >>Peter come in. Calling Dealer... >>Paul come in. Calling Dealer... ...calling Dealer... ...calling Dealer... >>Dealer is called to come in! Mary got (1)Enjoy Peter got (2)Rosetta Mary got (3)Code Paul got (1)Enjoy Peter got (2)Rosetta Paul got (3)Code Paul got (1)Enjoy Mary got (2)Rosetta Peter got (3)Code
E
Since E uses closure-style objects rather than classes, a singleton is simply an object which is defined at the top level of the program, not inside any method. There are no thread-safety issues since the singleton, like every other object, belongs to some particular vat (but can be remotely invoked from other vats).
<lang e>def aSingleton {
# ...
}</lang>
Io
Io does not have globals. But it is easy to make singleton objects: <lang io>Singleton := Object clone Singleton clone = Singleton</lang>
Objective-C
Non-Thread-Safe
(Using Cocoa/OpenStep's NSObject as a base class) <lang objc>// SomeSingleton.h @interface SomeSingleton : NSObject {
// any instance variables
}
+ (SomeSingleton*)sharedInstance;
@end</lang>
<lang objc>// SomeSingleton.m @implementation SomeSingleton
+ (SomeSingleton*) sharedInstance {
static sharedInstance = nil; if(!sharedInstance) { sharedInstance = [[SomeSingleton alloc] init]; } return sharedInstance;
}
@end</lang>
Java
Thread-safe
Double-checked locking; only use with Java 1.5+ <lang java>class Singleton {
private static Singleton myInstance; public static Singleton getInstance() { if (myInstance == null) synchronized(Singleton.class) if (myInstance == null) myInstance = new Singleton();
return myInstance; }
protected Singleton() { // Constructor code goes here. }
// Any other methods
}</lang>
Non-Thread-Safe
<lang java>class Singleton {
private static Singleton myInstance; public static Singleton getInstance() { if (myInstance == null) myInstance = new Singleton();
return myInstance; }
protected Singleton() { // Constructor code goes here. }
// Any other methods
}</lang>
PHP
<lang PHP>class Singleton {
protected static $instance = null; public $test_var; private function __construct(){ //Any constructor code } public static function getInstance(){ if (is_null(self::$instance)){ self::$instance = new self(); } return self::$instance; }
}
$foo = Singleton::getInstance(); $foo->test_var = 'One';
$bar = Singleton::getInstance(); echo $bar->test_var; //Prints 'One'
$fail = new Singleton(); //Fatal error</lang>
Python
In Python we use the Borg pattern to share state between instances rather than concentrate on identity.
Every instance of the Borg class will share the same state: <lang python>>>> class Borg(object): __state = {} def __init__(self): self.__dict__ = self.__state # Any other class names/methods
>>> b1 = Borg()
>>> b2 = Borg()
>>> b1 is b2
False
>>> b1.datum = range(5)
>>> b1.datum
[0, 1, 2, 3, 4]
>>> b2.datum
[0, 1, 2, 3, 4]
>>> b1.datum is b2.datum
True
>>> # For any datum!</lang>
Ruby
<lang ruby>require 'singleton' class MySingleton
include Singleton # constructor and/or methods go here
end
a = MySingleton.instance # instance is only created the first time it is requested b = MySingleton.instance puts a.equal?(b) # outputs "true"</lang>
Scala
The object construct in Scala is a singleton.
<lang scala>object Singleton {
// any code here gets executed as if in a constructor
}</lang>
Slate
Clones of Oddball themselves may not be cloned. Methods and slots may still be defined on them: <lang slate>define: #Singleton &builder: [Oddball clone]</lang>
Tcl
and the TclOO package
ref http://wiki.tcl.tk/21595 <lang tcl>package require Tcl 8.6
- This is a metaclass, a class that defines the behavior of other classes
oo::class create singleton {
superclass oo::class variable object unexport create ;# Doesn't make sense to have named singletons method new args { if {![info exists object]} { set object [next {*}$args] } return $object }
}
singleton create example {
method counter {} { my variable count return [incr count] }
}</lang> Demonstrating in an interactive shell <lang tcl>% set a [example new]
- oo::Obj20
% set b [example new] ;# note how this returns the same object name
- oo::Obj20
% expr {$a == $b} 1 % $a counter 1 % $b counter 2 % $a counter 3 % $b counter 4</lang>