IT培訓(xùn)網(wǎng)
IT在線學(xué)習(xí)
單例模式是保證一個類僅有一個實例的設(shè)計模式。Windows中的任務(wù)管理器就是一個典型的單例模式軟件。Windows任務(wù)管理器如圖所示。
Windows任務(wù)管理器
Windows任務(wù)管理器只能打開一個,即使用戶重復(fù)打開,也只能獲得一個實例,這不同于Word等軟件可以打開多個實例。這是因為如果有2個窗口同時都能結(jié)束進(jìn)程,那么在窗口A中結(jié)束了某進(jìn)程,而在窗口B中該進(jìn)程還保留著;反之,在窗口B中結(jié)束了某進(jìn)程,而在窗口A中該進(jìn)程還保留著。這樣就會造成沖突,導(dǎo)致系統(tǒng)崩潰。
定義單例類的語法格式如下:
class 類名(object):
def __new__(cls, *args, **kwargs):
if not hasattr(cls, '_instance'):
# 第一種方式
cls._instance = object.__new__(cls)
# 第二種方式
# cls._instance = super(類名, cls).__new__(cls)
return cls._instance
創(chuàng)建的單例類繼承了object類。類中定義了一個魔法方法__new__(),__new__()方法是創(chuàng)建實例時調(diào)用的方法,因此,常說的創(chuàng)建一個實例,其實就是使用這個方法創(chuàng)建的。在__new__()方法中,第一個參數(shù)為cls,說明這是一個類方法,后面兩個參數(shù)分別為*args和**kwargs。用這個方法來創(chuàng)建唯一實例。__new__()方法中,采用if語句判斷當(dāng)前類的實例是否存在,如果不存在,那么需要先創(chuàng)建實例,再返回當(dāng)前類的實例;如果存在,那么直接返回當(dāng)前類的實例�?梢圆捎脙煞N方式來創(chuàng)建實例,第一種方式是父類object調(diào)用魔法方法__new__(),參數(shù)為當(dāng)前類本身;第二種是用super()方法,指定調(diào)用當(dāng)前類父類的__new__()方法。
下面是一個單例類的示例。先編寫一個Singleton類,代碼如下:
- class Singleton(object):
- def __new__(cls, *args, **kwargs):
- if not hasattr(cls, '_instance'):
- cls._instance = object.__new__(cls)
- # cls._instance = super(Singleton, cls).__new__(cls)
- return cls._instance
再創(chuàng)建Singleton類的兩個實例,代碼如下:
- s1 = Singleton()
- s2 = Singleton()
最后通過id()函數(shù)生成兩個實例的內(nèi)存地址,從而判斷Singleton類是不是單例類,代碼如下:
- print('s1的地址:{},s2的地址:{}'.format(id(s1), id(s2)))
運(yùn)行結(jié)果:
- s1的地址:31244920,s2的地址:31244920
由運(yùn)行結(jié)果可知,這兩個實例的內(nèi)存地址一致,說明是同一個實例,即生成的是單一實例,也就是說s1和s2其實是這一個實例的不同名稱而已,因此,Singleton類是單例類。
在上述示例的基礎(chǔ)上,先創(chuàng)建一個Mother類繼承Singleton類,類中包含實例屬性msg表示菜信息,實例方法get_food()用于接收并拼接菜信息msg,實例方法food()用于打印菜信息msg:
- class Mother(Singleton): # 繼承Singleton類
- def __init__(self, msg=''):
- self.msg = msg
- def get_food(self, new_food):
- self.msg += new_food
- def food(self):
- print('做菜:', self.msg)
再創(chuàng)建Mother類的兩個實例,并分別調(diào)用get_food()方法將菜信息作為參數(shù)進(jìn)行傳遞,代碼如下:
- mother1 = Mother()
- mother2 = Mother()
- mother1.get_food('西紅柿')
- mother2.get_food('雞蛋')
最后分別打印這兩個實例的內(nèi)存地址,并調(diào)用food()方法打印菜信息,代碼如下:
- print('兒子的媽媽id:', id(mother1))
- mother1.food()
- print('女兒的媽媽id:', id(mother2))
- mother2.food()
運(yùn)行結(jié)果:
- 兒子的媽媽id: 5758896
- 做菜: 西紅柿雞蛋
- 女兒的媽媽id: 5758896
- 做菜: 西紅柿雞蛋
由于Monther類繼承了Singleton類,因此,實例mother1和mother2指向的是同一個內(nèi)存地址,兩次調(diào)用get_food()方法,參數(shù)中的字符串會拼接在一起,在調(diào)用food()方法時,打印結(jié)果都是拼接后的“西紅柿雞蛋”。
如果在創(chuàng)建Mother類時不繼承Singleton類,那么運(yùn)行結(jié)果是否發(fā)生改變呢?只修改定義Mother類的第一行代碼,其余代碼不變,修改的代碼如下:
- class Mother():
運(yùn)行結(jié)果:
- 兒子的媽媽id: 169246848
- 做菜: 西紅柿
- 女兒的媽媽id: 169246904
- 做菜: 雞蛋
由兩次的運(yùn)行結(jié)果可知,修改之前打印的兩個內(nèi)存地址是相同的,而修改之后打印的兩個內(nèi)存地址不相同,說明修改之后創(chuàng)建Monther類的兩個實例是不同的實例,因此,這兩個實例分別調(diào)用get_food()方法時,字符串不會進(jìn)行拼接,調(diào)用food()方法時打印結(jié)果也不相同。
綜上所述,單例模式只有唯一實例,解決資源共享問題,節(jié)約系統(tǒng)內(nèi)存,提高系統(tǒng)運(yùn)行效率。
>>本文地址:http://uj2y2uok.com/zhuanye/2021/68021.html
聲明:本站稿件版權(quán)均屬中公教育優(yōu)就業(yè)所有,未經(jīng)許可不得擅自轉(zhuǎn)載。
1 您的年齡
2 您的學(xué)歷
3 您更想做哪個方向的工作?