Design Patterns

Download Report

Transcript Design Patterns

The Singleton Pattern
(Creational)
©SoftMoore Consulting
Slide 1
Motivation
•
Some classes should have exactly one instance These
classes usually involve the central management of a
resource.
•
Examples
–
–
–
–
•
print spooler
– window manager
logger
– factory for a family of objects
an object that manages database connections
an object that interacts with a physical device
Singleton example in Java
– class java.lang.Runtime
– static method getRuntime() returns a reference to the single
instance.
©SoftMoore Consulting
Slide 2
Singleton Pattern
•
Intent: Ensure a class has only one instance, and
provide a global point of access to it
•
Motivation
– Sometimes we want just a single instance of a class to exist in
the system.
– We need to have that one instance easily accessible.
– We want to ensure that additional instances of the class can not
be created.
©SoftMoore Consulting
Slide 3
Singleton Pattern
(continued)
•
Structure
Singleton
instance
...
getInstance()
...
•
return instance
Collaborations: Clients access a Singleton instance
solely through Singleton’s getInstance() operation.
©SoftMoore Consulting
Slide 4
Singleton Pattern
(continued)
•
Consequences:
– controlled access to sole instance
– reduced name space
– permits refinement of operations and representation
(through subclassing)
– permits a variable number of instances
(in case you change your mind)
©SoftMoore Consulting
Slide 5
Implementing the Singleton Pattern in Java
(Version 1)
public class Singleton
{
// the one and only instance
private static Singleton instance = null;
...
// other fields
protected Singleton()
{
... // initialization code
}
©SoftMoore Consulting
Slide 6
Singleton Implementation in Java
(Version 1 continued)
public static Singleton getInstance()
{
if (instance == null)
instance = new Singleton();
return instance;
}
...
// other methods
}
Note use of lazy initialization – the instance
is not actually created until it is needed.
©SoftMoore Consulting
Slide 7
Using the Singleton Class
Singleton s = Singleton.getInstance();
s.someMethod();
©SoftMoore Consulting
Slide 8
Problems with this Implementation
of the Singleton Class
•
Does not ensure only one instance since protected
constructors in Java can be called by other classes in
the same package.
– Possible solutions:
•
•
•
Make the constructor private. If you do this, you should also declare
the Singleton class as final, which makes the intention explicit
and allows compiler optimizations.
Put the class in its own separate package
Not thread-safe
Thread 1
Thread 2
time
if (instance == null)
if (instance == null)
instance = new Singleton();
instance = new Singleton();
©SoftMoore Consulting
Slide 9
Singleton Implementation in Java
(Version 2 – Synchronized)
public class Singleton
{
... // same as before
public static synchronized Singleton getInstance()
{
if (instance == null)
instance = new Singleton();
return instance;
}
... same as before
}
©SoftMoore Consulting
Slide 10
Problem with the
Version 2 Implementation
• This version is thread-safe.
• Synchronized methods can be expensive performancewise, and method getInstance() needs to be
synchronized only the first time it is called.
– The performance penalty may be acceptable in many
applications.
– The performance penalty is less in recent versions of the Java
Virtual Machine (JVM)
©SoftMoore Consulting
Slide 11
Singleton Implementation in Java
(Version 3 – Double-checked Locking)
public class Singleton
{
private volatile static Singleton instance = null;
...
// other fields
protected Singleton()
{
... // initialization code
}
©SoftMoore Consulting
Slide 12
Singleton Implementation in Java
(Version 3 continued)
public static Singleton getInstance()
{
if (instance == null)
{
synchronized (Singleton.class)
{
if (instance == null)
instance = new Singleton();
}
}
return instance;
}
...
// other methods
}
©SoftMoore Consulting
Slide 13
Comments on Version 3
• This version is thread-safe.
• Avoids the overhead of unnecessary thread
synchronization after the first instance is created
but might not be noticeably more efficient than synchronizing the
getInstance() method for recent versions of Java
• Declare the static field instance as volatile to ensure
that multiple threads handle it correctly.
•
Not guaranteed to work in Java versions 1.4 and earlier.
©SoftMoore Consulting
Slide 14
Singleton Implementation in Java
(Version 4 – Eager Initialization)
public class Singleton
{
private static final Singleton instance
= new Singleton();
public static Singleton getInstance()
{
return instance;
}
protected Singleton()
{ ... }
...
}
©SoftMoore Consulting
Slide 15
Comments on Version 4
•
This version implementation is thread-safe and efficient.
For this implementation, method getInstance() does
not need to be synchronized in order to guarantee
thread-safety.
•
This version does not use lazy initialization – the
instance is always created.
(not usually a problem)
•
Modern implementations of the JVM will are almost
certain to inline the call to the static getInstance()
method (a Factory Method).
Note: java.lang.Runtime uses this approach
©SoftMoore Consulting
Slide 16
Singleton Implementation in Java
(Version 5 – Single-element Enum Type)
public enum Singleton
{
INSTANCE;
// other methods
}
•
Using the singleton class
INSTANCE.someMethod();
Note: Enum types were added to Java 5 in 2004.
©SoftMoore Consulting
Slide 17
Comments on Version 5
•
This version is thread-safe for reasons similar to those
for version 4.
• Concise
• Provides the serialization machinery for free
• Guarantees against multiple instantiation, even in the
face of sophisticated serialization or reflection attacks.
•
Recommended by Joshua Bloch as “the best way to
implement a singleton”
©SoftMoore Consulting
Slide 18
Singleton Implementation in Java:
Other Versions
• Nested class (Bill Pugh)
• ...
See references at end of slides for details.
©SoftMoore Consulting
Slide 19
Real Example of a Singleton Pattern
package ...;
import ...;
/**
* This class provides general logging support. <br/>
* (Implements the Singleton pattern.)
*/
public class Log
{
private static final String slash = File.separator;
private static Log instance = null;
private static Date dateCreated;
private PrintWriter logWriter;
(continued on next slide)
©SoftMoore Consulting
Slide 20
Real Example of a Singleton Pattern
(continued)
/**
* The default constructor for this class.
*/
private Log()
{
logWriter = null;
Note: another singleton
try
{
Properties properties = AppProperties.getInstance();
// get tomcat home from the environment
Map<String, String> env = System.getenv();
String tomcatHome = env.get("CATALINA_HOME");
(continued on next slide)
©SoftMoore Consulting
Slide 21
Real Example of a Singleton Pattern
(continued)
// set up path for log file
java.util.Date today = new java.util.Date();
dateCreated = new Date(today);
String timestamp = ... ;
String webappHome = ... ;
String logPathName = tomcatHome + slash
+ webappHome + slash + "logs" + slash
+ logFileName + timestamp + ".log";
logWriter = new PrintWriter
(new FileWriter(logPathName, true), true);
}
catch(IOException ex)
{
ex.printStackTrace();
logWriter = new PrintWriter(System.err);
}
}
©SoftMoore Consulting
(continued on next slide)
Slide 22
Real Example of a Singleton Pattern
(continued)
/**
* Returns the single instance of this class
*/
public static synchronized Log getInstance()
{
if(instance == null)
instance = new Log();
else
{
Date today = new Date();
if (!dateCreated.equals(today))
instance = new Log();
}
return instance;
}
(continued on next slide)
©SoftMoore Consulting
Slide 23
Real Example of a Singleton Pattern
(continued)
/**
* Logs a general informational message that does not
* represent a problem. (Not for logging Java Exceptions
* or Errors.)
*/
public synchronized void logMessage(String methodName,
String message)
{
String fullMessage = "
Method: " + methodName
+ "\n
Message: " + message;
logTimestamp();
logWriter.println(fullMessage);
logWriter.println();
logWriter.flush();
}
(continued on next slide)
©SoftMoore Consulting
Slide 24
Real Example of a Singleton Pattern
(continued)
/**
* Logs an error message resulting from a Java Exception
*/
public synchronized void logException(String methodName,
Exception ex)
{
...
}
...
// other logging methods
public synchronized void print(String message)
{
logWriter.print(message);
}
(continued on next slide)
©SoftMoore Consulting
Slide 25
Real Example of a Singleton Pattern
(continued)
public synchronized void println(String message)
{
logWriter.println(message);
}
public synchronized void println()
{
logWriter.println();
}
private synchronized void logTimestamp()
{
logWriter.println
(Calendar.getInstance().getTime().toString());
}
}
©SoftMoore Consulting
Slide 26
References
•
Singleton pattern (Wikipedia)
http://en.wikipedia.org/wiki/Singleton_pattern
•
Singleton Pattern (Object-Oriented Design)
http://www.oodesign.com/singleton-pattern.html
•
Java Singleton Design Pattern Best Practices with
Examples (Pankaj)
http://www.journaldev.com/1377/java-singleton-design-pattern-best-practiceswith-examples#thread-safe-singleton
•
Simply Singleton (JavaWorld)
http://www.javaworld.com/javaworld/jw-04-2003/jw-0425-designpatterns.html
©SoftMoore Consulting
Slide 27