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

1.创建型模式

单例模式

单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在。当你希望在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场。

比如,某个服务器程序的配置信息存放在一个文件中,客户端通过一个 AppConfig 的类来读取配置文件的信息。如果在程序运行期间,有很多地方都需要使用配置文件的内容,也就是说,很多地方都需要创建 AppConfig 对象的实例,这就导致系统中存在多个 AppConfig 的实例对象,而这样会严重浪费内存资源,尤其是在配置文件内容很多的情况下。事实上,类似 AppConfig 这样的类,我们希望在程序运行期间只存在一个实例对象

ContractedBlock.gif

ExpandedBlockStart.gif

1 classSingleton(object):2 def __init__(self):3 pass

4

5 def __new__(cls, *args, **kwargs):6 if not hasattr(Singleton, "_instance"): #反射

7 Singleton._instance = object.__new__(cls)8 returnSingleton._instance9

10 obj1 =Singleton()11 obj2 =Singleton()12 print(obj1, obj2) #<__main__.Singleton object at 0x004415F0> <__main__.Singleton object at 0x004415F0>

单例模式

工厂模式

工厂模式是一个在软件开发中用来创建对象的设计模式。

工厂模式包涵一个超类。这个超类提供一个抽象化的接口来创建一个特定类型的对象,而不是决定哪个对象可以被创建。

为了实现此方法,需要创建一个工厂类创建并返回。

当程序运行输入一个"类型”的时候,需要创建于此相应的对象。这就用到了工厂模式。在如此情形中,实现代码基于工厂模式,可以达到可扩展,可维护的代码。当增加一个新的类型,不在需要修改已存在的类,只增加能够产生新类型的子类。

简短的说,当以下情形可以使用工厂模式:

1.不知道用户想要创建什么样的对象

2.当你想要创建一个可扩展的关联在创建类与支持创建对象的类之间。

一个例子更能很好的理解以上的内容:

我们有一个基类Person ,包涵获取名字,性别的方法 。有两个子类male 和female,可以打招呼。还有一个工厂类。

工厂类有一个方法名getPerson有两个输入参数,名字和性别。

用户使用工厂类,通过调用getPerson方法。

在程序运行期间,用户传递性别给工厂,工厂创建一个与性别有关的对象。因此工厂类在运行期,决定了哪个对象应该被创建

ContractedBlock.gif

ExpandedBlockStart.gif

classPerson:def __init__(self):

self.name=None

self.gender=NonedefgetName(self):returnself.namedefgetGender(self):returnself.genderclassMale(Person):def __init__(self, name):print "Hello Mr." +nameclassFemale(Person):def __init__(self, name):print "Hello Miss." +nameclassFactory:defgetPerson(self, name, gender):if gender == "M':

returnMale(name)if gender == 'F':returnFemale(name)if __name__ == '__main__':

factory=Factory()

person= factory.getPerson("Chetan", "M")

工厂模式

建造者模式

将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

相关模式:思路和模板方法模式很像,模板方法是封装算法流程,对某些细节,提供接口由子类修改,建造者模式更为高层一点,将所有细节都交由子类实现

一个例子更能很好的理解以上的内容:

1. 有一个接口类,定义创建对象的方法。一个指挥员类,接受创造者对象为参数。两个创造者类,创建对象方法相同,内部创建可自定义

2.一个指挥员,两个创造者(瘦子 胖子),指挥员可以指定由哪个创造者来创造

ContractedBlock.gif

ExpandedBlockStart.gif

from abc importABCMeta, abstractmethodclassBuilder():__metaclass__ =ABCMeta

@abstractmethoddefdraw_left_arm(self):pass@abstractmethoddefdraw_right_arm(self):pass@abstractmethoddefdraw_left_foot(self):pass@abstractmethoddefdraw_right_foot(self):pass@abstractmethoddefdraw_head(self):pass@abstractmethoddefdraw_body(self):pass

classThin(Builder):defdraw_left_arm(self):print '画左手'

defdraw_right_arm(self):print '画右手'

defdraw_left_foot(self):print '画左脚'

defdraw_right_foot(self):print '画右脚'

defdraw_head(self):print '画头'

defdraw_body(self):print '画瘦身体'

