zoukankan      html  css  js  c++  java
  • <读书笔记> Thinking in python (Python 设计模式) 1. Singlton的c++与python的实现

    1.由于python的天然的泛型特征,python 中没有接口继承,所有的继承都是实现继承,子类为了继承父类的实现。

    2.Singlton 单件模式

    • singlton in c++

          下面看一个最简单的C++实现,它做到的是通过

          类static变量,以及将默认构造函数私有化

          从而使得只能有一个GlobalClass的实体存在

           1 #include <iostream>

     2 using namespace std;
     3 
     4 class GlobalClass {
     5     public:
     6         static GlobalClass* instance();
     7         static void create();
     8         static void destroy();
     9         void print() {
    10             cout << "haha" << endl;
    11         }
    12     private:
    13         static GlobalClass* s_instance;
    14         GlobalClass();
    15         ~GlobalClass(){
    16             //destroy();
    17             cout << "destruct" << endl;
    18 
    19         }
    20 };
    21 
    22 GlobalClass* GlobalClass::s_instance = NULL;
    23 
    24 GlobalClass::GlobalClass() {
    25     cout << "construct global class" << endl;
    26 }
    27 //GloblaClass::~GlobalClass() {
    28 //    destroy();
    29 //    cout << "destruct" << endl;
    30 //}
    31 GlobalClass* GlobalClass::instance() {
    32     return s_instance;
    33 }
    34 
    35 void GlobalClass::create() {
    36     if (!s_instance)
    37         s_instance = new GlobalClass();
    38 }
    39 
    40 void GlobalClass::destroy() {
    41     delete s_instance;
    42     s_instance = NULL;
    43     cout << "delete ok" << endl;
    44 }
    45 
    46 int main(int argc, char *argv[])
    47 {
    48     //GlobalClass my_global_class;  //can't create by this
    49     GlobalClass::create();
    50     GlobalClass* p_global_class = GlobalClass::instance();
    51     p_global_class->print();
    52     GlobalClass::destroy();
    53     return 0;
    54 }
    //result
    construct global class
    haha
    destruct
    delete ok

    刚刚想到effective c++第四款,提到的的利用函数内部local static变量的方法。这样也可以给出一种Siglton的实现
      1 //file singlton.h
      2 
      3 #ifndef _SINGLTON_H_
      4 #define _SINGLTON_H_
      5 #include <iostream>
      6 using namespace std;
      7 
      8 class GlobalClass {
      9     public:
     10         static GlobalClass& instance(int weight = 3){
     11             static GlobalClass global_object(weight);
     12             return global_object;
     13         }
     14         void print() {
     15             cout << "haha" << this << endl;
     16             cout << m_weight << endl << endl;
     17         }
     18         ~GlobalClass(){
     19             cout << "destruct" << this << endl;
     20 
     21         }
     22         void addOne() {
     23             m_weight += 1;
     24         }
     25 
     26     private:
     27         GlobalClass() {
     28             cout <<  "construct global class" << this << endl;
     29 
     30         }
     31         GlobalClass(int weight):m_weight(weight){ cout << "construct global class with weight" << this << endl;}
     32         GlobalClass& operator=const GlobalClass&);
     33         GlobalClass(const GlobalClass&);
     34         int m_weight;
     35 };
     36 #endif
     37 
     38 
     39 //file use_singlton.h
     40 #ifndef USE_SIGLTON_H
     41 #define USE_SIGLTON_H
     42 
     43 #include "singlton.h"
     44 void useSinglton();
     45  
     46 #endif
     47 
     48 //file use_singlton.cc
     49 #include <iostream>
     50 #include "use_singlton.h"
     51 using namespace std;
     52 void useSinglton() {
     53     GlobalClass& p_global_class = GlobalClass::instance(16);
     54     p_global_class.print();
     55     p_global_class.addOne();
     56     p_global_class.print();
     57 
     58     GlobalClass& p_global_class2 = GlobalClass::instance(46);
     59     p_global_class2.print();
     60     p_global_class2.addOne();
     61     p_global_class2.print();
     62 }
     63 
     64 //file test_singlton.cc
     65 #include <iostream>
     66 #include "singlton.h"
     67 #include "use_singlton.h"
     68 using namespace std;
     69 
     70 int main(int argc, char *argv[])
     71 {
     72     cout << "use singlton" << endl;
     73     useSinglton();
     74 
     75     cout << "wa ha ha " << endl;
     76     GlobalClass& p_global_class = GlobalClass::instance(4);
     77     p_global_class.print();
     78     p_global_class.addOne();
     79     p_global_class.print();
     80 
     81     GlobalClass& p_global_class2 = GlobalClass::instance(8);
     82     p_global_class2.print();
     83     p_global_class2.addOne();
     84     p_global_class2.print();
     85 
     86     cout << "ha ha wa" << endl;
     87     useSinglton();    
     88 
     89     return 0;
     90 }
     91 
     92 //allen:~/study/design_pattern/singlton_test$ g++ -g -o test_singlton  test_singlton.cc use_singlton.cc 
     93 allen:~/study/design_pattern/singlton_test$ ./test_singlton 
     94 use singlton
     95 construct global class with weight0x804a5c0
     96 haha0x804a5c0
     97 16
     98 
     99 haha0x804a5c0
    100 17
    101 
    102 haha0x804a5c0
    103 17
    104 
    105 haha0x804a5c0
    106 18
    107 
    108 wa ha ha 
    109 haha0x804a5c0
    110 18
    111 
    112 haha0x804a5c0
    113 19
    114 
    115 haha0x804a5c0
    116 19
    117 
    118 haha0x804a5c0
    119 20
    120 
    121 ha ha wa
    122 haha0x804a5c0
    123 20
    124 
    125 haha0x804a5c0
    126 21
    127 
    128 haha0x804a5c0
    129 21
    130 
    131 haha0x804a5c0
    132 22
    133 
    134 destruct0x804a5c0
    135 
    用local static的这个方法也保证了只有一个实例的存在,不过仅供学习吧,不如第一种方案,毕竟有一个类类型的static变量的存在,
    而且它只能在main介绍的时候才会被析构,上面的我们可以随时主动去析构对象。

    Singlton的基本思想很简单,但是用C++实现,关于资源的释放,何时释放还是感觉很别扭的。
    下面是网上找到的一个基于模版的singlton实现,可以方便的复用该框架,同时利用了shared_ptr,无需操心释放动态内存。
    另外给出一个OPEMESH中的singlton模版的实现,它也是使用了产生一个类类型的static变量(用户需要的时候才会产生出来)。
    这两种方式都会在main结束后析构掉siglton对象资源,如shared_ptr自动释放 new的资源,而OPEMESH的方法static的类对象会销毁(调用起析构函数).
    //使用shared_ptr实现的singlton模版类
     1 #include <iostream>
     2 #include <tr1/memory>
     3 using namespace std;
     4 using namespace std::tr1;
     5 template <typename T>
     6 class Singlton {
     7     public:
     8         static T* instance();
     9         static void create();
    10         void print() {
    11              cout << "haha" << endl;
    12         }
    13         ~Singlton() {
    14             cout << "destruct singlton" << endl;
    15         }
    16     protected:
    17         Singlton();
    18     //private:
    19     protected:
    20         static shared_ptr<T> s_instance; 
    21         //Singlton();
    22 };
    23 template <typename T>
    24 shared_ptr<T> Singlton<T>::s_instance;
    25 
    26 template <typename T>
    27 Singlton<T>::Singlton() {
    28     cout << "construct singlton" << endl;
    29 }
    30 
    31 template <typename T>
    32 T* Singlton<T>::instance() {
    33     return s_instance.get();
    34 }
    35 
    36 template <typename T>
    37 void Singlton<T>::create() {
    38     if (!s_instance.get())
    39         s_instance.reset(new T);
    40 
    41 }
    42 
    43 // well 这里注意,我理解为Singlton<T>::create() 应该可以调用 MySinglton的私有函数,但事实上不行
    44 // 因为理论上 还是调用基类的函数 Singlton<MySinglton>::create()
    45 //class MySinglton : public Singlton<MySinglton> {
    46 //    //private:
    47 //    public:
    48 //        MySinglton(){
    49 //            cout << "construct my singlton" << endl;
    50 //        }
    51 //
    52 //};
    53 class MySinglton : public Singlton<MySinglton> {
    54         friend  class Singlton<MySinglton>;
    55     private:
    56         MySinglton(){
    57             cout << "construct my singlton" << endl;
    58         }
    59         MySinglton * MyInstance() {
    60             return s_instance.get();
    61         }
    62 };
    63 
    64 //or can directyly define one class like MyClass1, and to not consider siglton part,
    65 //than use Singlton<MyClass1>  is OK. May be typedef Singlton<MyClass1> MyClass1Singlton 
    66 //and use MyClass1Siglton
    67 int main(int argc, char *argv[])
    68 {
    69        
    70     MySinglton::create();
    71     MySinglton* p_my_singlton = MySinglton::instance();
    72     p_my_singlton->print();
    73     return 0;
    74 }
    75 /*result
    76 construct singlton
    77 construct my singlton
    78 haha
    79 destruct singlton
    80 */
    OPMESH的singlton模版类的实现,这个似乎更专业些:)
      1 //SingltonT.hh
      2 //=============================================================================
      3 //
      4 //  Implements a simple singleton template
      5 //
      6 //=============================================================================
      7 
      8 
      9 #ifndef __SINGLETON_HH__
     10 #define __SINGLETON_HH__
     11 
     12 
     13 //=== INCLUDES ================================================================
     14 
     15 // OpenMesh
     16 #include <OpenMesh/Core/System/config.h>
     17 
     18 // STL
     19 #include <stdexcept>
     20 #include <iostream>
     21 
     22 
     23 //== NAMESPACES ===============================================================
     24 
     25 
     26 namespace OpenMesh {
     27 
     28 
     29 //=== IMPLEMENTATION ==========================================================
     30 
     31 
     32 /** A simple singleton template.
     33     Encapsulates an arbitrary class and enforces its uniqueness.
     34 */
     35 
     36 template <typename T>
     37 class SingletonT
     38 {
     39 public:
     40 
     41   /** Singleton access function.
     42       Use this function to obtain a reference to the instance of the 
     43       encapsulated class. Note that this instance is unique and created
     44       on the first call to Instance().
     45   */
     46 
     47   static T& Instance()
     48   {
     49     if (!pInstance__)
     50     {
     51       // check if singleton alive
     52       if (destroyed__)
     53       {
     54     OnDeadReference();
     55       }
     56       // first time request -> initialize
     57       else
     58       {
     59     Create();
     60       }
     61     }
     62     return *pInstance__;
     63   }
     64 
     65 
     66 private:
     67 
     68   // Disable constructors/assignment to enforce uniqueness
     69   SingletonT();
     70   SingletonT(const SingletonT&);
     71   SingletonT& operator=(const SingletonT&);
     72 
     73   // Create a new singleton and store its pointer
     74   static void Create()
     75   {
     76     static T theInstance;
     77     pInstance__ = &theInstance;
     78   }
     79   
     80   // Will be called if instance is accessed after its lifetime has expired
     81   static void OnDeadReference()
     82   {
     83     throw std::runtime_error("[Singelton error] - Dead reference detected!\n");
     84   }
     85 
     86   virtual ~SingletonT()
     87   {
     88     pInstance__ = 0;
     89     destroyed__ = true;
     90   }
     91   
     92   static T*     pInstance__;
     93   static bool   destroyed__;
     94 };
     95 
     96 
     97 
     98 //=============================================================================
     99 // namespace OpenMesh
    100 //=============================================================================
    101 #if defined(OM_INCLUDE_TEMPLATES) && !defined(OPENMESH_SINGLETON_C)
    102 #  define OPENMESH_SINGLETON_TEMPLATES
    103 #  include "SingletonT.cc"
    104 #endif
    105 //=============================================================================
    106 #endif // __SINGLETON_HH__
    107 //=============================================================================
    108 
    109 
    110 //SingltonT.cc
    111 //=============================================================================
    112 //
    113 //  Implements a simple singleton template
    114 //
    115 //=============================================================================
    116 
    117 
    118 #define OPENMESH_SINGLETON_C
    119 
    120 
    121 //== INCLUDES =================================================================
    122 
    123 
    124 // header
    125 #include <OpenMesh/Core/Utils/SingletonT.hh>
    126 
    127 
    128 //== NAMESPACES ===============================================================
    129 
    130 
    131 namespace OpenMesh {
    132 
    133 
    134 //== SINGLETON'S DATA =========================================================
    135 
    136 
    137 template <class T> 
    138 T* SingletonT<T>::pInstance__ = 0;
    139 
    140 template <class T>
    141 bool SingletonT<T>::destroyed__ = false;
    142 
    143 
    144 //=============================================================================
    145 // namespace OpenMesh
    146 //=============================================================================
    147 
    使用的时候如
    typedef SingletonT<LoopSchemeMaskDouble>    LoopSchemeMaskDoubleSingleton;
    

    • singlton in python

          那么在python中,作者提到的singlton的概念得到了放宽,

               Alex Martelli makes the observation that what we really want with a
               Singleton is to have a single set of state data for all objects. That is, you
               could create as many objects as you want and as long as they all refer to
               the same state information then you achieve the effect of Singleton.

          你可以有任意多的对象,但是它们都指向相同的状态信息,即为singlton。Borg利用__dict__属性巧妙的实现了一个

          singlton 模式。

    
    
     1 class Borg():
     2     shared_dict = {}
     3     def __init__(self):
     4         self.__dict__ = self.shared_dict  
     5 
     6 class Singleton(Borg):
     7     def __init__(self, arg):
     8         Borg.__init__(self)
     9         self.val = arg
    10     def __str__(self): 
    11         print(self.__dict__)
    12         return self.val
    13 
    14 
    15 if __name__ == '__main__':
    16     x = Singleton('abc')
    17     y = Singleton('def')
    18     print(x)
    19     print(y)
    20 
    21 output = '''
    22 {'val': 'def'}
    23 def
    24 {'val': 'def'}
    25 def
    26 '''

    这种方案,简洁清楚,并且很容易通过继承而复用。当然作者还提到许多其它的实现方法,对比下面的方法。

      1 class OnlyOne:

     2 
     3     class __OnlyOne:
     4         def __init__(self, arg):
     5             self.val = arg
     6         def __str__(self):
     7             return 'self' + self.val
     8             #return `self` + self.val
     9     instance = None
    10     def __init__(self, arg):
    11         if not OnlyOne.instance:
    12             OnlyOne.instance = OnlyOne.__OnlyOne(arg)
    13         else:
    14             OnlyOne.instance.val = arg
    15     def __getattr__(self, name):
    16         return getattr(self.instance, name)
    17 
    18 
    19 = OnlyOne('sausage')
    20 print(x)
    21 = OnlyOne('eggs')
    22 print(y)
    23 = OnlyOne('spam')
    24 print(z)
    25 
    26 print(x)
    27 print(y)
    28 print(z)
    29 print('x')
    30 print('y'
    31 print('z'
    32 
    33 print(x.instance)
    34 output = '''
    35 selfsausage
    36 selfeggs
    37 selfspam
    38 selfspam
    39 selfspam
    40 selfspam
    41 x
    42 y
    43 z
    44 selfspam
    45 '''

  • 相关阅读:
    Python time ctime()方法
    Python time clock()方法
    Python time asctime()方法
    Python time altzone()方法
    Python 日期和时间
    java——字符串常量池、字符串函数以及static关键字的使用、数组的一些操作函数、math函数
    java——API
    java——类、对象、private、this关键字
    Java——方法及构造方法、intellij IDEA中的一些快捷键
    IntelliJ IDEA 运行java程序时出现“程序发生找不到或无法加载主类 cn.test1.test1”错误
  • 原文地址:https://www.cnblogs.com/rocketfan/p/1574900.html
Copyright © 2011-2022 走看看