Singleton:确保每一类只有一个实例,并且提供对这个实例的全局访问
通常用于需要共享的资源。例如数据库对象
Singleton还是一种有效保护使变量免遭改写的技术
实现方法
构造函数私有化
用一个静态函数作为constructor,通过它创建一个新对象并存储在一个静态空间里
Python中的实现有一些魔法,其中一个就是Python中任何东西都是对象,包括类本身也是对象。type
本质上不是类,而是一个元类。type(1)
输出结果是<class 'int'>
,表明它创建了一个类!
实际上也可以这样写:
1 2 type (Foo, (object ,), {"a" :1 })
使用元类的目的:控制类的产生过程和对象的产生过程。继承type
就可以产生元类。例如可以控制一个类必须要有文档(参考 ):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 class Mymeta (type ): def __init__ (self, class_name, class_bases, class_dic ): if class_dic.get('__doc__' ) is None or \ len (class_dic.get('__doc__' ).strip()) == 0 : raise TypeError('This class must have docstring!' ) if not class_name.istitle(): raise TypeError('First letter in class name should be capitalized!' ) super (Mymeta, self).__init__(class_name, class_bases, class_dic) class People (object , metaclass=Mymeta): country = 'China' def __init__ (self, name, age ): self.name = name self.age = age def eat (self ): print ('%s is eating' % self.name)
判断一个对象最好的办法是isinstance
,因为可以用来处理子类的情况:isinstance(True, int) == True
!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 class SingletonMeta (type ): _instances = {} def __call__ (cls, *args, **kwargs ): if cls not in cls._instances: instance = super ().__call__(*args, **kwargs) cls._instances[cls] = instance return cls._instances[cls] class Database (metaclass=SingletonMeta): def __init__ (self, db_conn: str ) -> None : self.db = DBConn(db_conn) def query (self, sql:str ): session = self.db.create_session() return session.query(sql) if __name__ == "__main__" : db = Database("mysql://database" ) db.query("SELECT ..." ) db = Database("mysql://database" ) db.query("SELECT ..." )
cpp中关于static
的用法说明:
修饰静态成员变量:需要在类外部定义和初始化,因为它们不是在对象被创建时实例化的,而是在程序开始运行时(在进入 main 函数之前)就已经分配好了内存。
修饰静态成员函数:是类的一部分,但它们不依赖于类的特定实例。这意味着它们不能访问类的非静态成员变量或调用非静态成员函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 class Database { private : static Database* pdatabase_; static std::mutex mutex_; protected : Database (const std::string dbconn) : dbconn_ (dbconn) {} ~Database () {} std::string dbconn_; public : Database (Database &other) = delete ; void operator =(const Database &) = delete ; static Database* GetInstance (const std::string& dbconn) ; ReturnType query (std::string sql) { } }; Database* Database::pdatabase_{nullptr }; std::mutex Database::mutex_; Database* Database::GetInstance (const std::string& dbconn) { std::lock_guard<std::mutex> lock (mutex_) ; if (pdatabase_ == nullptr ) pdatabase_ = new Database (dbconn); return pdatabase_; } void ThreadFoo () { std::this_thread::sleep_for (std::chrono::milliseconds (1000 )); Database* db = Database::GetInstance ("sql://cool" ); std::cout << db->query ("SELECT ..." ) << "\n" ; } void ThreadBar () { std::this_thread::sleep_for (std::chrono::milliseconds (1000 )); Database* db = Database::GetInstance ("sql://another_cool" ); std::cout << db->query ("SELECT ..." ) << "\n" ; } int main () { std::thread t1 (ThreadFoo) ; std::thread t2 (ThreadBar) ; t1.join (); t2.join (); return 0 ; }