聊聊 Python 面試最常被問(wèn)到的幾種設(shè)計(jì)模式(上)

1. 前言
在很多人的印象里,Python 作為一款動(dòng)態(tài)編程語(yǔ)言,在日常開(kāi)發(fā)中也很少涉及到設(shè)計(jì)模式
事實(shí)上,任何一個(gè)編程語(yǔ)言都可以使用設(shè)計(jì)模式,它可以保證代碼的規(guī)范性,只是每一種語(yǔ)言的實(shí)現(xiàn)方式略有不同而已
今天我們聊聊 Python 面試中,常被問(wèn)到的 5 種設(shè)計(jì)模式,它們是:單例模式、工廠(chǎng)模式、構(gòu)建者模式、代理模式、觀察者模式
2. 單例模式
單例模式,是最簡(jiǎn)單常用的設(shè)計(jì)模式,主要目的是保證某一個(gè)實(shí)例對(duì)象只會(huì)存在一個(gè),減少資源的消耗
Python 單例模式有很多實(shí)現(xiàn)方式,這里推薦下面 2 種
第 1 種,重寫(xiě)?__new__ 方法
定義一個(gè)實(shí)例變量,在?__new__ 方法中保證這個(gè)變量?jī)H僅初始化一次
#?單例模式
class?Singleton(object):
????_instance?=?None
????def?__new__(cls,?*args,?**kwargs):
????????if?cls._instance?is?None:
????????????cls._instance?=?object.__new__(cls,?*args,?**kwargs)
????????return?cls._instance使用方式如下:
if?__name__?==?'__main__':
????#?構(gòu)建3個(gè)實(shí)例
????instance1?=?Singleton()
????instance2?=?Singleton()
????instance3?=?Singleton()
????#?打印出實(shí)例的內(nèi)存地址,判斷是否是同一個(gè)實(shí)例
????print(id(instance1))
????print(id(instance2))
????print(id(instance3))第 2 種,閉包定義裝飾器
使用閉包的方式定義一個(gè)單例裝飾器,將類(lèi)的定義隱藏到閉包函數(shù)中
def?singleton(cls):
????"""
????定義單例的裝飾器(閉包)
????:param?cls:
????:return:
????"""
????_instance?=?{}
????def?_singleton(*args,?**kargs):
????????if?cls?not?in?_instance:
????????????_instance[cls]?=?cls(*args,?**kargs)
????????return?_instance[cls]
????return?_singleton
使用上面裝飾器的類(lèi),構(gòu)建的實(shí)例都能保證單例存在
@singleton
class?Singleton(object):
????"""單例實(shí)例"""
????def?__init__(self,?arg1):
????????self.arg1?=?arg1
使用方式如下:
if?__name__?==?'__main__':
????instance1?=?Singleton("xag")
????instance2?=?Singleton("xingag")
????print(id(instance1))
????print(id(instance2))需要注意的是,上面 2 種方式創(chuàng)建的單例并不適用于多線(xiàn)程
要保證多線(xiàn)程中構(gòu)建的實(shí)例對(duì)象為單例,需要在?__new__ 函數(shù)中使用?threading.Lock()?加入同步鎖
class?Singleton(object):
????"""
????實(shí)例化一個(gè)對(duì)象
????"""
?????#?鎖
????_instance_lock?=?threading.Lock()
????def?__init__(self):
????????pass
????def?__new__(cls,?*args,?**kwargs):
????????if?not?hasattr(Singleton,?"_instance"):
????????????with?Singleton._instance_lock:
????????????????if?not?hasattr(Singleton,?"_instance"):
????????????????????Singleton._instance?=?object.__new__(cls)
????????return?Singleton._instance使用的時(shí)候,在線(xiàn)程任務(wù)中實(shí)例化對(duì)象,運(yùn)行線(xiàn)程即可
def?task(arg):
????"""
????任務(wù)
????:param?arg:
????:return:
????"""
????instance?=?Singleton()
????print(id(instance),?'\n')
if?__name__?==?'__main__':
????#?3個(gè)線(xiàn)程
????for?i?in?range(3):
????????t?=?threading.Thread(target=task,?args=[i,?])
????????t.start()這樣,就保證了多線(xiàn)程創(chuàng)建的實(shí)例是單例存在的,不會(huì)導(dǎo)致臟數(shù)據(jù)!
3. 工廠(chǎng)模式
#?定義一系列水果
class?Apple(object):
????"""蘋(píng)果"""
????def?__repr__(self):
????????return?"蘋(píng)果"
class?Banana(object):
????"""香蕉"""
????def?__repr__(self):
????????return?"香蕉"
class?Orange(object):
????"""橘子"""
????def?__repr__(self):
????????return?"橘子"class?FactorySimple(object):
????"""簡(jiǎn)單工廠(chǎng)模式"""
????@staticmethod
????def?get_fruit(fruit_name):
????????if?'a'?==?fruit_name:
????????????return?Apple()
????????elif?'b'?==?fruit_name:
????????????return?Banana()
????????elif?'o'?==?fruit_name:
????????????return?Orange()
????????else:
????????????return?'沒(méi)有這種水果'if?__name__?==?'__main__':
????#?分別獲取3種水果
????#?輸入?yún)?shù),通過(guò)簡(jiǎn)單工廠(chǎng),返回對(duì)應(yīng)的實(shí)例
????instance_apple?=?FactorySimple.get_fruit('a')
????instance_banana?=?FactorySimple.get_fruit('b')
????instance_orange?=?FactorySimple.get_fruit('o')import?abc
from?factory.fruit?import?*
class?AbstractFactory(object):
????"""抽象工廠(chǎng)"""
????__metaclass__?=?abc.ABCMeta
[email protected]
????def?get_fruit(self):
????????passclass?AppleFactory(AbstractFactory):
????"""生產(chǎn)蘋(píng)果"""
????def?get_fruit(self):
????????return?Apple()
class?BananaFactory(AbstractFactory):
????"""生產(chǎn)香蕉"""
????def?get_fruit(self):
????????return?Banana()
class?OrangeFactory(AbstractFactory):
????"""生產(chǎn)橘子"""
????def?get_fruit(self):
????????return?Orange()if?__name__?==?'__main__':
????#?每個(gè)工廠(chǎng)負(fù)責(zé)生產(chǎn)自己的產(chǎn)品也避免了我們?cè)谛略霎a(chǎn)品時(shí)需要修改工廠(chǎng)的代碼,而只要增加相應(yīng)的工廠(chǎng)即可
????instance_apple?=?AppleFactory().get_fruit()
????instance_banana?=?BananaFactory().get_fruit()
????instance_orange?=?OrangeFactory().get_fruit()
????print(instance_apple)
????print(instance_banana)
????print(instance_orange)
class?MaoXW_CC(object):
????"""川菜-毛血旺"""
????def?__str__(self):
????????return?"川菜-毛血旺"
class?XiaoCR_CC(object):
????"""川菜-小炒肉"""
????def?__str__(self):
????????return?"川菜-小炒肉"
class?MaoXW_XC(object):
????"""湘菜-毛血旺"""
????def?__str__(self):
????????return?"湘菜-毛血旺"
class?XiaoCR_XC(object):
????"""湘菜-小炒肉"""
????def?__str__(self):
????????return?"湘菜-小炒肉"class?AbstractFactory(object):
????"""
????抽象工廠(chǎng)
????既可以生產(chǎn)毛血旺,也可以生成小炒肉
????"""
????__metaclass__?=?abc.ABCMeta
[email protected]
????def?product_maoxw(self):
????????pass
[email protected]
????def?product_xiaocr(self):
????????pass
class?CCFactory(AbstractFactory):
????"""川菜館"""
????def?product_maoxw(self):
????????return?MaoXW_CC()
????def?product_xiaocr(self):
????????return?XiaoCR_CC()
class?XCFactory(AbstractFactory):
????"""湘菜館"""
????def?product_maoxw(self):
????????return?MaoXW_XC()
????def?product_xiaocr(self):
????????return?XiaoCR_XC()
if?__name__?==?'__main__':
????#?川菜炒兩個(gè)菜,分別是:毛血旺和小炒肉
????maoxw_cc?=?CCFactory().product_maoxw()
????xiaocr_cc?=?CCFactory().product_xiaocr()
????print(maoxw_cc,?xiaocr_cc)
????maoxw_xc?=?XCFactory().product_maoxw()
????xiaocr_xc?=?XCFactory().product_xiaocr()
????print(maoxw_xc,?xiaocr_xc)4. 最后
單例模式和工廠(chǎng)模式是日常使用最為頻繁的兩種設(shè)計(jì)模式,下篇文章將聊聊后面 3 種設(shè)計(jì)模式,希望大家在留言區(qū)捧個(gè)場(chǎng)支持一下,月底統(tǒng)計(jì)常來(lái)留言的同學(xué)送書(shū),給個(gè)三連哈!你的支持,就是我原創(chuàng)的最佳動(dòng)力!
星球的價(jià)格是一年88元,然后現(xiàn)在雙11期間有優(yōu)惠券20元,相當(dāng)于是68一年,算下來(lái)每個(gè)月6塊錢(qián),連半杯奶茶的錢(qián)都不到,一天才2毛錢(qián),非常劃算。
推薦閱讀:
入門(mén):?最全的零基礎(chǔ)學(xué)Python的問(wèn)題? |?零基礎(chǔ)學(xué)了8個(gè)月的Python??|?實(shí)戰(zhàn)項(xiàng)目?|學(xué)Python就是這條捷徑
干貨:爬取豆瓣短評(píng),電影《后來(lái)的我們》?|?38年NBA最佳球員分析?|? ?從萬(wàn)眾期待到口碑撲街!唐探3令人失望? |?笑看新倚天屠龍記?|?燈謎答題王?|用Python做個(gè)海量小姐姐素描圖?|碟中諜這么火,我用機(jī)器學(xué)習(xí)做個(gè)迷你推薦系統(tǒng)電影
趣味:彈球游戲? |?九宮格? |?漂亮的花?|?兩百行Python《天天酷跑》游戲!
AI:?會(huì)做詩(shī)的機(jī)器人?|?給圖片上色?|?預(yù)測(cè)收入?|?碟中諜這么火,我用機(jī)器學(xué)習(xí)做個(gè)迷你推薦系統(tǒng)電影
小工具:?Pdf轉(zhuǎn)Word,輕松搞定表格和水印!?|?一鍵把html網(wǎng)頁(yè)保存為pdf!|??再見(jiàn)PDF提取收費(fèi)!?|?用90行代碼打造最強(qiáng)PDF轉(zhuǎn)換器,word、PPT、excel、markdown、html一鍵轉(zhuǎn)換?|?制作一款釘釘?shù)蛢r(jià)機(jī)票提示器!?|60行代碼做了一個(gè)語(yǔ)音壁紙切換器天天看小姐姐!|
年度爆款文案

