A single case model and c++11 of C + + for the optimization of Singleton mode

Source: Internet
Author: User

Single-Case mode

Singleton mode, it can be said that the design pattern is the most commonly used mode, is said to be the interviewer's favorite topic. But if you have not learned the design pattern of people, may not think to apply a singleton mode, facing the situation of the singleton mode, may prefer to use global or static variables, this is relatively simple, but also did not learn the design pattern of the most simple way to think of people.

In general, some of the classes we build are tool-like and do not need to store too much data about ourselves, in which case, each time you go to new object, it adds overhead and makes the code more bloated. In fact, we just need an instance object to do it. Using global or static variables can affect encapsulation and make it difficult to ensure that other code does not affect global variables.

With these requirements in mind, we declare the default constructor private so that it is not new to the outside, and you can even declare the destructor as private so that only you can delete yourself. In plain object-oriented languages such as Java and C #, the singleton pattern is very well implemented and can be initialized directly in the static area and then returned by GetInstance, which is known as the A Hungry Man Singleton class (instance). Also some of the wording is in getinstance new instance and then return, this is called the lazy Singleton class, but this involves the first getinstance of a judgement problem.

The following code is just an indication of which language is not related.

Single Thread:

singleton* getinstance () {    if (instance = = NULL        )new  Singleton ();      return  instance;}

This makes it possible to ensure that only one instance is obtained. However, in a multi-threaded environment, it is not possible, because it is likely that two threads run simultaneously to the IF (instance = = NULL) sentence, resulting in the possibility of generating two instances. The code is then locked.

singleton* getinstance () {    lock();     if (Instance = = NULL)    {       new  Singleton ();    }    Unlock ();     return instance;}

But in this case, it will slightly image performance, because each time the judgment is empty need to be locked, if there are many threads, love will cause a lot of thread blocking. Then there was a double lock.

singleton* getinstance () {    if (instance = = NULL    )    {lock()        ; if (Instance = = NULL)        {               new  Singleton ();        }        Unlock ();    }     return instance;}

This is only a very low probability, by crossing the IF (instance = = NULL) thread will have to enter the lock critical section of the possibility, the probability is relatively low, does not block too many threads, but in order to prevent a thread into the critical section to create an instance, the other thread also went into the critical section to create an instance, A defensive if (instance = = NULL) is added, which ensures that the creation is not repeated.

Common scenarios

The singleton pattern is often used in conjunction with Factory mode, because the factory only needs to create product instances, and in the multi-threaded environment will not cause any conflicts, so only a factory instance is required.

Advantages

1. Reduces the cost of time and space (the cost of the new instance).

2. Improve the encapsulation, make the external difficult to change the instance.

Disadvantages

1. Lazy-type is the way to change space by time. (the method used above)

2. The A Hungry man style is a way of space-changing time. (the method used below)

#ifndef _singleton_h_#define_singleton_h_classsingleton{ Public:    Staticsingleton*getinstance ();Private: Singleton (); //The copy constructor and = operator are also set to private to prevent replicationSingleton (Constsingleton&); Singleton&operator=(Constsingleton&); Staticsingleton*instance;};#endif#include"Singleton.h"Singleton::singleton () {}singleton::singleton (Constsingleton&) {}singleton& Singleton::operator=(Constsingleton&){}//Initialize heresingleton* singleton::instance =NewSingleton (); Singleton*singleton::getinstance () {returninstance;} #include"Singleton.h"#include<stdio.h>intMain () {Singleton* Singleton1 =singleton::getinstance (); Singleton* Singleton2 =singleton::getinstance (); if(Singleton1 = =singleton2) fprintf (stderr,"Singleton1 = singleton2\n"); return 0;}

there are problems with the methods used above: only types with no parameters can be instantiated, and other types with parameters are not.

C++11 provides us with a solution: variable template parameters

  

Template <typename t>classsingleton{ Public: Template<typename ... Args>Statict* Instance (args&&.. args) {        if(m_pinstance==nullptr) m_pinstance=NewT (std::forward<args>(args) ...); returnm_pinstance; }Statict*getinstance () {if(M_pinstance = =nullptr)ThrowStd::logic_error ("The instance isn't init, please initialize the instance first"); returnm_pinstance; }Static voiddestroyinstance () {delete m_pinstance; M_pinstance=nullptr; }Private: Singleton (void); Virtual~singleton (void); Singleton (Constsingleton&); Singleton&operator= (Constsingleton&);Private:    Statict*m_pinstance;}; Template<classt> t* singleton<t>::m_pinstance = nullptr;

Since the original interface, the initialization and the value of the Singleton object is an interface, may be misused, after the update, the initialization and the value is divided into two interfaces, the use of a single case is: first initialization, after the value, if the halfway destroy the single case, the need to re-fetch value. If the value is not initialized, an exception is thrown.

The realization of Multiton

#include <map>#include<string>#include<memory>using namespacestd;template< TypeName T, typename K =string>classmultiton{ Public: Template<typename ... Args>StaticStd::shared_ptr<t> Instance (Constk& Key, args&&.. args) {        returnGetInstance (Key, std::forward<args>(args) ...); } template<typename ... Args>StaticStd::shared_ptr<t> Instance (k&& key, args&&.. args) {        returnGetInstance (Key, std::forward<args>(args) ...); }Private: Template<typename Key, TypeName ... Args>StaticStd::shared_ptr<t> getinstance (key&& Key, args&&.. args) {Std::shared_ptr<T> instance =nullptr; Auto It=M_map.find (key); if(It = =M_map.end ()) {Instance= Std::make_shared<t> (std::forward<args>(args) ...);        M_map.emplace (key, instance); }        Else{instance= it->second; }        returninstance; }Private: Multiton (void); Virtual~multiton (void); Multiton (Constmultiton&); Multiton&operator= (Constmultiton&);Private:    StaticMap<k, std::shared_ptr<t>>M_map;}; Template<typename T, TypeName k>Map<k, std::shared_ptr<t>> multiton<t, k>::m_map;

A single case model and c++11 of C + + for the optimization of Singleton mode

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.