成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

使用python解釋設(shè)計(jì)模式[譯]

MadPecker / 2286人閱讀

摘要:最重要的是,任何設(shè)計(jì)模式都是一把雙刃劍。另一個(gè)設(shè)計(jì)模式是迭代器,在語(yǔ)言中以循環(huán)的形式實(shí)現(xiàn)。我們可以換個(gè)方法,利用策略模式和適配器模式的變種,能夠完美處理這種情景。何時(shí)使用它單例模式也許是最簡(jiǎn)單的設(shè)計(jì)模式了。

使用python解釋設(shè)計(jì)模式

原文地址
有沒(méi)有好奇過(guò)設(shè)計(jì)模式是什么呢?在這篇文章中,我們將了解為什么設(shè)計(jì)模式是重要的,同時(shí)也會(huì)給出一些python的例子,解釋為什么以及在什么時(shí)候使用設(shè)計(jì)模式。

什么是設(shè)計(jì)模式?

設(shè)計(jì)模式是我們?nèi)粘S龅降木幊虇?wèn)題時(shí)的優(yōu)化過(guò)的可重用的解決方案。一個(gè)設(shè)計(jì)模式不是可以直接嵌入到我們系統(tǒng)中的一個(gè)庫(kù)或者一個(gè)類;它的含義要比這廣泛的多。它是一個(gè)必須在特地場(chǎng)景實(shí)現(xiàn)的模板。同時(shí)設(shè)計(jì)模式也不是針對(duì)特地語(yǔ)言的。一個(gè)好的設(shè)計(jì)模式應(yīng)該可以在幾乎所有-如果不是全部的話-的語(yǔ)言實(shí)現(xiàn),這取決于語(yǔ)言的能力。最重要的是,任何設(shè)計(jì)模式都是一把雙刃劍。如果在錯(cuò)誤的場(chǎng)景使用,它將會(huì)給你帶來(lái)很多麻煩。然而,在合適的場(chǎng)景使用,它將成為你的救世主。

起初,你可以把設(shè)計(jì)模式看做解決特定一類問(wèn)題的非常深刻巧妙的方式。就像是一群人考慮了一個(gè)問(wèn)題的各方面然后想出一個(gè)最通用,靈活的解決方案。這個(gè)問(wèn)題可能是你之前看見(jiàn)過(guò)的解決過(guò)的,但是你的解決方案可能不具備設(shè)計(jì)模式中的完備性。

盡管他們把這叫做“設(shè)計(jì)模式”,但這和設(shè)計(jì)領(lǐng)域并沒(méi)有什么關(guān)系。一種模式和傳統(tǒng)意義上關(guān)于分析,設(shè)計(jì)和實(shí)現(xiàn)的思想相差甚遠(yuǎn),一種模式更多地是象征程序中體現(xiàn)的一個(gè)完整的想法,因此有時(shí)候設(shè)計(jì)模式會(huì)出現(xiàn)在分析階段或者更高層的設(shè)計(jì)階段。這是挺有趣的一件事因?yàn)橐粋€(gè)模式在代碼層面有一個(gè)直接的實(shí)現(xiàn)所以在底層設(shè)計(jì)或?qū)崿F(xiàn)之前你可能看不見(jiàn)它的身影。(事實(shí)上你可能在這些階段之前都不會(huì)意識(shí)到自己需要一個(gè)特定的設(shè)計(jì)模式)

模式的基本概念也可以被當(dāng)作是程序設(shè)計(jì)的基本概念:添加一個(gè)抽象層。當(dāng)你在抽象某個(gè)事物的時(shí)候,你也在將特定的細(xì)節(jié)獨(dú)立出來(lái),這當(dāng)中最強(qiáng)烈的動(dòng)機(jī)便是把變化的與不變的分開(kāi)。換個(gè)說(shuō)法就是一旦你在程序中找到了由于種種原因可能變動(dòng)的部分,你會(huì)想要防止它們?cè)诖a中產(chǎn)生其他的變動(dòng)。這不僅使得代碼更加容易維護(hù),并且更加易讀。

