開始復習設計模式,第一個,單件模式。
我想我要寫的東西太長了,于是我打算說我解決了什么問題,基礎足夠的同學請自行補腦。

單件模式為解決復雜系統(tǒng)只需要一個實例的問題。但是沒有提在C++里面怎么解決內(nèi)存自動釋放的問題。
我相信大多數(shù)人首先想到的C++實現(xiàn)都單純的類似這樣:
class Singleton 

public
~Singleton(){} 
static Singleton* Instance() 

  if (_instance == NULL) 
  { 
   _instance = new Singleton(); 
  } 
  return _instance; 

private
Singleton(){} 
static Singleton* _instance; 
}; 
Singleton* Singleton::_instance = NULL;

這個確實是單件模式了,但是它沒有解決單例的生命周期問題,new出來的內(nèi)存沒有delete掉,那么這個對象的生命到底什么時候結(jié)束呢?
答案不是確定的,在不同的操作系統(tǒng)平臺上又不同的情況。Unix下是進程消失時內(nèi)存釋放。

我們來解決這個問題,給它加一個清理器。嘿嘿!~~
為了更加通用,我打算用模板來實現(xiàn),請看代碼:

// singleton.h
#ifndef __SINGLETON__
#define __SINGLETON__

#include <iostream>

template<typename T>
class Singleton {
public:
    static T *instance(){
        if (_instance == nullptr) {  //clang++ c++11標準
            _instance = new T;
            static Cleaner clr;  //延遲單件模式的清理對象
            /*
              static Cleaner clr;這個聲明,由于是靜態(tài)成員,系統(tǒng)會在棧里分配內(nèi)存,回收工作也就由系統(tǒng)自動完成了。
             
*/
        }
        return _instance;
    }
    
private:
    Singleton(){
    }
    Singleton(const Singleton &s){};
    void operator=(const Singleton &rhs){};
    static T *_instance;
    
    class Cleaner { 
    public
        Cleaner(){
            std::cout<<"Singleton cleaner Construct"<<std::endl;
        } 
        ~Cleaner(){
            std::cout<<"Singleton cleaner Deconstruct"<<std::endl;
            if(Singleton<T>::instance()) {
                delete Singleton::instance();
            }
        } 
    }; 
};
 
template<typename T> T * Singleton<T>::_instance = nullptr;
 
#endif

那么我們來使用一下:
#include <iostream>
#include "singleton.h"

typedef class aClass{
    //整個函數(shù)可以注釋掉
public:
    void Print(const char* str){ 
        std::cout << "aClass print:" << str;
        std::cout<<", my address is " << this << std::endl;
    }
    ~aClass(){
        std::cout<<"aClass Deonstruct"<<std::endl;  //可以注釋
    }
    aClass(){
        std::cout<<"aClass Construct"<<std::endl;  //可以注釋
    }
}aClass;

void
 f(){
    Singleton<aClass >::instance()->Print("print 1"); 
    Singleton<aClass >::instance()->Print("print 2");
}

int main(){
    f();
    return 0;
}
這樣解決了單件模式自動釋放的問題。
原理是什么呢?
在instance中,static Cleaner clr;這個聲明,由于是靜態(tài)成員,系統(tǒng)會在棧里分配內(nèi)存,回收工作也就由系統(tǒng)自動完成了。

有時候我們要考慮單件在整個軟件系統(tǒng)中的釋放順序,因此,
如果您還有興趣,我們可以看一下這個單例的釋放究竟是在什么時候:
#include <vector>
#include "singleton.h"

typedef class aClass{
    //整個函數(shù)可以注釋掉
public:
    void Print(const char* str){ 
        std::cout << "aClass print:" << str;
        std::cout<<", my address is " << this << std::endl;
    }
    ~aClass(){
        std::cout<<"aClass Deonstruct"<<std::endl;  //可以注釋
    }
    aClass(){
        std::cout<<"aClass Construct"<<std::endl;  //可以注釋
    }
}aClass;

void f(){
    Singleton<aClass >::instance()->Print("print 1"); 
    Singleton<aClass >::instance()->Print("print 2");
}

class bClass{
public:
    bClass(){
        std::cout<<"bClass Construct"<<std::endl;
    }
    ~bClass(){
        std::cout<<"bClass Deconstruct"<<std::endl;
    }
}globalObject;

class cClass{
public:
    cClass(){
        std::cout<<"cClass Construct"<<std::endl;
    }
    ~cClass(){
        std::cout<<"cClass Deconstruct"<<std::endl;
    }
};

int main(){
    cClass c;
    
    f();
    
    Singleton<aClass >::instance()->Print("print 2");
    
    return 0;
}

根據(jù)在MAC下的控制臺的輸出結(jié)果:
clang++ -std=c++1y main.cpp && ./a.out
bClass Construct
cClass Construct
aClass Construct
Singleton cleaner construct
aClass print:print 1, my address is 0x7f923ac000e0
aClass print:print 2, my address is 0x7f923ac000e0
aClass print:print 2, my address is 0x7f923ac000e0
cClass Deconstruct
Singleton cleaner deconstruct
aClass Deonstruct
bClass Deconstruct

我們可以看出,這個單件模式的實例的釋放時機為:在main退出之后,在全局對象析構之前。(也就是說它的釋放時機是和系統(tǒng)的棧內(nèi)存一樣的。)

最后有人會問,你這個沒有考慮多線程下的問題。
是的,不過這也簡單,我們?yōu)閕nstance函數(shù)添加互斥條件就可以了。

謝謝參觀!