日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > python >内容正文

python

常见设计模式 (python代码实现)

發(fā)布時間:2023/12/9 python 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 常见设计模式 (python代码实现) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

1.創(chuàng)建型模式

單例模式

單例模式(Singleton Pattern)是一種常用的軟件設(shè)計模式,該模式的主要目的是確保某一個類只有一個實例存在。當(dāng)你希望在整個系統(tǒng)中,某個類只能出現(xiàn)一個實例時,單例對象就能派上用場。

比如,某個服務(wù)器程序的配置信息存放在一個文件中,客戶端通過一個 AppConfig 的類來讀取配置文件的信息。如果在程序運行期間,有很多地方都需要使用配置文件的內(nèi)容,也就是說,很多地方都需要創(chuàng)建 AppConfig 對象的實例,這就導(dǎo)致系統(tǒng)中存在多個 AppConfig 的實例對象,而這樣會嚴(yán)重浪費內(nèi)存資源,尤其是在配置文件內(nèi)容很多的情況下。事實上,類似 AppConfig 這樣的類,我們希望在程序運行期間只存在一個實例對象

1 class Singleton(object):2 def __init__(self):3 pass4 5 def __new__(cls, *args, **kwargs):6 if not hasattr(Singleton, "_instance"): # 反射7 Singleton._instance = object.__new__(cls)8 return Singleton._instance9 10 obj1 = Singleton() 11 obj2 = Singleton() 12 print(obj1, obj2) #<__main__.Singleton object at 0x004415F0> <__main__.Singleton object at 0x004415F0>

?

工廠模式

工廠模式是一個在軟件開發(fā)中用來創(chuàng)建對象的設(shè)計模式。

工廠模式包涵一個超類。這個超類提供一個抽象化的接口來創(chuàng)建一個特定類型的對象,而不是決定哪個對象可以被創(chuàng)建。

為了實現(xiàn)此方法,需要創(chuàng)建一個工廠類創(chuàng)建并返回。?

當(dāng)程序運行輸入一個“類型”的時候,需要創(chuàng)建于此相應(yīng)的對象。這就用到了工廠模式。在如此情形中,實現(xiàn)代碼基于工廠模式,可以達到可擴展,可維護的代碼。當(dāng)增加一個新的類型,不在需要修改已存在的類,只增加能夠產(chǎn)生新類型的子類。

簡短的說,當(dāng)以下情形可以使用工廠模式:

1.不知道用戶想要創(chuàng)建什么樣的對象

2.當(dāng)你想要創(chuàng)建一個可擴展的關(guān)聯(lián)在創(chuàng)建類與支持創(chuàng)建對象的類之間。