通常,開(kāi)發(fā)一個(gè)優(yōu)雅而易維護(hù)的架構(gòu)最困難的部分在于探究“變化的矢量(vector)”(在這里vector指最大的梯度而不是容器類)。意思就是找到在你的系統(tǒng)中發(fā)生變化的最重要的東西。換句話說(shuō)找到你最巨大的開(kāi)銷。一旦你找到了改變的vector,你便有了一個(gè)架構(gòu)設(shè)計(jì)的重點(diǎn)。

所以設(shè)計(jì)模式的目的是隔離你代碼中的改變。如果以這個(gè)角度來(lái)看的話,你已經(jīng)看過(guò)一些設(shè)計(jì)模式了。比如說(shuō),繼承可以被看做是一種設(shè)計(jì)模式(盡管它是被編譯器實(shí)現(xiàn)的)它讓你可以表達(dá)有同樣接口的對(duì)象在行為上的差異。組合也可以被看做是一個(gè)設(shè)計(jì)模式,因?yàn)樗屇沆o態(tài)或動(dòng)態(tài)地改變類的對(duì)象以及類工作的方式。

另一個(gè)設(shè)計(jì)模式是迭代器,在語(yǔ)言中以for 循環(huán)的形式實(shí)現(xiàn)。迭代器允許你隱藏容器實(shí)現(xiàn)的細(xì)節(jié),就像你在一步一步遍歷元素。于是你可以寫(xiě)出在一個(gè)序列上處理所有元素的通用代碼而不需要考慮序列建立的方式,因此你的通用代碼可以被任何生成出迭代器的對(duì)象使用。

有三種基本的設(shè)計(jì)模式:

結(jié)構(gòu)化模式通常處理實(shí)體之間的關(guān)系,使他們之間的合作溝通更加簡(jiǎn)單。

創(chuàng)造性模式提供實(shí)例化的機(jī)制,使得在特殊場(chǎng)景下創(chuàng)建對(duì)象變得更加方便。

行為模式通常被用在實(shí)體之間的通信,使得他們之間的通信更加簡(jiǎn)單和靈活。

為什么我們需要設(shè)計(jì)模式

設(shè)計(jì)模式在原則上是程序設(shè)計(jì)中經(jīng)過(guò)深思熟慮的解決方案。許多程序員在之前遇到過(guò)類似的問(wèn)題,然后用這些方案來(lái)解決它們。如果你碰上了類似的問(wèn)題,為什么二次創(chuàng)造一個(gè)已經(jīng)有給定答案的方案呢?

例子

讓我們想象一下你需要一個(gè)方法來(lái)合并兩個(gè)不同的類。而這兩個(gè)類在現(xiàn)有的系統(tǒng)的不同地方中已經(jīng)被使用很多了,這使得改變已有代碼非常困難。如果要合并的話,改變已有代碼也需要測(cè)試所有改變過(guò)的代碼,由于系統(tǒng)依賴不同的組件,很大可能會(huì)形成新的bug。我們可以換個(gè)方法,利用策略模式(strategy pattern)和適配器模式(adapter pattern)的變種,能夠完美處理這種情景。

class StrategyAndAdapterExampleClass():
 
    def __init__(self, context, class_one, class_two):
        self.context = context
        self.class_one = class_one
        self.class_two = class_two
 
    def operation1(self):
        if self.context == "Context_For_Class_One":
            self.class_one.operation1_in_class_one_context()
        else:
            self.class_two.operational_in_class_two_context()

非常簡(jiǎn)單不是嗎?現(xiàn)在,讓我們仔細(xì)地看看策略模式。

策略模式(Strategy Pattern)

策略模式是一種讓你在運(yùn)行時(shí)決定程序具體行為的行為模式。你可以將兩個(gè)類中不同的算法封裝起來(lái),然后在運(yùn)行時(shí)(runtime)決定你想采取哪個(gè)策略。