classFat(Builder):defdraw_left_arm(self):print '画左手'

defdraw_right_arm(self):print '画右手'

defdraw_left_foot(self):print '画左脚'

defdraw_right_foot(self):print '画右脚'

defdraw_head(self):print '画头'

defdraw_body(self):print '画胖身体'

classDirector():def __init__(self, person):

self.person=persondefdraw(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()

建造者模式

原型模式

1367382-20180601221422268-1304951551.png

用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

原型模式本质就是克隆对象,所以在对象初始化操作比较复杂的情况下,很实用,能大大降低耗时,提高性能,因为"不用重新初始化对象,而是动态地获得对象运行时的状态”。

浅拷贝(Shallow Copy):指对象的字段被拷贝,而字段引用的对象不会被拷贝,拷贝的对象和源对象只是名称相同,但是他们共用一个实体。

深拷贝(deep copy):对对象实例中字段引用的对象也进行拷贝。

ContractedBlock.gif

ExpandedBlockStart.gif

importcopyfrom collections importOrderedDictclassBook:def __init__(self, name, authors, price, **rest):'''rest的例子有:出版商、长度、标签、出版日期'''self.name=name

self.authors=authors

self.price= price #单位为美元

self.__dict__.update(rest)def __str__(self):

mylist=[]

ordered= OrderedDict(sorted(self.__dict__.items()))for i inordered.keys():

mylist.append('{}: {}'.format(i, ordered[i]))if i == 'price':

mylist.append('$')

mylist.append(' ')return ''.join(mylist)classPrototype:def __init__(self):

self.objects=dict()defregister(self, identifier, obj):

self.objects[identifier]=objdefunregister(self, identifier):delself.objects[identifier]def clone(self, identifier, **attr):

found=self.objects.get(identifier)if notfound:raise ValueError('Incorrect object identifier: {}'.format(identifier))

obj=copy.deepcopy(found)

obj.__dict__.update(attr)returnobjdefmain():

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.结构型模式

适配器模式

所谓适配器模式是指是一种接口适配技术,它可通过某个类来使用另一个接口与之不兼容的类,运用此模式,两个类的接口都无需改动。

适配器模式主要应用于希望复用一些现存的类,但是接口又与复用环境要求不一致的情况,比如在需要对早期代码复用一些功能等应用上很有实际价值。

解释二:

适配器模式(Adapter Pattern):将一个类的接口转换成为客户希望的另外一个接口.Adapter Pattern使得原本由于接口不兼容而不能一起工作的那些类可以一起工作.

应用场景:系统数据和行为都正确,但接口不符合时,目的是使控制范围之外的一个原有对象与某个接口匹配,适配器模式主要应用于希望复用一些现存的类,但接口又与复用环境不一致的情况

1264910-20171116103255452-1901747047.png

ContractedBlock.gif

ExpandedBlockStart.gif

classTarget(object):defrequest(self):print "普通请求"

classAdaptee(object):defspecific_request(self):print "特殊请求"

classAdapter(Target):def __init__(self):

self.adaptee=Adaptee()defrequest(self):

self.adaptee.specific_request()if __name__ == "__main__":

target=Adapter()

target.request()

适配器模式

修饰器模式

该模式虽名为修饰器,但这并不意味着它应该只用于让产品看起来更漂亮。修饰器模式通常用于扩展一个对象的功能。这类扩展的实际例子有,给枪加一个消音器、使用不同的照相机镜头

1371028-20180726174144243-2031079749.jpg

ContractedBlock.gif

ExpandedBlockStart.gif

importfunctoolsdefmemoize(fn):

known=dict()

@functools.wraps(fn)def memoizer(*args):if args not inknown:

known[args]= fn(*args)returnknown[args]returnmemoizer

@memoizedefnsum(n):'''返回前n个数字的和'''

assert(n >= 0), 'n must be >= 0'

return 0 if n == 0 else n + nsum(n-1)

@memoizedeffibonacci(n):'''返回斐波那契数列的第n个数'''

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 importTimer

measure= [ {'exec':'fibonacci(100)', 'import':'fibonacci','func':fibonacci},{'exec':'nsum(200)', 'import':'nsum','func':nsum} ]for m inmeasure:

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"""

修饰器模式

外观模式

外观模式又叫做门面模式。在面向对象程序设计中,解耦是一种推崇的理念。但事实上由于某些系统中过于复杂,从而增加了客户端与子系统之间的耦合度。例如:在家观看多媒体影院时,更希望按下一个按钮就能实现影碟机,电视,音响的协同工作,而不是说每个机器都要操作一遍。这种情况下可以采用外观模式,即引入一个类对子系统进行包装,让客户端与其进行交互。

外观模式(Facade Pattern):外部与一个子系统的通信必须通过一个统一的外观对象进行,为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。外观模式又称为门面模式,它是一种对象结构型模式。

ContractedBlock.gif

ExpandedBlockStart.gif

from enum importEnumfrom abc importABCMeta, abstractmethod

State= Enum('State', 'new running sleeping restart zombie')classUser:pass

classProcess:pass

classFile:pass

class Server(metaclass=ABCMeta):

@abstractmethoddef __init__(self):pass

def __str__(self):returnself.name

@abstractmethoddefboot(self):pass@abstractmethoddef kill(self, restart=True):pass

classFileServer(Server):def __init__(self):'''初始化文件服务进程要求的操作'''self.name= 'FileServer'self.state=State.newdefboot(self):print('booting the {}'.format(self))'''启动文件服务进程要求的操作'''self.state=State.runningdef kill(self, restart=True):print('Killing {}'.format(self))'''终止文件服务进程要求的操作'''self.state= State.restart if restart elseState.zombiedefcreate_file(self, user, name, permissions):'''检查访问权限的有效性、用户权限等'''

print("trying to create the file '{}' for user '{}' with permissions{}".format(name, user, permissions))classProcessServer(Server):def __init__(self):'''初始化进程服务进程要求的操作'''self.name= 'ProcessServer'self.state=State.newdefboot(self):print('booting the {}'.format(self))'''启动进程服务进程要求的操作'''self.state=State.runningdef kill(self, restart=True):print('Killing {}'.format(self))'''终止进程服务进程要求的操作'''self.state= State.restart if restart elseState.zombiedefcreate_process(self, user, name):'''检查用户权限和生成PID等'''

print("trying to create the process '{}' for user '{}'".format(name, user))classWindowServer:pass

classNetworkServer:pass

classOperatingSystem:'''外观'''

def __init__(self):

self.fs=FileServer()

self.ps=ProcessServer()defstart(self):

[i.boot()for i in(self.fs, self.ps)]defcreate_file(self, user, name, permissions):returnself.fs.create_file(user, name, permissions)defcreate_process(self, user, name):returnself.ps.create_process(user, name)defmain():

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'"""

外观模式

享元模式

运用共享技术有效地支持大量细粒度的对象。

内部状态:享元对象中不会随环境改变而改变的共享部分。比如围棋棋子的颜色。

外部状态:随环境改变而改变、不可以共享的状态就是外部状态。比如围棋棋子的位置。

应用场景:程序中使用了大量的对象,如果删除对象的外部状态,可以用相对较少的共享对象取代很多组对象,就可以考虑使用享元模式。

ContractedBlock.gif

ExpandedBlockStart.gif

1 importrandom2 from enum importEnum3 TreeType = Enum('TreeType', 'apple_tree cherry_tree peach_tree')4

5 classTree:6 pool =dict()7 def __new__(cls, tree_type):8 obj =cls.pool.get(tree_type, None)9 if notobj:10 obj = object.__new__(cls)11 cls.pool[tree_type] =obj12 obj.tree_type =tree_type13 returnobj14

15 defrender(self, age, x, y):16 print('render a tree of type {} and age {} at ({}, {})'.format(self.tree_type, age, x, y))17

18

19 defmain():20 rnd =random.Random()21 age_min, age_max = 1, 30 #单位为年

22 min_point, max_point = 0, 100

23 tree_counter =024 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: 1873 trees actually created: 374 4866032 == 4866032? True75 4866032 == 4742704? False76

77 """

享元模式

模型-视图-控制器模式

代理模式

3.行为型模式

责任链模式

命令模式

解释器模式

观察者模式

状态模式

策略模式

模板模式

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值