A single case model of C + + design pattern _c language

Source: Internet
Author: User

Problem description

Now, no matter how big a system is developed (at least my current department is like this), will bring a log function, in the actual development process, there will be a special log module, responsible for writing the log, because in the system anywhere, we are likely to call the log module functions, to write a log. So, how do you construct an instance of a log module? Don't tell me you did it every time you write a new log module instance, finish the log, and then delete it. In C + +, you can construct a global variable for a log module, so you can use it anywhere, yes, that's right. However, the C + + coding specification for my development department is modelled on Google's coding specifications.

Global variables can be used in the project, it is a time bomb, is an unsafe hidden trouble, especially in multithreaded programs, there will be a lot of unpredictability, while using global variables, also does not conform to the object-oriented encapsulation principle, so, in pure object-oriented language Java and C #, There is no pure global variable. So, how to solve this log problem perfectly, we need to introduce the single case pattern in the design pattern.

Single case mode

What is a singleton pattern, in Gof's design pattern: The basics of reusable object-oriented software: To ensure that a class has only one instance and to provide a global access point to access it. First, you need to make sure that a class has only one instance; In a class, to construct an instance, you must call the constructor of the class, so that to prevent the constructor of the class from being invoked externally, you need to mark the access permission of the constructor as protected or private; To provide a global access point, you need to define a static function in the class to return an instance that is uniquely constructed inside the class. The meaning is clear, using UML class diagrams to represent the following.

UML Class Diagram

Code implementation

Single example mode, from UML class diagram, on a class, there is no complex relationship. However, in real projects, there are many aspects to consider when using code implementations.

Achieve one:

Copy Code code as follows:

/*
* * FILENAME:SINGLETONPATTERNDEMO1
* * author:jelly Young
* * DATE:2013/11/20
* * Description:more information, http://www.jb51.net
*/

#include <iostream>
using namespace Std;

Class Singleton
{
Public
Static Singleton *getinstance ()
{
if (m_instance = NULL)
{
M_instance = new Singleton ();
}
return m_instance;
}

static void Destoryinstance ()
{
if (m_instance!= NULL)
{
Delete m_instance;
M_instance = NULL;
}
}

This is just a operation example
int Gettest ()
{
return m_test;
}

Private
Singleton () {m_test = 10;}
Static Singleton *m_instance;
int m_test;
};

Singleton *singleton:: m_instance = NULL;

int main (int argc, char *argv [])
{
Singleton *singletonobj = Singleton:: getinstance ();
Cout<<singletonobj->gettest () <<endl;

Singleton::D estoryinstance ();
return 0;
}

This is the simplest, is also the most common way of implementation, but also the current online blog accounts of the implementation of the way, but this implementation, there are many problems, such as: Do not take into account the problem of multithreading, in the case of multithreading, you may create multiple singleton instances, the following version is an improved version.

Realize two:

Copy Code code as follows:

/*
* * Filename:singletonpatterndemo2
* * author:jelly Young
* * DATE:2013/11/20
* * Description:more information, http://www.jb51.net
*/

#include <iostream>
using namespace Std;

Class Singleton
{
Public
Static Singleton *getinstance ()
{
if (m_instance = NULL)
{
Lock (); C + + does not have a direct lock operation, please use lock of other libraries, such as boost, here just to illustrate
if (m_instance = NULL)
{
M_instance = new Singleton ();
}
UnLock (); C + + does not have a direct lock operation, please use lock of other libraries, such as boost, here just to illustrate
}
return m_instance;
}

static void Destoryinstance ()
{
if (m_instance!= NULL)
{
Delete m_instance;
M_instance = NULL;
}
}

int Gettest ()
{
return m_test;
}

Private
Singleton () {m_test = 0;}
Static Singleton *m_instance;
int m_test;
};

Singleton *singleton:: m_instance = NULL;

int main (int argc, char *argv [])
{
Singleton *singletonobj = Singleton:: getinstance ();
Cout<<singletonobj->gettest () <<endl;
Singleton::D estoryinstance ();

return 0;
}

This is the two times m_instance = null judgment, is borrowed from the Java single example mode implementation, the use of the so-called "double check lock" mechanism. Because a lock and unlock is required to pay the corresponding cost, and two times to judge, you can avoid multiple lock and unlock operations, but also to ensure thread safety. However, this method of implementation in peacetime project development used very well, there is no problem? However, if the operation of large data, the lock operation will become a performance bottleneck; For this reason, the implementation of a new single example pattern appears.

Realize three:

Copy Code code as follows:

/*
* * FILENAME:SINGLETONPATTERNDEMO3
* * author:jelly Young
* * DATE:2013/11/20
* * Description:more information, http://www.jb51.net
*/

#include <iostream>
using namespace Std;

Class Singleton
{
Public
Static Singleton *getinstance ()
{
return const_cast <singleton *> (m_instance);
}

static void Destoryinstance ()
{
if (m_instance!= NULL)
{
Delete m_instance;
M_instance = NULL;
}
}

int Gettest ()
{
return m_test;
}

Private
Singleton () {m_test = 10;}
static const Singleton *m_instance;
int m_test;
};

Const Singleton *singleton:: m_instance = new Singleton ();

int main (int argc, char *argv [])
{
Singleton *singletonobj = Singleton:: getinstance ();
Cout<<singletonobj->gettest () <<endl;
Singleton::D estoryinstance ();
}