在我們上面的例子里,策略的選擇是基于context變量在實(shí)例化類的時(shí)候被賦予的值。如果context變量被賦值為class_one,它將使用class_one,反之亦然。

在哪可以使用

想象一下你正在開(kāi)發(fā)一個(gè)創(chuàng)建或者更新用戶紀(jì)錄的類。它需要相同的輸入(姓名,地址,手機(jī),等)但是取決于給定的情況,它在更新和創(chuàng)建時(shí)會(huì)調(diào)用不同的函數(shù)。你當(dāng)然可以使用if else語(yǔ)句來(lái)實(shí)現(xiàn),但這樣的話你就必須寫(xiě)很多個(gè)if else語(yǔ)句。直接說(shuō)明你的上下文不是方便多了?

class User():
    def create_or_update(self, name, address, mobile, userid=None):
        if userid:
            # it means the user doesn"t exist yet, create a new record
        else:
            # it means the user already exists, just update based on the given userid

通常情況下的策略模式會(huì)將你的代碼封裝到另外一個(gè)類中,但在該例中,使用另外的類會(huì)很浪費(fèi)。記住你不需要完全按照模板來(lái)操作。只要符合原則,能解決問(wèn)題即可。

適配器模式(Adapter Pattern)

適配器模式是一個(gè)結(jié)構(gòu)化的設(shè)計(jì)模式,它讓你使用一個(gè)不同的接口來(lái)重用一個(gè)類,使它能在一個(gè)調(diào)用不同方法的系統(tǒng)中使用。

該模式也允許你更改從client class接受的輸入,使其與被適配對(duì)象的函數(shù)兼容。

如何使用?

適配器類的另一個(gè)名稱叫做封裝類,它讓你將一系列操作封裝在一個(gè)類里然后在合適的場(chǎng)合重用這些操作。
比較下面兩種實(shí)現(xiàn)。

非適配器方案
class User(object):
    def create_or_update(self):
        pass
 
class Profile(object):
    def create_or_update(self):
        pass
 
user = User()
user.create_or_update()
 
profile = Profile()
profile.create_or_update()

如果我們需要在不同的地方重新做一次,或者在另一個(gè)項(xiàng)目中重用這份代碼,我們需要從頭開(kāi)始再寫(xiě)一遍。

更好的選擇
account_domain = Account()
account_domain.NewAccount()

在此處,我們有一個(gè)封裝類,為Account:

class User(object):
    def create_or_update(self):
        pass
 
class Profile(object):
    def create_or_update(self):
        pass
 
class Account():
    def new_account(self):
        user = User()
        user.create_or_update()
 
        profile = Profile()
        profile.create_or_update()

按這種方式,在需要的時(shí)候可以重用你的Account,當(dāng)然你也可以在你的主類下包裝其他的類。

工廠模式

工廠模式是一種創(chuàng)造型設(shè)計(jì)模式,正如其名,它像工廠一樣生產(chǎn)出對(duì)象實(shí)例。

該模式的主要目的是將可能擴(kuò)展到不同類中的創(chuàng)建過(guò)程封裝進(jìn)單個(gè)函數(shù)。通過(guò)提供合適的上下文,它會(huì)返回合適的對(duì)象。

何時(shí)使用它?

使用工廠模式的最佳時(shí)機(jī)是你的單個(gè)實(shí)體有多個(gè)變種時(shí)。假設(shè)你有一個(gè)按鈕類,該類有不同的變化,比如圖像按鈕,輸入按鈕,flash按鈕。你可以會(huì)根據(jù)不同場(chǎng)景創(chuàng)建不同的按鈕,此時(shí)便可以使用工廠來(lái)為你創(chuàng)造按鈕。
首先我們先創(chuàng)造三個(gè)類:

class Button(object):
    html = ""
    def get_html(self):
        return self.html
 
