常见设计模式 (python代码实现)
1.創(chuàng)建型模式
單例模式
單例模式(Singleton Pattern)是一種常用的軟件設計模式,該模式的主要目的是確保某一個類只有一個實例存在。當你希望在整個系統(tǒng)中,某個類只能出現(xiàn)一個實例時,單例對象就能派上用場。
比如,某個服務器程序的配置信息存放在一個文件中,客戶端通過一個 AppConfig 的類來讀取配置文件的信息。如果在程序運行期間,有很多地方都需要使用配置文件的內(nèi)容,也就是說,很多地方都需要創(chuàng)建 AppConfig 對象的實例,這就導致系統(tǒng)中存在多個 AppConfig 的實例對象,而這樣會嚴重浪費內(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)建對象的設計模式。
工廠模式包涵一個超類。這個超類提供一個抽象化的接口來創(chuàng)建一個特定類型的對象,而不是決定哪個對象可以被創(chuàng)建。
為了實現(xiàn)此方法,需要創(chuàng)建一個工廠類創(chuàng)建并返回。?
當程序運行輸入一個“類型”的時候,需要創(chuàng)建于此相應的對象。這就用到了工廠模式。在如此情形中,實現(xiàn)代碼基于工廠模式,可以達到可擴展,可維護的代碼。當增加一個新的類型,不在需要修改已存在的類,只增加能夠產(chǎn)生新類型的子類。
簡短的說,當以下情形可以使用工廠模式:
1.不知道用戶想要創(chuàng)建什么樣的對象
2.當你想要創(chuàng)建一個可擴展的關(guān)聯(lián)在創(chuàng)建類與支持創(chuàng)建對象的類之間。
一個例子更能很好的理解以上的內(nèi)容:
在程序運行期間,用戶傳遞性別給工廠,工廠創(chuàng)建一個與性別有關(guān)的對象。因此工廠類在運行期,決定了哪個對象應該被創(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")建造者模式
將一個復雜對象的構(gòu)建與它的表示分離,使得同樣的構(gòu)建過程可以創(chuàng)建不同的表示。
相關(guān)模式:思路和模板方法模式很像,模板方法是封裝算法流程,對某些細節(jié),提供接口由子類修改,建造者模式更為高層一點,將所有細節(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ì)就是克隆對象,所以在對象初始化操作比較復雜的情況下,很實用,能大大降低耗時,提高性能,因為“不用重新初始化對象,而是動態(tài)地獲得對象運行時的狀態(tài)”。
淺拷貝(Shallow Copy):指對象的字段被拷貝,而字段引用的對象不會被拷貝,拷貝的對象和源對象只是名稱相同,但是他們共用一個實體。
深拷貝(deep copy):對對象實例中字段引用的對象也進行拷貝。
?
2.結(jié)構(gòu)型模式
適配器模式
所謂適配器模式是指是一種接口適配技術(shù),它可通過某個類來使用另一個接口與之不兼容的類,運用此模式,兩個類的接口都無需改動。
適配器模式主要應用于希望復用一些現(xiàn)存的類,但是接口又與復用環(huán)境要求不一致的情況,比如在需要對早期代碼復用一些功能等應用上很有實際價值。
解釋二:
適配器模式(Adapter Pattern):將一個類的接口轉(zhuǎn)換成為客戶希望的另外一個接口.Adapter Pattern使得原本由于接口不兼容而不能一起工作的那些類可以一起工作.
應用場景:系統(tǒng)數(shù)據(jù)和行為都正確,但接口不符合時,目的是使控制范圍之外的一個原有對象與某個接口匹配,適配器模式主要應用于希望復用一些現(xiàn)存的類,但接口又與復用環(huán)境不一致的情況
?
修飾器模式
該模式雖名為修飾器,但這并不意味著它應該只用于讓產(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計中,解耦是一種推崇的理念。但事實上由于某些系統(tǒng)中過于復雜,從而增加了客戶端與子系統(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):'''初始化文件服務進程要求的操作'''self.name = 'FileServer'self.state = State.newdef boot(self):print('booting the {}'.format(self))'''啟動文件服務進程要求的操作'''self.state = State.runningdef kill(self, restart=True):print('Killing {}'.format(self))'''終止文件服務進程要求的操作'''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):'''初始化進程服務進程要求的操作'''self.name = 'ProcessServer'self.state = State.newdef boot(self):print('booting the {}'.format(self))'''啟動進程服務進程要求的操作'''self.state = State.runningdef kill(self, restart=True):print('Killing {}'.format(self))'''終止進程服務進程要求的操作'''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ù)有效地支持大量細粒度的對象。
內(nèi)部狀態(tài):享元對象中不會隨環(huán)境改變而改變的共享部分。比如圍棋棋子的顏色。
外部狀態(tài):隨環(huán)境改變而改變、不可以共享的狀態(tài)就是外部狀態(tài)。比如圍棋棋子的位置。
應用場景:程序中使用了大量的對象,如果刪除對象的外部狀態(tài),可以用相對較少的共享對象取代很多組對象,就可以考慮使用享元模式。
?
模型-視圖-控制器模式
代理模式
3.行為型模式
責任鏈模式
命令模式
解釋器模式
觀察者模式
狀態(tài)模式
?
策略模式
模板模式
?
轉(zhuǎn)載于:https://www.cnblogs.com/ExMan/p/10427172.html
總結(jié)
以上是生活随笔為你收集整理的常见设计模式 (python代码实现)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 碳钢腐蚀速率计算公式_镁合金轮毂螺栓连接
- 下一篇: 物流前沿理论与方法1