Another blog post for a single case pattern
http://blog.csdn.net/nalanmingdian/article/details/77848079 single case design pattern application Scenario
In some cases, the system requires only one instance. For example, a system has multiple print tasks, but only one that has a working task. Only one task manager can be opened in a Windows system. Therefore, it is sometimes necessary to ensure the uniqueness of an object. It can reduce the performance overhead of the system. Double judgment lock and volatile single case mode
public class single{
private single () {}
private static volatile single instance;
public static single getinstance () {
if (instance==null) {
synchronized (single.class) {
if (instance==null )
instance=new single ();
}
}
return instance
}
}
Why use Single.class instead of instance.
First, there are only two kinds of locks, one is class lock, the other is Object lock. At this point, a null pointer exception is reported because the instance is not initialized. Therefore, only class locks can be used. The above single example mode is absolutely thread safe.
No... A single example design pattern can still be broken.
such as reflection, such as serialization. Single case mode of reflection failure
The reflection mechanism is dynamic to get all the information of the class, including the private constructor.
public static void Main (string[] args) {
try {
constructor cs=class.forname ("Test. Single ")
. Getdeclaredconstructor ();
Setaccessible is a private member variable
cs.setaccessible (true) that can be accessed;
The reflection mechanism obtains the instance single
s1= (single) cs.newinstance ();
Single s2= (single) cs.newinstance ();
The general method obtains the instance single
s3=single.getinstance ();
Single s4=single.getinstance ();
SYSTEM.OUT.PRINTLN ("Reflection mechanism obtains instance S1==S2:" +s1.equals (S2));
SYSTEM.OUT.PRINTLN ("Conventional method obtains an instance s3==s4:" +s3.equals (S4));
System.out.println ("Comparison of reflection and conventional S1==S3:" +s1.equals (S3));
} catch (Exception e) {
}
}
The results are as follows:
The reflection mechanism obtains the instance S1==s2:false
the general method obtains the instance S3==s4:true
reflection and the conventional comparison S1==s3:false
As you can see from the preceding code, reflection can get its construction method for a singleton pattern, which can cause multiple instances to be created, destroying the object uniqueness of the singleton pattern.
Prevention: Limits the number of calls to constructors in a single case pattern.
The code is as follows:
Class single{
private static Boolean flag=false;
Private single () {
synchronized (single.class)
{
if (flag = = False)
{
flag =!flag;
}
else
{
throw new RuntimeException ("single mode is violated.") ");
}
}
}
Private static volatile single s;
public static single getinstance () {
if (s==null) {
synchronized (single.class) {
System.out.println (" Shili ");
if (s==null)
s=new single ();
}
}
return s;
}
}
Serialization and deserialization destroy the definition of single case pattern serialization and deserialization
* * Object Persistence method. **objectinputstream ObjectOutputStream ... The
process of converting an object to a byte sequence is the serialization of the object, which can be written to the stream for network transmission or saved to a file, database, and other system. The
process of restoring a byte sequence to an object is the deserialization of the object. The
implements the Serializable interface (Java.lang package, there is no method).
1. A class can be serialized and its child can be serialized.
2. Static class member, transient (the value of the instance variable does not need to be maintained when the object is stored) that represents the temporary data of the object and cannot be serialized.
in serialization and deserialization, Serialversionuid (static final) is so important that each class is specific and deserialized to determine the compatibility of the class. Inconsistencies can throw exceptions. How to break the
Import Java.io.File;
Import Java.io.FileInputStream;
Import java.io.FileNotFoundException;
Import Java.io.FileOutputStream;
Import java.io.IOException;
Import Java.io.ObjectInputStream;
Import Java.io.ObjectOutputStream;
Import java.io.Serializable; public class test1{public static void Main (string[] args) throws FileNotFoundException, IOException, Classnotfoundexc eption{//write Obj to file serialization ObjectOutputStream Oos = new ObjectOutputStream (New FileOutputStream ("tem
PFile "));
Oos.writeobject (Single.getinstance ());
Read Obj from file deserialized file File = new file ("Tempfile");
ObjectInputStream ois = new ObjectInputStream (new FileInputStream (file));
Single newinstance = (single) ois.readobject ();
Determine whether the same object System.out.println (newinstance = = Single.getinstance ());
The result is false} class single implements serializable{private only () {} private static volatile single s; public static SiNgle getinstance () {if (s==null) {synchronized (Single.class) {if (s==null)
S=new single ();
} return s; }
}
By the above code, by serialization and deserialization, the resulting object is a new object, which destroys the uniqueness of the single case schema object.
The serialization process of the object is implemented through ObjectOutputStream and Objectinputputstream, and then with the question, analyze the Objectinputputstream readobject How the method is implemented.
To save space, here's a readobject call stack for ObjectInputStream:
readobject->readobject0->readordinaryobject-> Checkresolve
Look at the key code here, the code snippet for the Readordinaryobject method:
Private Object Readordinaryobject (Boolean unshared)
throws IOException
{
//Here omit part of code
Object obj;
try {
obj = desc.isinstantiable () desc.newinstance (): null;
} catch (Exception ex) {
throw (ioexception) NE W invalidclassexception (
desc.forclass (). GetName (),
"Unable to create instance"). Initcause (ex);
Part of the code is omitted here
if (obj!= null &&
handles.lookupexception (passhandle) = = NULL &&
Desc.hasreadresolvemethod ())
{
Object rep = desc.invokereadresolve (obj);
if (unshared && rep.getclass (). IsArray ()) {
rep = Clonearray (Rep);
}
If (rep!= obj) {
handles.setobject (passhandle, obj = Rep);
}
return obj;
}
As shown in the first section:
Object obj;
try {
obj = desc.isinstantiable () desc.newinstance (): null;
} catch (Exception ex) {
throw (ioexception) NE W invalidclassexception (Desc.forclass (). GetName (), "Unable to create instance"). Initcause (ex);
The Obj object is the object to be returned by this method. You can also temporarily understand the objects returned by the ObjectInputStream ReadObject.
Desc.isinstantiable: If a serializable/externalizable class can be instantiated at run time, then the method returns True.
Desc.newinstance: This method invokes the parameterless construct method through reflection to create a new object.
As a result, a parameterless constructor is invoked to create a new object when deserializing. This destroys the object uniqueness of the single case pattern. Prevent serialization damage
As the second paragraph of the Code learns,
if (obj!= null &&
handles.lookupexception (passhandle) = = null &&
desc.hasreadresolvemethod ()
{
Object rep = desc.invokereadresolve (obj);
if (unshared && rep.getclass (). IsArray ()) {
rep = Clonearray (Rep);
}
If (rep!= obj) {
handles.setobject (passhandle, obj = Rep);
}
Hasreadresolvemethod: Returns True if the class that implements the serializable or Externalizable interface contains Readresolve
Invokereadresolve: Invokes the Readresolve method of the class to be deserialized by reflection.
Therefore, we can prevent a single instance from being corrupted by defining a Readresolve method in the single case pattern and specifying the generation policy of the object to be returned in the method.
Add the
private Object readresolve () {return singleton in a single example
;
}
Enumeration method to implement a single case pattern
In the Java1.5 version, single-element enumerations are the best way to implement a single case pattern. Enumerate knowledge
Enumeration resembles a class, and an enumeration can have member variables, member methods, and constructor methods.
Most basic usage:
Enum type{
a,b,c,d;
}
In fact, when created, the compiler automatically generates a class that inherits Java.lang.Enum, so the enumeration type can no longer inherit other classes, and the Enum class implements the serializable interface so that it serializes and deserializes the same object.
, such as the above enum can be seen as implemented in the following way:
Class Type extends enum{public
static final Type A;
public static final Type B;
...
}
You can think of type as a class, and ABCD as an instance.
An enum is constructed in private and is not allowed to be invoked.
You can also create a class method in which the instance method
Enum type{
a,b,c,d;
static int value;
public static int GetValue () {return
value;
}
String type;
Public String GetType () {return
type;
}
}
Based on the original, the class method and the instance method are added. We think of type as a class, so the static fields and methods in the enum can be considered as class methods. As we call the normal static method, the invocation of the class method is also done via Type.getvalue (), and access to the class properties is type.value.
The following is an instance method, which is the method that each instance can invoke. So what is the case? Yes, it's a,b,c,d. So we call the instance method, and we call it by Type.a.gettype ().
Finally, for an instance, you can also implement your own instance methods. Then look at the following code:
Enum type{
a{public
String GetType () {return "I won't tell you
";
}
},b,c,d;
static int value;
public static int GetValue () {return
value;
}
String type;
Public String GetType () {return
type;
}
}
{...} after instance a is to belong to the example of a method, can be covered by the original method, to achieve their own customization. In addition, we can add abstract methods that force ABCD to implement their own processing logic in an enum:
Enum type{
a{public
String GetType () {return
' A ';
}
},b {
@Override
public String GetType () {return
' B ';
}
},c {
@Override public
string GetType () {return
"C"; c27/>}
},d {
@Override public
String GetType () {return
"D";
}
};
Public abstract String GetType ();
}
Enum Single Example
All instances of an enumeration class are capitalized.
The enumeration is constructed in a privatized manner, and each instance invokes the constructor once.
Enum singletonc{
INSTANCE;
Private String field;
Public String GetField () {return
field;
}
public void SetField (String field) {
This.field = field;
}
}
Call singletonc.instance;
1. The enumeration instance is static final and is guaranteed to be instantiated only once.
2. For serialization and deserialization, the inherited enum class for enumerations implements the serializable interface by default. When serializing an enumeration class, you do not need to add the Readrsolve method to prevent the single case schema from being corrupted.
The declaration of the enumeration class is public
abstract class Enum<e extends enum<e>>
implements COMPARABLE<E> Serializable
3. For reflection, the inverse compilation of an enumeration is an abstract class and cannot be created by reflection.
4. An enumeration is a a hungry man load, so it is thread-safe.