class Image(Button):
    html = ""
 
class Input(Button):
    html = ""
 
class Flash(Button):
    html = ""

接下來(lái)我們可以創(chuàng)建工廠類:

class ButtonFactory():
    def create_button(self, typ):
        targetclass = typ.capitalize()
        return globals()[targetclass]()

我們可以這樣使用它:

button_obj = ButtonFactory()
    button = ["image", "input", "flash"]
    for b in button:
            print button_obj.create_button(b).get_html()

輸出即為所有按鈕類型的html。按此法,你可以在不同場(chǎng)景創(chuàng)建不同的按鈕并且可以重用代碼。

裝飾器模式

裝飾器模式是一種結(jié)構(gòu)型模式。它能夠讓我們?cè)谶\(yùn)行時(shí)根據(jù)情景為對(duì)象添加額外的行為。

該模式的目的是在特定情景下對(duì)實(shí)例進(jìn)行額外的操作同時(shí)也可以創(chuàng)建原有的實(shí)例。該模式允許對(duì)一個(gè)實(shí)例添加多個(gè)裝飾器。該模式可以用來(lái)替換子類,創(chuàng)建一個(gè)類繼承父類的功能。和在編譯時(shí)添加行為的子類不同,裝飾器允許你在運(yùn)行時(shí)添加新的行為。

為了實(shí)現(xiàn)裝飾器模式,我們可以按照下面的步驟。

將原來(lái)的組件類封裝進(jìn)裝飾器類作為子類。

在裝飾器類中,添加一個(gè)字段作為組件的指針。

傳遞一個(gè)組件給裝飾器的構(gòu)造函數(shù)來(lái)初始化指針。

在裝飾器類中,將所有的組件方法重定向到指針,并且

在裝飾器類中,覆蓋所有需要修改的 組件方法,

何時(shí)使用它?

使用裝飾器模式的最好場(chǎng)景是當(dāng)你在特定時(shí)期
需要給某個(gè)實(shí)體特殊的行為時(shí)。假設(shè)你有一個(gè)HTML鏈接元素,一個(gè)登出鏈接,你希望基于當(dāng)前頁(yè)面做出輕微的改變。此時(shí)我們可以使用裝飾器模式。

首先我們需要建立不同的“裝飾”。如果我們?cè)谥黜?yè)登陸,該鏈接就需要用h2標(biāo)簽包裹。
如果我們?cè)诓煌捻?yè)面登錄,該鏈接需要用下劃線標(biāo)簽包裹。
如果我們已登錄,那么該鏈接將被包裹成加強(qiáng)標(biāo)簽。一旦我們定義好了“裝飾”,我們就可以開(kāi)始編程了。

class HtmlLinks():
    def set_html(self, html):
        self.html = html
 
    def get_html(self):
        return self.html
 
    def render(self):
        print(self.html)
 
class LogoutLink(HtmlLinks):
    def __init__(self):
        self.html = " Logout "
 
class LogoutLinkH2Decorator(HtmlLinks):
    def __init__(self, logout_link):
        self.logout_link = logout_link
        self.set_html(" {0} ".format(self.logout_link.get_html()))
 
    def call(self, name, args):
        self.logout_link.name(args[0])
 
class LogoutLinkUnderlineDecorator(HtmlLinks):
    def __init__(self, logout_link):
        self.logout_link = logout_link
        self.set_html(" {0} ".format(self.logout_link.get_html()))
 
    def call(self, name, args):
        self.logout_link.name(args[0])
 
class LogoutLinkStrongDecorator(HtmlLinks):
    def __init__(self, logout_link):
        self.logout_link = logout_link
        self.set_html(" {0} ".format(self.logout_link.get_html()))
 
    def call(self, name, args):
        self.logout_link.name(args[0])
 
logout_link = LogoutLink()
is_logged_in = 0
in_home_page = 0
 
if is_logged_in:
    logout_link = LogoutLinkStrongDecorator(logout_link)
