Design Mode-singleton Mode

Source: Internet
Author: User

The Singleton mode, also called the singleton mode, is a common software design mode. When this mode is applied, the class of the singleton object must ensure that only one instance exists. In many cases, the whole system only needs to have one global object, which is conducive to coordinating the overall behavior of the system. For example, in a server program, the configuration information of the server is stored in a file, and the configuration data is read by a singleton object in a unified manner, other objects in the service process then obtain the configuration information through the singleton object. This method simplifies Configuration Management in complex environments. The idea of implementing the singleton mode is: A class can return a reference (always the same) to an object and a method to obtain the instance (must be a static method, the getInstance name is usually used). When we call this method, if the reference held by the class is not empty, this reference is returned, if the reference of the class persistence is null, create an instance of the class and assign the instance reference to the reference of the class persistence. At the same time, we also define the constructor of the class as a private method, in this way, the code in other places cannot instantiate the object of this class by calling the constructor of this class. Only the static method provided by this class can be used to obtain the unique instance of this class. The above is a reference definition on Wikipedia. Since the singleton mode only allows one object, the copying and assigning values of objects are not allowed, therefore, we declare all the copy constructors and value assignment operators as private. The first method is to implement 123456789101112131415161718 class Singleton {private: static Singleton * m_instance; Singleton () {}// hide the constructor Singleton (const Singleton &) {}// hide the copy constructor Singleton & operator = (const Singleton & a) {}// hide the value assignment operator ~ Singleton () {}// hide the Destructor public: static Singleton * getInstance () {if (m_instance = NULL) m_instance = new Singleton; return m_instance ;}}; singleton * Singleton: m_instance = NULL; this implementation obviously meets the requirements of the Singleton mode, but there are two problems (1) Our new object is not deleted, (2) this design is not thread-safe (two threads may judge m_instance = NULL at the same time, so that two instances are created). To solve the problem above, the second implementation is as follows. The second implementation is 1234567891011121314151617181920212223242526272829303132333435 class Singleton {private: static. Singleton * m_instance; Singleton () {}// hide the constructor Singleton (const Singleton &) {}// hide the copy constructor Singleton & operator = (const Singleton &) {}// hide the value assignment operator ~ Singleton () {}// hide the Destructor class DelInstance {public :~ DelInstance () {if (Singleton: m_instance) delete Singleton: m_instance ;}}; static DelInstance delIns; // recycles new objects; public: static Singleton * getInstance () {if (m_instance = NULL) {lock (); // lock (lock and unlock are random Write Functions, c ++ does not) if (m_instance = NULL) m_instance = new Singleton; unlock (); // release lock} return m_instance ;}}; Singleton: DelInstance Singleton: delIns; Singleton * Singleton:: m_instance = NUL L; here we use another private embedded class DelInstance, which defines a static object delIns in Singleton to recycle new objects, because the static object delIns will automatically call their own destructor at the end of the program to release the memory pointed to by m_instance, the novice may make two errors: 1. No additional classes are used, write the delete statement directly in the destructor of singleton. This is wrong because we use the new singleton instance, and the Destructor will not be automatically called at the end of the program. If it is called, it will enter an infinite loop, that is, singleton's destructor is used to delete a singleton object. When this object is deleted, singleton's destructor will be called, which keeps repeating. 2. delIns cannot be converted to static. This is also incorrect. If delIns are not static, The delIns will not be parsed until the singleton object is parsed. However, the goal of delIns is to analyze singleton, which is a conflict. If delIns are static, their life cycle has nothing to do with their class objects. It is equivalent to a global one. When their life cycle ends, it will automatically analyze the structure, to analyze singleton. In getInstance, we use double-check to ensure thread security. The thread is locked only when m_instance is NULL. This ensures that only one object instance is created. This is a lazy mode, that is, to create an instance of an object only when necessary. In this article, the third method is to implement 12345678910111213141516171819202122232425262728 class Singleton {private: static Singleton * m_instance; Singleton () {}// hide the const Singleton (const Singleton &) {}// hide copy constructor Singleton & operator = (const Singleton & a) {}// hide the value assignment operator ~ Singleton () {}// hide the Destructor class DelInstance {public :~ DelInstance () {if (Singleton: m_instance) delete Singleton: m_instance ;}}; static DelInstance delIns; // recycles new objects; public: static Singleton * getInstance () {return m_instance ;}}; Singleton: DelInstance Singleton: delIns; Singleton * Singleton: m_instance = new Singleton; this is the hunger mode, that is, when an instance of a class is created from the beginning, its address will be returned in the future, which is thread-safe. Fourth, implement 1234567891011121314151617 class Singleton {private: static Singleton s; Singleton () {}// hide the constructor Singleton (const Singleton &) {}// hide copy constructor Singleton & operator = (const Singleton & a) {}// hide the value assignment operator ~ Singleton () {}// hide the Destructor public: static Singleton * getInstance () {return & s ;}}; Singleton: s; hunger mode, this implementation defines a private static object instance (note that you cannot define your own non-static objects in the class, because this will create an infinite loop definition, and the static object is guaranteed to have only one copy, so it will not be cyclically defined). This is also the fifth thread-safe implementation of 1234567891011121314151617 class Singleton {private: Singleton () {}// hidden constructor Singleton (const Singleton &) {}// hide copy constructor Singleton & operator = (const Singleton & a) {}// hide the value assignment operator ~ Singleton () {}// hide the Destructor public: static Singleton * getInstance () {lock (); // c ++ 11 you do not need to lock static Singleton s; unlock (); return & s ;}}; lazy mode. This implementation only defines the local static variable s when getInstance is called for the first time and then returns it directly. The lock is required before c ++ 11, because the initialization operation of the variable is not an atomic operation. Without the lock, the thread is not secure. c ++ 11 does not need to be locked because c ++ 11 guarantees: if the command logic enters an uninitialized declared variable, all concurrent execution should wait until the variable is fully initialized (see here ). Note that the first, second, third, and fourth methods may cause static initialization order fiasco (refer to here ). In c ++, global variables in the global or namespace scope are declared as static in a class or defined as static in a file range. These three variables are collectively referred to as "non-local static objects". The initialization sequence "C ++" of these three objects is not explicitly specified. Therefore, if a class calls getInstance: struct Foo {Foo () {Singleton: getInstance () ;}; Foo foo; In the constructor, m_instance has been initialized

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.