C + + Implementation of design pattern 1. Single case mode __c++

Source: Internet
Author: User
Tags instance method

A singleton pattern is the implementation of a singleton class, that is, a class in the system has only one instance, and the instance is easy to access outside. This facilitates the control of the number of instances and saves system resources.

And a single example commonly used with some nonlocal static objects, for these objects, the program is difficult to control, and for these objects that are present and global, and generally persisted, sometimes need to be initialized in a certain constraint or order, and initialization of these objects is extremely unsafe without using a single instance method. This is the time to use a single example mode to solve this problem.

There are a number of ways to implement a single example, the simplest of which is to put an object in a function as its static member:

Class SingleTon;
singleton* getsingletoninstance () {
	static singleton* instance = new SingleTon (); 
	return instance;
}
Class singleton{
	friend singleton* getsingletoninstance ();
Private:
	SingleTon () {}
};
This is the simplest way I think of implementing a single case pattern, but the disadvantage is that the function that gets the single instance object is not in the class. The first is to implement the single case pattern, declaring the constructor as rare so that the constructor cannot be a method or create an object of a single instance class at will. And here you get the static object of the instance as a function, so there is only one, and the time is created to the end of the program.

Of course, you can also change a static object in a function to a static object in a class, and the global function is set to a static function in the class, which is a more commonly used form:

Class singleton{public
:
	static singleton* getinstance () {
		static singleton* instance = new SingleTon ();
		return instance;
	}
	~singleton () {}
private:
	SingleTon () {	}
	SingleTon (const singleton&);
	singleton& operator= (const singleton&);
It is also possible to use static members in a function, using static members in a class:

Class singleton{public
:
	static singleton* getinstance () {
		if (NULL = = Instance)
			Instance = new SingleTon ();
		return instance;
	}

Private:
	SingleTon () {	}
	SingleTon (const singleton&);
	singleton& operator= (const singleton&);
	static singleton* instance;
singleton* singleton::instance;//= new SingleTon (); Static member initialization within a class can invoke a private constructor in a class.

For security, the copy constructor and assignment operators are hidden here, but the destructor is still visible, and the programmer will still misuse delete to delete the single entity, which is unsafe, optionally putting the destructor in private, hiding the destructor, and then, for some objects at the end of the destructor, You don't have to care about the release process.

However, if you want to call a destructor for instance deletion in the execution of a program, you use a public function to encapsulate the destructor and make the destructor private:

Class singleton{public
:
	static singleton* getinstance () {
		if (NULL = = Instance)
			Instance = new SingleTon ();
		return instance;
	}
	static void Delelteinstance () {
		if (NULL!= instance) {
			Delete instance;
			instance = NULL;
		}
	}
Private:
	SingleTon () {	}
	SingleTon (const singleton&);
	singleton& operator= (const singleton&);
	static singleton* instance;
	~singleton ();
};
singleton* singleton::instance;

This is basically safe on a single thread, then consider multithreading, when multiple threads attempt to initialize a singleton instance at the same time, there is a problem, to use mutexes to solve the problem, here is the use of a critical section to resolve:

Critical_section CS;
Class singleton{public
:
	static singleton* getinstance () {
		if (NULL = = Instance) {
			EnterCriticalSection (&CS); 
			if (NULL = = instance) {//double check lock, after entering the critical section to detect whether the object has been established
				instance = new SingleTon ();
			}
			LeaveCriticalSection (&CS);  
		}
		return instance;
	}
	static void Delelteinstance () {
		if (NULL!= instance) {
			entercriticalsection (&CS);
			if (NULL!= instance) {
				Delete instance;
				instance = NULL;
			}
			LeaveCriticalSection (&CS);  
		}
Private:
	SingleTon () {	}
	SingleTon (const singleton&);
	singleton& operator= (const singleton&);
	static singleton* instance;
	~singleton ();
};
singleton* singleton::instance;
Here, the mechanism of double check lock is the first time to determine whether the instance needs to be manipulated. The second is to enter the critical area that is, after the data lock, judge the data is no longer outside interference in the case, the first judgment and the second judgment is carried out between the other threads, so that two judgments to ensure the security of the instance.

But this is not safe enough, because there are still some special cases in the thread, some files in the class are locked, such as file handle, database connection, etc., which will not immediately close the resource as the program closes, you must manually release the program before it shuts down. The point here is not automatically closed, but for the destructor is private, because the system cannot access a private destructor, a class that occupies only a few addresses in memory when there is no such connection, the system treats it as a global variable and releases its memory resources at the end, so there is no memory leak. And if there are file handles and database connections in the class, the system does not help to close them, so you must manually invoke the shutdown of those files in the destructor.

For such a situation, typically, a private inline class Garbo, meaning garbage worker, contains a private static garbage worker object in a single instance class, and when the program ends, the system calls the destructor of the object, which is the destructor of a single instance class object.

Critical_section CS; 
			Class singleton{public:static singleton* getinstance () {if (NULL = = instance) {entercriticalsection (&CS);
			if (NULL = = instance) {//double check lock, after entering the critical section to detect whether the object has been established instance = new SingleTon ();  
		} leavecriticalsection (&cs);
	return instance;
			} static void Delelteinstance () {if (NULL!= instance) {entercriticalsection (&CS);
				if (NULL!= instance) {Delete instance;
			instance = NULL;  
		} leavecriticalsection (&cs);
	} Private:singleton () {} SingleTon (const singleton&);
	singleton& operator= (const singleton&);
	static singleton* instance; ~singleton () {}//Operations class garbo{public: ~garbo () {if (NULL!= instance) {entercriticalsection (&c)
					s);
						if (NULL!= instance) {Delete instance;
					instance = NULL;  
				} leavecriticalsection (&cs);
	}
			}
	};
Static Garbo GC;
};
singleton* singleton::instance; Singleton::garbo initialization outside the singleton::gc;//class.
This makes for a more perfect single case class.


Related Article

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.