if in_home_page:
    logout_link = LogoutLinkH2Decorator(logout_link)
else:
    logout_link = LogoutLinkUnderlineDecorator(logout_link)
 
logout_link.render()
單例模式

單例模式是一種創(chuàng)造型模式,它保證你在runtime時(shí)只有一個(gè)特定的實(shí)例,提供一個(gè)全局的指針。

這為其他人調(diào)用該實(shí)例變得更加簡(jiǎn)單,由于該變量總會(huì)返回同樣的東西。

何時(shí)使用它?

單例模式也許是最簡(jiǎn)單的設(shè)計(jì)模式了。它給某個(gè)特殊的類型提供了獨(dú)一無(wú)二的實(shí)例。為了達(dá)成這點(diǎn) ,你必須操縱該類型的創(chuàng)建過(guò)程。一種簡(jiǎn)便的方法是將單例委托給一個(gè)內(nèi)部的私有類。

class OnlyOne:
    class __OnlyOne:
        def __init__(self, arg):
            self.val = arg
        def __str__(self):
            return repr(self) + self.val
    instance = None
    def __init__(self, arg):
        if not OnlyOne.instance:
            OnlyOne.instance = OnlyOne.__OnlyOne(arg)
        else:
            OnlyOne.instance.val = arg
    def __getattr__(self, name):
        return getattr(self.instance, name)
 
x = OnlyOne("sausage")
print(x)
y = OnlyOne("eggs")
print(y)
z = OnlyOne("spam")
print(z)
print(x)
print(y)
print(`x`)
print(`y`)
print(`z`)
output = """
<__main__.__OnlyOne instance at 0076B7AC>sausage
<__main__.__OnlyOne instance at 0076B7AC>eggs
<__main__.__OnlyOne instance at 0076B7AC>spam
<__main__.__OnlyOne instance at 0076B7AC>spam
<__main__.__OnlyOne instance at 0076B7AC>spam
<__main__.OnlyOne instance at 0076C54C>
<__main__.OnlyOne instance at 0076DAAC>
<__main__.OnlyOne instance at 0076AA3C>
"""

由于內(nèi)部類的名字以雙下劃線開(kāi)頭,所以用戶是不能直接訪問(wèn)它的。內(nèi)部的類包含了所有你需要的方法,然后將它封裝進(jìn)你創(chuàng)建的單例類。你第一次創(chuàng)建OnlyOne的時(shí)候,它會(huì)對(duì)實(shí)例初始化,在此之后它會(huì)忽略你的創(chuàng)建請(qǐng)求。

訪問(wèn)實(shí)例通過(guò)使用__getattr__()的方法來(lái)重定向你的訪問(wèn)請(qǐng)求。你可以從輸出看出即使看上去創(chuàng)建了很多實(shí)例,但實(shí)際上只創(chuàng)建了一個(gè)__OnlyOne 對(duì)象。OnlyOne的實(shí)例是獨(dú)立的,但是他們都指向同一個(gè)__OnlyOne 對(duì)象。

注意上述方法并不限制你只創(chuàng)建一個(gè)實(shí)例。這也是一種創(chuàng)建限定數(shù)量的對(duì)象池的方法。但在此情景下,你可能會(huì)遇到對(duì)象池分享的問(wèn)題。如果該問(wèn)題出現(xiàn)了,你可以創(chuàng)建相應(yīng)的check in 和 check out 方法。

總結(jié)