一個例子更能很好的理解以上的內(nèi)容:

  • 我們有一個基類Person ,包涵獲取名字,性別的方法 。有兩個子類male 和female,可以打招呼。還有一個工廠類。
  • ?工廠類有一個方法名getPerson有兩個輸入?yún)?shù),名字和性別。
  • ?用戶使用工廠類,通過調(diào)用getPerson方法。
  • 在程序運行期間,用戶傳遞性別給工廠,工廠創(chuàng)建一個與性別有關(guān)的對象。因此工廠類在運行期,決定了哪個對象應(yīng)該被創(chuàng)建

    class Person:def __init__(self):self.name = Noneself.gender = Nonedef getName(self):return self.namedef getGender(self):return self.genderclass Male(Person):def __init__(self, name):print "Hello Mr." + nameclass Female(Person):def __init__(self, name):print "Hello Miss." + nameclass Factory:def getPerson(self, name, gender):if gender == ‘M':return Male(name)if gender == 'F':return Female(name)if __name__ == '__main__':factory = Factory()person = factory.getPerson("Chetan", "M")

    建造者模式

    將一個復(fù)雜對象的構(gòu)建與它的表示分離,使得同樣的構(gòu)建過程可以創(chuàng)建不同的表示。

    相關(guān)模式:思路和模板方法模式很像,模板方法是封裝算法流程,對某些細(xì)節(jié),提供接口由子類修改,建造者模式更為高層一點,將所有細(xì)節(jié)都交由子類實現(xiàn)

    一個例子更能很好的理解以上的內(nèi)容:

    1. 有一個接口類,定義創(chuàng)建對象的方法。一個指揮員類,接受創(chuàng)造者對象為參數(shù)。兩個創(chuàng)造者類,創(chuàng)建對象方法相同,內(nèi)部創(chuàng)建可自定義

    2.一個指揮員,兩個創(chuàng)造者(瘦子 胖子),指揮員可以指定由哪個創(chuàng)造者來創(chuàng)造

    from abc import ABCMeta, abstractmethodclass Builder():__metaclass__ = ABCMeta@abstractmethoddef draw_left_arm(self):pass@abstractmethoddef draw_right_arm(self):pass@abstractmethoddef draw_left_foot(self):pass@abstractmethoddef draw_right_foot(self):pass@abstractmethoddef draw_head(self):pass@abstractmethoddef draw_body(self):passclass Thin(Builder):def draw_left_arm(self):print '畫左手'def draw_right_arm(self):print '畫右手'def draw_left_foot(self):print '畫左腳'def draw_right_foot(self):print '畫右腳'def draw_head(self):print '畫頭'def draw_body(self):print '畫瘦身體'class Fat(Builder):def draw_left_arm(self):print '畫左手'def draw_right_arm(self):print '畫右手'def draw_left_foot(self):print '畫左腳'def draw_right_foot(self):print '畫右腳'def draw_head(self):print '畫頭'def draw_body(self):print '畫胖身體'class Director():def __init__(self, person):self.person=persondef draw(self):self.person.draw_left_arm()self.person.draw_right_arm()self.person.draw_left_foot()self.person.draw_right_foot()self.person.draw_head()self.person.draw_body()if __name__=='__main__':thin=Thin()fat=Fat()director_thin=Director(thin)director_thin.draw()director_fat=Director(fat)director_fat.draw()

    ?

    原型模式

    ?

    用原型實例指定創(chuàng)建對象的種類,并且通過拷貝這些原型創(chuàng)建新的對象。
    原型模式本質(zhì)就是克隆對象,所以在對象初始化操作比較復(fù)雜的情況下,很實用,能大大降低耗時,提高性能,因為“不用重新初始化對象,而是動態(tài)地獲得對象運行時的狀態(tài)”。

    淺拷貝(Shallow Copy):指對象的字段被拷貝,而字段引用的對象不會被拷貝,拷貝的對象和源對象只是名稱相同,但是他們共用一個實體。
    深拷貝(deep copy):對對象實例中字段引用的對象也進行拷貝。

    import copy from collections import OrderedDictclass Book:def __init__(self, name, authors, price, **rest):'''rest的例子有:出版商、長度、標(biāo)簽、出版日期'''self.name = nameself.authors = authorsself.price = price # 單位為美元self.__dict__.update(rest)def __str__(self):mylist = []ordered = OrderedDict(sorted(self.__dict__.items()))for i in ordered.keys():mylist.append('{}: {}'.format(i, ordered[i]))if i == 'price':mylist.append('$')mylist.append('\n')return ''.join(mylist)class Prototype:def __init__(self):self.objects = dict()def register(self, identifier, obj):self.objects[identifier] = objdef unregister(self, identifier):del self.objects[identifier]def clone(self, identifier, **attr):found = self.objects.get(identifier)if not found:raise ValueError('Incorrect object identifier: {}'.format(identifier))obj = copy.deepcopy(found)obj.__dict__.update(attr)return objdef main():b1 = Book('The C Programming Language', ('Brian W. Kernighan', 'Dennis M.Ritchie'),price=118, publisher='Prentice Hall', length=228, publication_date='1978-02-22',tags=('C', 'programming', 'algorithms', 'data structures'))prototype = Prototype()cid = 'k&r-first'prototype.register(cid, b1)b2 = prototype.clone(cid, name='The C Programming Language(ANSI)', price=48.99,length=274, publication_date='1988-04-01', edition=2)for i in (b1, b2):print(i)print("ID b1 : {} != ID b2 : {}".format(id(b1), id(b2)))if __name__ == '__main__':main()""" >>> python3 prototype.py authors: ('Brian W. Kernighan', 'Dennis M. Ritchie') length: 228 name: The C Programming Language price: 118$ publication_date: 1978-02-22 publisher: Prentice Hall tags: ('C', 'programming', 'algorithms', 'data structures')authors: ('Brian W. Kernighan', 'Dennis M. Ritchie') edition: 2 length: 274 name: The C Programming Language (ANSI) price: 48.99$ publication_date: 1988-04-01 publisher: Prentice Hall tags: ('C', 'programming', 'algorithms', 'data structures')ID b1 : 140004970829304 != ID b2 : 140004970829472 """

    ?

    2.結(jié)構(gòu)型模式

    適配器模式

    所謂適配器模式是指是一種接口適配技術(shù),它可通過某個類來使用另一個接口與之不兼容的類,運用此模式,兩個類的接口都無需改動。

    適配器模式主要應(yīng)用于希望復(fù)用一些現(xiàn)存的類,但是接口又與復(fù)用環(huán)境要求不一致的情況,比如在需要對早期代碼復(fù)用一些功能等應(yīng)用上很有實際價值。

    解釋二:

    適配器模式(Adapter Pattern):將一個類的接口轉(zhuǎn)換成為客戶希望的另外一個接口.Adapter Pattern使得原本由于接口不兼容而不能一起工作的那些類可以一起工作.
    應(yīng)用場景:系統(tǒng)數(shù)據(jù)和行為都正確,但接口不符合時,目的是使控制范圍之外的一個原有對象與某個接口匹配,適配器模式主要應(yīng)用于希望復(fù)用一些現(xiàn)存的類,但接口又與復(fù)用環(huán)境不一致的情況

    class Target(object):def request(self):print "普通請求"class Adaptee(object):def specific_request(self):print "特殊請求"class Adapter(Target):def __init__(self):self.adaptee = Adaptee()def request(self):self.adaptee.specific_request()if __name__ == "__main__":target = Adapter()target.request()

    ?

    修飾器模式

    該模式雖名為修飾器,但這并不意味著它應(yīng)該只用于讓產(chǎn)品看起來更漂亮。修飾器模式通常用于擴展一個對象的功能。這類擴展的實際例子有,給槍加一個消音器、使用不同的照相機鏡頭

    import functools def memoize(fn):known = dict()@functools.wraps(fn)def memoizer(*args):if args not in known:known[args] = fn(*args)return known[args]return memoizer @memoize def nsum(n):'''返回前n個數(shù)字的和'''assert(n >= 0), 'n must be >= 0'return 0 if n == 0 else n + nsum(n-1) @memoize def fibonacci(n):'''返回斐波那契數(shù)列的第n個數(shù)'''assert(n >= 0), 'n must be >= 0'return n if n in (0, 1) else fibonacci(n-1) + fibonacci(n-2) if __name__ == '__main__':from timeit import Timermeasure = [ {'exec':'fibonacci(100)', 'import':'fibonacci','func':fibonacci},{'exec':'nsum(200)', 'import':'nsum','func':nsum} ]for m in measure:t = Timer('{}'.format(m['exec']), 'from __main__ import{}'.format(m['import']))print('name: {}, doc: {}, executing: {}, time:{}'.format(m['func'].__name__, m['func'].__doc__,m['exec'], t.timeit()))""" >>> python3 mymath.py name: fibonacci, doc: Returns the nth number of the Fibonacci sequence, executing: fibonacci(100), time: 0.4169441329995607 name: nsum, doc: Returns the sum of the first n numbers, executing: nsum(200), time: 0.4160157349997462 """

    ?

    ?

    外觀模式

    外觀模式又叫做門面模式。在面向?qū)ο蟪绦蛟O(shè)計中,解耦是一種推崇的理念。但事實上由于某些系統(tǒng)中過于復(fù)雜,從而增加了客戶端與子系統(tǒng)之間的耦合度。例如:在家觀看多媒體影院時,更希望按下一個按鈕就能實現(xiàn)影碟機,電視,音響的協(xié)同工作,而不是說每個機器都要操作一遍。這種情況下可以采用外觀模式,即引入一個類對子系統(tǒng)進行包裝,讓客戶端與其進行交互。

    外觀模式(Facade Pattern):外部與一個子系統(tǒng)的通信必須通過一個統(tǒng)一的外觀對象進行,為子系統(tǒng)中的一組接口提供一個一致的界面,外觀模式定義了一個高層接口,這個接口使得這一子系統(tǒng)更加容易使用。外觀模式又稱為門面模式,它是一種對象結(jié)構(gòu)型模式。

    from enum import Enum from abc import ABCMeta, abstractmethodState = Enum('State', 'new running sleeping restart zombie')class User:passclass Process:passclass File:passclass Server(metaclass=ABCMeta):@abstractmethoddef __init__(self):passdef __str__(self):return self.name@abstractmethoddef boot(self):pass@abstractmethoddef kill(self, restart=True):passclass FileServer(Server):def __init__(self):'''初始化文件服務(wù)進程要求的操作'''self.name = 'FileServer'self.state = State.newdef boot(self):print('booting the {}'.format(self))'''啟動文件服務(wù)進程要求的操作'''self.state = State.runningdef kill(self, restart=True):print('Killing {}'.format(self))'''終止文件服務(wù)進程要求的操作'''self.state = State.restart if restart else State.zombiedef create_file(self, user, name, permissions):'''檢查訪問權(quán)限的有效性、用戶權(quán)限等'''print("trying to create the file '{}' for user '{}' with permissions{}".format(name, user, permissions))class ProcessServer(Server):def __init__(self):'''初始化進程服務(wù)進程要求的操作'''self.name = 'ProcessServer'self.state = State.newdef boot(self):print('booting the {}'.format(self))'''啟動進程服務(wù)進程要求的操作'''self.state = State.runningdef kill(self, restart=True):print('Killing {}'.format(self))'''終止進程服務(wù)進程要求的操作'''self.state = State.restart if restart else State.zombiedef create_process(self, user, name):'''檢查用戶權(quán)限和生成PID等'''print("trying to create the process '{}' for user '{}'".format(name, user))class WindowServer:passclass NetworkServer:passclass OperatingSystem:'''外觀'''def __init__(self):self.fs = FileServer()self.ps = ProcessServer()def start(self):[i.boot() for i in (self.fs, self.ps)]def create_file(self, user, name, permissions):return self.fs.create_file(user, name, permissions)def create_process(self, user, name):return self.ps.create_process(user, name)def main():os = OperatingSystem()os.start()os.create_file('foo', 'hello', '-rw-r-r')os.create_process('bar', 'ls /tmp')if __name__ == '__main__':main()""" booting the FileServer booting the ProcessServer trying to create the file 'hello' for user 'foo' with permissions-rw-r-r trying to create the process 'ls /tmp' for user 'bar' """

    ?

    享元模式

    運用共享技術(shù)有效地支持大量細(xì)粒度的對象。
    內(nèi)部狀態(tài):享元對象中不會隨環(huán)境改變而改變的共享部分。比如圍棋棋子的顏色。
    外部狀態(tài):隨環(huán)境改變而改變、不可以共享的狀態(tài)就是外部狀態(tài)。比如圍棋棋子的位置。

    應(yīng)用場景:程序中使用了大量的對象,如果刪除對象的外部狀態(tài),可以用相對較少的共享對象取代很多組對象,就可以考慮使用享元模式。

    1 import random2 from enum import Enum3 TreeType = Enum('TreeType', 'apple_tree cherry_tree peach_tree')4 5 class Tree:6 pool = dict()7 def __new__(cls, tree_type):8 obj = cls.pool.get(tree_type, None)9 if not obj: 10 obj = object.__new__(cls) 11 cls.pool[tree_type] = obj 12 obj.tree_type = tree_type 13 return obj 14 15 def render(self, age, x, y): 16 print('render a tree of type {} and age {} at ({}, {})'.format(self.tree_type, age, x, y)) 17 18 19 def main(): 20 rnd = random.Random() 21 age_min, age_max = 1, 30 # 單位為年 22 min_point, max_point = 0, 100 23 tree_counter = 0 24 for _ in range(10): 25 t1 = Tree(TreeType.apple_tree) 26 t1.render(rnd.randint(age_min, age_max), 27 rnd.randint(min_point, max_point), 28 rnd.randint(min_point, max_point)) 29 tree_counter += 1 30 for _ in range(3): 31 t2 = Tree(TreeType.cherry_tree) 32 t2.render(rnd.randint(age_min, age_max), 33 rnd.randint(min_point, max_point), 34 rnd.randint(min_point, max_point)) 35 tree_counter += 1 36 for _ in range(5): 37 t3 = Tree(TreeType.peach_tree) 38 t3.render(rnd.randint(age_min, age_max), 39 rnd.randint(min_point, max_point), 40 rnd.randint(min_point, max_point)) 41 tree_counter += 1 42 43 print('trees rendered: {}'.format(tree_counter)) 44 print('trees actually created: {}'.format(len(Tree.pool))) 45 t4 = Tree(TreeType.cherry_tree) 46 t5 = Tree(TreeType.cherry_tree) 47 t6 = Tree(TreeType.apple_tree) 48 print('{} == {}? {}'.format(id(t4), id(t5), id(t4) == id(t5))) 49 print('{} == {}? {}'.format(id(t5), id(t6), id(t5) == id(t6))) 50 51 main() 52 53 """ 54 render a tree of type TreeType.apple_tree and age 28 at (29, 80) 55 render a tree of type TreeType.apple_tree and age 28 at (38, 94) 56 render a tree of type TreeType.apple_tree and age 16 at (82, 84) 57 render a tree of type TreeType.apple_tree and age 18 at (43, 98) 58 render a tree of type TreeType.apple_tree and age 2 at (84, 72) 59 render a tree of type TreeType.apple_tree and age 16 at (89, 29) 60 render a tree of type TreeType.apple_tree and age 30 at (91, 53) 61 render a tree of type TreeType.apple_tree and age 12 at (92, 73) 62 render a tree of type TreeType.apple_tree and age 3 at (11, 54) 63 render a tree of type TreeType.apple_tree and age 1 at (34, 59) 64 render a tree of type TreeType.cherry_tree and age 11 at (67, 72) 65 render a tree of type TreeType.cherry_tree and age 27 at (65, 81) 66 render a tree of type TreeType.cherry_tree and age 27 at (10, 48) 67 render a tree of type TreeType.peach_tree and age 11 at (35, 38) 68 render a tree of type TreeType.peach_tree and age 3 at (58, 83) 69 render a tree of type TreeType.peach_tree and age 18 at (73, 50) 70 render a tree of type TreeType.peach_tree and age 24 at (94, 3) 71 render a tree of type TreeType.peach_tree and age 4 at (2, 9) 72 trees rendered: 18 73 trees actually created: 3 74 4866032 == 4866032? True 75 4866032 == 4742704? False 76 77 """

    ?

    模型-視圖-控制器模式

    代理模式

    3.行為型模式

    責(zé)任鏈模式

    命令模式

    解釋器模式

    觀察者模式

    狀態(tài)模式

    ?

    策略模式

    模板模式

    ?

    轉(zhuǎn)載于:https://www.cnblogs.com/ExMan/p/10427172.html

    總結(jié)

    以上是生活随笔為你收集整理的常见设计模式 (python代码实现)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。