The static initialization instance guarantees thread security because static initialization completes the initialization in a single-threaded manner before the program starts, that is, before the main function is entered. When performance requirements are high, this approach can be used to avoid resource wastage caused by frequent lock and unlock. Due to the above three implementations, we have to take into account the destruction of the instance, the destruction of the case will be in the analysis. As a result, a fourth implementation is present:

Achieve four:

Copy Code code as follows:

/*
* * Filename:singletonpatterndemo4
* * author:jelly Young
* * DATE:2013/11/20
* * Description:more information, http://www.jb51.net
*/

#include <iostream>
using namespace Std;

Class Singleton
{
Public
Static Singleton *getinstance ()
{
Static Singleton m_instance;
Return &m_Instance;
}

int Gettest ()
{
return m_test++;
}

Private
Singleton () {m_test = 10;};
int m_test;
};

int main (int argc, char *argv [])
{
Singleton *singletonobj = Singleton:: getinstance ();
Cout<<singletonobj->gettest () <<endl;

Singletonobj = Singleton:: getinstance ();
Cout<<singletonobj->gettest () <<endl;
}

The above is four kinds of mainstream single example mode of implementation, if you have any good way to achieve, I hope you can recommend to me. Thank you, sir.

instance Destroy

Of the four methods mentioned above, the remaining three are used except for the fourth, which is not instantiated with the new operator; Our general programming idea is that the new operation needs to match the delete operation; Yes, that's the right idea. In the above implementation, it is added a destoryinstance static function, which is also the simplest and most common method of processing; however, many times, it is easy to forget to call the Destoryinstance function, just as you forget to call the delete operation. Because of the fear of forgetting the delete operation, there is a smart pointer, so, in a single example model, there is no "smart single case", What to do? What to do?

Let me start with the actual project, in the actual project, especially the client development, actually do not care about the destruction of this instance. Because, the global is such a variable, the overall use, its lifecycle with the software lifecycle, the software is over, it will automatically end, because a program is closed, it will release the memory resources it occupies, so, there is no so-called memory leaks. However, the following conditions are necessary for instance destruction:

1. In the class, there are some file locks, file handles, database connections, and so on, these resources, which will not close immediately as the program closes, must be manually released before the program closes;

3. A programmer with obsessive compulsive disorder.

Above, that is my summary of the two points.

Although the fourth method in the code implementation section satisfies the second condition, the first condition cannot be met. Ok, next, I'll introduce a method that I've learned from the Web, and the code is implemented as follows:

Copy Code code as follows:

/*
* * FILENAME:SINGLETONPATTERNDEMO5
* * author:jelly Young
* * DATE:2013/11/20
* * Description:more information, http://www.jb51.net
*/

#include <iostream>
using namespace Std;

Class Singleton
{
Public
Static Singleton *getinstance ()
{
return m_instance;
}

int Gettest ()
{
return m_test;
}

Private
Singleton () {m_test = 10;}
Static Singleton *m_instance;
int m_test;

This is important
Class GC
{
Public:
~GC ()
{
We can destory all of the resouce here, eg:db Connector, file handle and
if (m_instance!= NULL)
{
cout<< "This is the test" <<endl;
Delete m_instance;
M_instance = NULL;
}
}
};
Static GC GC;
};

Singleton *singleton:: m_instance = new Singleton ();
Singleton:: GC Singleton:: GC;

int main (int argc, char *argv [])
{
Singleton *singletonobj = Singleton:: getinstance ();
Cout<<singletonobj->gettest () <<endl;

return 0;
}

At the end of the program run, the system invokes the destructor of the static member GC of Singleton, which releases the resource in a way that the programmer "does not know", while the programmer does not have to be particularly concerned with the use of the Code of the single case pattern There is no need to care about the release of resources. So what is the rationale for this implementation? When I analyze the problem, I like to dissect it to the root of the problem, and never be confused to stay on the surface. As the program ends, the system automatically reconstructs all the global variables, and in fact, the system also reconstructs the static member variables of all classes, just as these static variables are global variables. We know that both static variables and global variables are stored in the static storage in memory, so they are treated equally in the destructor.

Because an internal GC class is used here, and the class is used to release resources, and this technique is widely available in C + +, I will summarize this technique in later blogs, see the RAII mechanism in C + +.

Schema extension

In the actual project, a pattern is not as simple as our code here, only in the familiar with the characteristics of various design patterns in order to better use in the actual project. The single case pattern and the factory pattern are often seen in actual projects, and the combination of the two patterns is common in the project. Therefore, it is necessary to sum up the combination of the two modes of use.

A product, which is produced in a factory, is a description of a factory model, and only one factory can produce a product, which is a description of a single example pattern. So, in practice, a product, we only need a factory, at this time, we need the factory model and the combination of a single case model design. Because the single case pattern provides an external global access point, we need to define an identity that identifies which single piece to create, using a method like that in a simple factory pattern. Because of the more analog code, at the end of the article, provide a download link.

Summarize

In order to write this article, his own investigation of a lot of information, because the information on the Internet in all aspects have a lot of flaws, the quality of the time is not homogeneous, I also caused a certain misleading. And this article, have my own understanding, if there is a mistake, please correct me.

Because of this article to the design pattern summary, I thought than on-line 80% All is comprehensive, hoped is useful to everybody. In the actual development, and will not use a single example of such a variety of patterns, each design pattern, should be in the most appropriate situation to use, in the future projects, should be able to put the vector, but not in order to use design patterns and design patterns.

Project download

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.