由于python的動(dòng)態(tài)語(yǔ)言特性,設(shè)計(jì)模式在python中并不是非常重要的概念,但是在python中展示設(shè)計(jì)模式非常簡(jiǎn)單。記住類和函數(shù)本身是一等公民所以有些設(shè)計(jì)模式可能不是非常實(shí)用。除此之外也有許多其他的設(shè)計(jì)模式。在本文中我只介紹了一些在編程中使用較多的設(shè)計(jì)模式。如果你對(duì)其他設(shè)計(jì)模式感興趣,可以訪問(wèn)相應(yīng)的wiki頁(yè)面。
最后一件事,當(dāng)你使用設(shè)計(jì)模式時(shí),確保你在試圖解決正確的問(wèn)題。我之前也提及過(guò),設(shè)計(jì)模式是把雙刃劍:如果用在了錯(cuò)誤的地方,它將把事情變的更糟。如果用在對(duì)的地方,它將是至關(guān)重要的。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/37623.html

相關(guān)文章

  • 】技能測(cè)試解決方案:Python中的數(shù)據(jù)科學(xué)(四)

    摘要:友情鏈接譯技能測(cè)試解決方案中的數(shù)據(jù)科學(xué)一譯技能測(cè)試解決方案中的數(shù)據(jù)科學(xué)二譯技能測(cè)試解決方案中的數(shù)據(jù)科學(xué)三 本文是譯文,可以轉(zhuǎn)載,但需注明出處,點(diǎn)擊這里可以獲取原文,有刪減。本系列博文包含四篇文章:【譯】技能測(cè)試解決方案:Python中的數(shù)據(jù)科學(xué)(一)——Q1-Q15【譯】技能測(cè)試解決方案:Python中的數(shù)據(jù)科學(xué)(二)——Q16-Q30【譯】技能測(cè)試解決方案:Python中的數(shù)據(jù)科學(xué)(...

    sourcenode 評(píng)論0 收藏0
  • [][Tkinter 教程01] 入門(mén): Label 控件

    摘要:已獲原作者授權(quán)原系列地址下面我們將以中最簡(jiǎn)單的控件控件開(kāi)始這個(gè)系列的教程在中控件用以顯示文字和圖片通常被用來(lái)展示信息而非與用戶交互譯者注也可以綁定點(diǎn)擊等事件只是通常不這么用程序員的教程怎么能少了我們尊重這個(gè)傳統(tǒng)但我們不說(shuō)讓我們來(lái)秀出吧下面的 已獲原作者授權(quán). 原系列地址: Python Tkinter Hello Tkinter Label 下面我們將以 Tkinter 中最簡(jiǎn)單的控...

    Sike 評(píng)論0 收藏0
  • []Python面試中8個(gè)必考問(wèn)題

    摘要:因此,當(dāng)任何由返回的函數(shù)被調(diào)用時(shí),的值將在附近的范圍進(jìn)行查找。下面是解決這一問(wèn)題的一些方法。另外一個(gè)解決方案就是創(chuàng)造一個(gè)閉包,利用默認(rèn)函數(shù)立即綁定。當(dāng)缺失時(shí),執(zhí)行類,字典的實(shí)例將自動(dòng)實(shí)例化這個(gè)數(shù)列。 1、下面這段代碼的輸出結(jié)果是什么?請(qǐng)解釋。 def extendList(val, list=[]): list.append(val) return list list...

    warmcheng 評(píng)論0 收藏0
  • 】技能測(cè)試解決方案:Python中的數(shù)據(jù)科學(xué)(三)

    摘要:在關(guān)聯(lián)該數(shù)據(jù)集時(shí),重復(fù)行會(huì)帶來(lái)一定的困擾,為了避免這個(gè)困擾,我們只保留重復(fù)數(shù)據(jù)第一個(gè)出現(xiàn)的樣本。 本文是譯文,可以轉(zhuǎn)載,但需注明出處,點(diǎn)擊這里可以獲取原文,有刪減。本系列博文包含四篇文章:【譯】技能測(cè)試解決方案:Python中的數(shù)據(jù)科學(xué)(一)——Q1-Q15【譯】技能測(cè)試解決方案:Python中的數(shù)據(jù)科學(xué)(二)——Q16-Q30 【譯】技能測(cè)試解決方案:Python中的數(shù)據(jù)科學(xué)(三)...

    i_garfileo 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<