1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

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

        共 5864字,需瀏覽 12分鐘

         ·

        2020-08-10 16:53


        點(diǎn)擊上方“AirPython”,選擇“加為星標(biāo)

        第一時(shí)間關(guān)注 Python 技術(shù)干貨!


        1. 前言

        在很多人的印象里,Python 作為一款動態(tài)編程語言,在日常開發(fā)中也很少涉及到設(shè)計(jì)模式

        事實(shí)上,任何一個(gè)編程語言都可以使用設(shè)計(jì)模式,它可以保證代碼的規(guī)范性,只是每一種語言的實(shí)現(xiàn)方式略有不同而已

        今天我們聊聊 Python 面試中,常被問到的 5 種設(shè)計(jì)模式,它們是:單例模式、工廠模式、構(gòu)建者模式、代理模式、觀察者模式

        2. 單例模式

        單例模式,是最簡單常用的設(shè)計(jì)模式,主要目的是保證某一個(gè)實(shí)例對象只會存在一個(gè),減少資源的消耗

        Python 單例模式有很多實(shí)現(xiàn)方式,這里推薦下面 2 種

        第 1 種,重寫?__new__ 方法

        定義一個(gè)實(shí)例變量,在?__new__ 方法中保證這個(gè)變量僅僅初始化一次

        #?單例模式
        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è)單例裝飾器,將類的定義隱藏到閉包函數(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

        使用上面裝飾器的類,構(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)建的單例并不適用于多線程

        要保證多線程中構(gòu)建的實(shí)例對象為單例,需要在?__new__ 函數(shù)中使用?threading.Lock()?加入同步鎖

        class?Singleton(object):
        ????"""
        ????實(shí)例化一個(gè)對象
        ????"""


        ?????#?鎖
        ????_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í)候,在線程任務(wù)中實(shí)例化對象,運(yùn)行線程即可

        def?task(arg):
        ????"""
        ????任務(wù)
        ????:param?arg:
        ????:return:
        ????"""

        ????instance?=?Singleton()
        ????print(id(instance),?'\n')

        if?__name__?==?'__main__':
        ????#?3個(gè)線程
        ????for?i?in?range(3):
        ????????t?=?threading.Thread(target=task,?args=[i,?])
        ????????t.start()

        這樣,就保證了多線程創(chuàng)建的實(shí)例是單例存在的,不會導(dǎo)致臟數(shù)據(jù)!

        3. 工廠模式

        生產(chǎn)3種水果對象為例,定義 3 類水果,分別是:蘋果、香蕉、橘
        #?定義一系列水果
        class?Apple(object):
        ????"""蘋果"""

        ????def?__repr__(self):
        ????????return?"蘋果"


        class?Banana(object):
        ????"""香蕉"""

        ????def?__repr__(self):
        ????????return?"香蕉"


        class?Orange(object):
        ????"""橘子"""

        ????def?__repr__(self):
        ????????return?"橘子"
        工廠模式包含:簡單工廠、工廠方法、抽象工廠
        第 1 種,簡單工廠
        簡單工廠是最常見的工廠模式,適用于簡單的業(yè)務(wù)場景
        首先,定義一個(gè)工廠類,創(chuàng)建一個(gè)靜態(tài)方法,根據(jù)輸入的類型,返回不同的對象
        class?FactorySimple(object):
        ????"""簡單工廠模式"""

        ????@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?'沒有這種水果'
        使用方式如下:
        if?__name__?==?'__main__':
        ????#?分別獲取3種水果
        ????#?輸入?yún)?shù),通過簡單工廠,返回對應(yīng)的實(shí)例
        ????instance_apple?=?FactorySimple.get_fruit('a')
        ????instance_banana?=?FactorySimple.get_fruit('b')
        ????instance_orange?=?FactorySimple.get_fruit('o')
        第 2 種,工廠方法
        工廠方法將創(chuàng)建對象的工作讓相應(yīng)的工廠子類去實(shí)現(xiàn),保證在新增工廠類時(shí),不用修改原有代碼
        首先,創(chuàng)建一個(gè)抽象公共工廠類,并定義一個(gè)生產(chǎn)對象的方法
        import?abc
        from?factory.fruit?import?*

        class?AbstractFactory(object):
        ????"""抽象工廠"""
        ????__metaclass__?=?abc.ABCMeta

        [email protected]
        ????def?get_fruit(self):
        ????????pass
        接著,創(chuàng)建抽象工廠類的 3 個(gè)子類,并重寫方法,創(chuàng)建一個(gè)實(shí)例對象并返回
        class?AppleFactory(AbstractFactory):
        ????"""生產(chǎn)蘋果"""

        ????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è)工廠負(fù)責(zé)生產(chǎn)自己的產(chǎn)品也避免了我們在新增產(chǎn)品時(shí)需要修改工廠的代碼,而只要增加相應(yī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)
        第 3 種,抽象工廠
        如果一個(gè)工廠要生產(chǎn)多個(gè)產(chǎn)品,使用工廠方法的話,就需要編寫很多工廠類,不太實(shí)用,使用抽象工廠就可以很好的解決這個(gè)問題
        以川菜館和湘菜館炒兩個(gè)菜,毛血旺和小炒肉為例
        首先,創(chuàng)建川菜毛血旺、川菜小炒肉、湘菜毛血旺、湘菜小炒肉?4 個(gè)類
        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?"湘菜-小炒肉"
        然后,定義一個(gè)抽象工廠類,內(nèi)部定義兩個(gè)方法,可以生成毛血旺和小炒肉
        class?AbstractFactory(object):
        ????"""
        ????抽象工廠
        ????既可以生產(chǎn)毛血旺,也可以生成小炒肉
        ????"""

        ????__metaclass__?=?abc.ABCMeta

        [email protected]
        ????def?product_maoxw(self):
        ????????pass

        [email protected]
        ????def?product_xiaocr(self):
        ????????pass
        接著,創(chuàng)建抽象工廠類的兩個(gè)子類,川菜工廠和湘菜工廠,重寫方法,然后創(chuàng)建對應(yīng)的實(shí)例對象返回
        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()
        最后,使用川菜工廠和湘菜工廠分別炒兩個(gè)菜
        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. 最后

        單例模式和工廠模式是日常使用最為頻繁的兩種設(shè)計(jì)模式,下篇文章將聊聊后面 3 種設(shè)計(jì)模式

        我已經(jīng)將文中全部源碼上傳到后臺,關(guān)注公眾號后回復(fù)「?設(shè)計(jì)模式?」即可獲得全部源碼

        如果你覺得文章還不錯,請大家?點(diǎn)贊、分享、留言下,因?yàn)檫@將是我持續(xù)輸出更多優(yōu)質(zhì)文章的最強(qiáng)動力!



        留言送書

        本周贈書:《機(jī)器學(xué)習(xí)算法框架實(shí)戰(zhàn)-Java和Python實(shí)現(xiàn)
        PS:中獎名單將于下周一在交流群/朋友圈同步公布
        機(jī)器學(xué)習(xí)算法與框架實(shí)戰(zhàn),以一個(gè)自研機(jī)器學(xué)習(xí)算法框架的構(gòu)建為主線,首先介紹了機(jī)器學(xué)習(xí)的相關(guān)概念和背景,然后按照代數(shù)矩陣運(yùn)算層、*優(yōu)化方法層、算法模型層和業(yè)務(wù)功能層的分層順序?qū)λ惴蚣苷归_講述
        旨在通過理論和實(shí)踐相結(jié)合的方式,幫助廣大零算法基礎(chǔ)的開發(fā)人員了解和掌握一定的算法能力,同時(shí)作為算法設(shè)計(jì)人員在工程實(shí)現(xiàn)上的參考范例


        推薦閱讀


        聊聊 Python 代碼覆蓋率工具 - Coverage

        自動化篇 | 這些自動化場景,批處理腳本完全可以取代 Python!

        行為驅(qū)動開發(fā):一篇文章帶你用 Python 玩轉(zhuǎn) BDD



        瀏覽 62
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評論
        圖片
        表情
        推薦
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            亚洲天堂电影网 | 国产精品色哟哟 | 香蕉av福利 | 我与俩邻居少妇的性事 | 美女网站免费 | 中国老熟女~x88AV | 三级片网站日本 | 久久爽中文字 | 黑人大鸡巴操逼 | 无码人妻 一区二区三区 |