Full Analysis of Singleton mode (3) -- simple but confusing Singleton Mode

Source: Internet
Author: User
Document directory
  • Use the Registry
  • Use reflection
  • Encapsulate the Registry
  • Classloaders
  • Serialization
  • Singleton mode conclusion
Use the Registry

You can use a singleton registry:

  • In running period refers to order EXAMPLE Class
  • Prevents instances that generate multiple Singleton subclass classes
    In the singleton class in Example 8, a registration registry for Singleton classes is maintained:
    Example 8 Singleton class with registry
    1. ImportJava. util.Hashmap;
    2. ImportOrg. Apache. log4j. Logger;
    3.  
    4. Public ClassSingleton {
    5. Private Static HashmapMap =New Hashmap();
    6. Private StaticLogger logger = logger. getrootlogger ();
    7.  
    8. ProtectedSingleton (){
    9. // Exists only to thwart instantiation
    10. }
    11. Public Static SynchronizedSingleton getinstance (StringClassname ){
    12. If(Classname =Null)Throw New Illegalargumentexception("Illegal classname ");
    13. Singleton = (Singleton) map. Get (classname );
    14.  
    15. If(Singleton! =Null){
    16. Logger.info ("got Singleton from map:" + Singleton );
    17. ReturnSingleton;
    18. }
    19. If(Classname. Equals ("singeltonsubclass_one "))
    20. Singleton =NewSingletonsubclass_one ();
    21. Else If(Classname. Equals ("singeltonsubclass_two "))
    22. Singleton =NewSingletonsubclass_two ();
    23.  
    24. Map. Put (classname, Singleton );
    25. Logger.info ("created singleton:" + Singleton );
    26. ReturnSingleton;
    27. }
    28. // Assume functionality follows that's attractive to inherit
    29. }

    The base classes of this code first create subclass instances and store them in a map. However, the base class has to pay a high price because you must replace its getinstance () method with each subclass. Fortunately, we can use reflection to solve this problem.

    Use reflection


    In the singleton class with a registry in Example 9, reflection is used to instantiate an object of a special class. Compared with Example 8, the singleton. getinstance () method does not need to be rewritten in each implemented subclass.
    Example 9 use reflection to instantiate a singleton class

    1. ImportJava. util.Hashmap;
    2. ImportOrg. Apache. log4j. Logger;
    3.  
    4. Public ClassSingleton {
    5. Private Static HashmapMap =New Hashmap();
    6. Private StaticLogger logger = logger. getrootlogger ();
    7.  
    8. ProtectedSingleton (){
    9. // Exists only to thwart instantiation
    10. }
    11. Public Static SynchronizedSingleton getinstance (StringClassname ){
    12. Singleton = (Singleton) map. Get (classname );
    13.  
    14. If(Singleton! =Null){
    15. Logger.info ("got Singleton from map:" + Singleton );
    16. ReturnSingleton;
    17. }
    18. Try{
    19. Singleton = (Singleton)Class. Forname (classname). newinstance ();
    20. }
    21. Catch(ClassnotfoundexceptionCNF ){
    22. Logger. Fatal ("couldn't find class" + classname );
    23. }
    24. Catch(InstantiationexceptionIE ){
    25. Logger. Fatal ("couldn't instantiate an object of type" + classname );
    26. }
    27. Catch(IllegalaccessexceptionIA ){
    28. Logger. Fatal ("couldn't access class" + classname );
    29. }
    30. Map. Put (classname, Singleton );
    31. Logger.info ("created singleton:" + Singleton );
    32.  
    33. ReturnSingleton;
    34. }
    35. }

    The registry of Singleton classes should note that they should be encapsulated in their own classes for maximum reuse.

    Encapsulate the Registry


    Example 10 lists a single registry class.
    Example 10: singletonregistry class

    1. ImportJava. util.Hashmap;
    2. ImportOrg. Apache. log4j. Logger;
    3.  
    4. Public ClassSingletonregistry {
    5. Public StaticSingletonregistry registry =NewSingletonregistry ();
    6.  
    7. Private Static HashmapMap =New Hashmap();
    8. Private StaticLogger logger = logger. getrootlogger ();
    9.  
    10. ProtectedSingletonregistry (){
    11. // Exists to defeat instantiation
    12. }
    13. Public Static Synchronized ObjectGetinstance (StringClassname ){
    14. ObjectSingleton = map. Get (classname );
    15.  
    16. If(Singleton! =Null){
    17. ReturnSingleton;
    18. }
    19. Try{
    20. Singleton =Class. Forname (classname). newinstance ();
    21. Logger.info ("created singleton:" + Singleton );
    22. }
    23. Catch(ClassnotfoundexceptionCNF ){
    24. Logger. Fatal ("couldn't find class" + classname );
    25. }
    26. Catch(InstantiationexceptionIE ){
    27. Logger. Fatal ("couldn't instantiate an object of type" +
    28. Classname );
    29. }
    30. Catch(IllegalaccessexceptionIA ){
    31. Logger. Fatal ("couldn't access class" + classname );
    32. }
    33. Map. Put (classname, Singleton );
    34. ReturnSingleton;
    35. }
    36. }

    Note that the singletonregistry class is implemented as a singleton mode. I also generalized this registry so that it can store and retrieve any type of objects. The Singleton class shown in example 11 uses this registry.
    Example 11 A singleton class of the encapsulated registry is used.

    1. ImportJava. util.Hashmap;
    2. ImportOrg. Apache. log4j. Logger;
    3.  
    4. Public ClassSingleton {
    5.  
    6. ProtectedSingleton (){
    7. // Exists only to things instantiation.
    8. }
    9. Public StaticSingleton getinstance (){
    10. Return(Singleton) singletonregistry. Registry. getinstance (classname );
    11. }
    12. }

    The Singleton class above uses the unique instance of the Registry to obtain the singleton object through the class name.
    Now we know how to implement the thread-safe Singleton class and how to use a registry to name the order_instance class in the running period. Next let's examine how to arrange the classloader and process serialization.

    Classloaders


    In many cases, using multiple classloaders is common-including servlet containers-so no matter how careful you are when implementing your Singleton class, you can finally get instances of multiple Singleton classes.. If you want to ensure that your Singleton class is loaded by the same class loader, you must specify the class loader by yourself. For example:

    1. Private Static ClassGetclass (StringClassname)
    2. Throws Classnotfoundexception{
    3. ClassloaderClassloader =Thread. Currentthread (). getcontextclassloader ();
    4.  
    5. If(Classloader =Null)
    6. Classloader = Singleton.Class. Getclassloader ();
    7.  
    8. Return(Classloader. loadclass (classname ));
    9. }
    10. }

    This method will try to associate the current thread with the Class Loader. If the classloader is null, this method will use the class loader that loads the single-instance class base class. This method can be replaced by class. forname.

    Serialization


    If you serialize a singleton class and refactor it twice, you will get two instances of that Singleton class unless you implement the readresolve () method, as shown below:
    Example 12: A serializable Singleton class

    1. ImportOrg. Apache. log4j. Logger;
    2.  
    3. Public ClassSingletonImplementsJava. Io.Serializable{
    4. Public StaticSingleton instance =NewSingleton ();
    5.  
    6. ProtectedSingleton (){
    7. // Exists only to things instantiation.
    8. }
    9. [B]Private ObjectReadresolve (){
    10. ReturnInstance;
    11. } [/B]}

    The Singleton class implementation above returns a unique instance from the readresolve () method, so that no matter when the singleton class is restructured, it will only return the same Singleton class instance.
    Example 13 test the singleton class of example 12:
    Example 13 test a serializable Singleton class

    1. ImportJava. Io .*;
    2. ImportOrg. Apache. log4j. Logger;
    3. ImportJUnit. framework.Assert;
    4. ImportJUnit. framework.Testcase;
    5.  
    6. Public ClassSingletontestExtends Testcase{
    7. PrivateSingleton sone =Null, Stwo =Null;
    8. Private StaticLogger logger = logger. getrootlogger ();
    9.  
    10. PublicSingletontest (StringName ){
    11. Super(Name );
    12. }
    13. Public VoidSetup (){
    14. Sone = singleton. instance;
    15. Stwo = singleton. instance;
    16. }
    17. Public VoidTestserialize (){
    18. Logger.info ("testing Singleton serialization ...");
    19. [B] writesingleton ();
    20. Singleton S1 = readsingleton ();
    21. Singleton S2 = readsingleton ();
    22. Assert. Assertequals (True, S1 = S2); [/B]}
    23. Private VoidWritesingleton (){
    24. Try{
    25. FileoutputstreamFos =New Fileoutputstream("Serializedsingleton ");
    26. ObjectoutputstreamOos =New Objectoutputstream(FOS );
    27. Singleton S = singleton. instance;
    28.  
    29. Oos. writeobject (singleton. instance );
    30. Oos. Flush ();
    31. }
    32. Catch(NotserializableexceptionSe ){
    33. Logger. Fatal ("not serializable exception:" + Se. getmessage ());
    34. }
    35. Catch(IoexceptionIox ){
    36. Logger. Fatal ("Io exception:" + iox. getmessage ());
    37. }
    38. }
    39. PrivateSingleton readsingleton (){
    40. Singleton S =Null;
    41.  
    42. Try{
    43. FileinputstreamFiis =New Fileinputstream("Serializedsingleton ");
    44. ObjectinputstreamOis =New Objectinputstream(FS );
    45. S = (Singleton) Ois. readobject ();
    46. }
    47. Catch(ClassnotfoundexceptionCNF ){
    48. Logger. Fatal ("class not found exception:" + CNF. getmessage ());
    49. }
    50. Catch(NotserializableexceptionSe ){
    51. Logger. Fatal ("not serializable exception:" + Se. getmessage ());
    52. }
    53. Catch(IoexceptionIox ){
    54. Logger. Fatal ("Io exception:" + iox. getmessage ());
    55. }
    56. ReturnS;
    57. }
    58. Public VoidTestunique (){
    59. Logger.info ("testing Singleton uniqueness ...");
    60. Singleton another =NewSingleton ();
    61.  
    62. Logger.info ("Checking singletons for Equality ");
    63. Assert. Assertequals (True, Sone = stwo );
    64. }
    65. }

    In the previous test case, serialize the singleton class in example 12 and refactor it twice. Then, this test case checks whether the singleton instance to be restructured is the same object. The following is the output of the test case:

    1.  
    2. Buildfile: Build. xml
    3.  
    4. Init:
    5. [Echo] Build 20030422)
    6.  
    7. Compile:
    8.  
    9. Run-test-text:
    10. [Java]. info main: Testing Singleton serialization...
    11. [Java]. info main: Testing Singleton uniqueness...
    12. [Java] info main: Checking singletonsForEquality
    13.  
    14. <G id = "1"> [Java] Time: 0.1 </G>
    15.  
    16. [Java] OK (2 tests)

    Singleton mode conclusion


    The Singleton mode is simple but confusing, especially for Java developers. In this article, the author demonstrates how Java developers can implement the singleton mode in consideration of multithreading, class loaders, and serialization. The author also shows how you can implement the registry of a singleton class so that you can refer to the order class at run time.

  • Contact Us

    The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

    If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.