最全36种python设计模式
设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。
设计模式一般是针对java语言而言,一般的主推面向过程的js 、shell、c语言就很少谈那么多种套路了。通常说的设计模式也是从java经验中提取出来的。
但只要是面向对象的语言,设计模式都可以融入,如php python,但脚本语言像python谈论设计模式的场景和次数比java少很多,估计是py入门低,使用灵活,很多人只习惯喜欢opp方式编程,还有就是py人数在国内十分少,从招聘网站上基本可以得出结论,除开软件测试领域、运维领域或者一些个体户(这些用py只是辅助不是天天写项目),正规军python不到java php的二十分之一估计~~。
设计模式,必须是oop编程,如果写代码只喜欢从上往下一条条命令累加,或者是提取出一些函数来复用,排斥oop,那绝大多数的设计模式都是用不了了(可以给模块打猴子补丁来实现,但是很坑很别扭的这种方式),所以90%的设计模式必须是oop方式的编程。
python中和java有点不同,py没有接口(就比如工厂模式、外观模式、桥接模式啥的啥的java需要保证多个类有同样的方法,会使用接口,python本身没有接口,三方包zope.interface里面可以实现接口,python只要保证那些类是鸭子类型就ok了,没有强制性的接口,比较灵活,但约束少很难保证多个人合作时候懂这个意图,强制实现接口和鸭子类各有利弊吧),py支持多继承和mixin类甚至是打猴子补丁,不是需要完全与java一样来写。
如果没听说设计模式那也有可能经常用过某模式,或者灵感爆发用了某模式,只有专门学习设计模式,才能形成稳定的设计和输出。也有认为设计模式不重要的不需要学习,说得是类似金庸风清扬境界的无招胜有招,手中无招,心中有招。设计模式没有个死的,特别是设计模式的结构型模式中很多模式,基本通过类的组合千变万化变幻而来,很相近的。但是成为编程界的风清扬估计没个七八年的编程经验和好悟性达不到,风清扬也是老了才那么厉害嘛,要想速成可学葵花宝典。风清扬也是先要按套路学,不学基础就达不到这种境界,无招胜有招说的是不能死按套路来,见文。
主要还是有固定的模式,看代码容易些。别人接盘也方便。因为遇到过很多人所有地方所有场景全写函数,而且没有下划线来区别哪些只是内部辅助函数,或者一个函数高达300行,真的很坑爹。如果不会自定义项目或者完全不懂设计模式,那应该找个三方框架来用,这样接盘侠也容易看懂,因为你是按照标准的三方库来用的,别人看代码就节约很多时间了。又不引用三方框架 严格按框架的规定来写,又不用设计模式,到处是原生自定义的写的很长一坨一坨的函数,接盘这样的代码那就很烦人,需要不停的ctrl 加b跳转代码和上下翻屏查看函数怎么写的。
据我的经验改造了十几个模块,光是使用oop就能最起码使代码数量减少40到70%,如果配合设计模式,能够使代码数量最多减少高达90%。我说的这个优化量是针对无限 复制+ 黏贴 + 扣字 这种写法的人写出来的代码,比如写十几个平台,每个平台又分国内外,差的人写法是,无限复制粘贴一个写好的文件然后扣字母去修改,因为每个平台又80%的共性,又有20%的不同之处,不会模式的人,会情不自禁很容易懒惰造成不想在设计模式层面下功夫而是无限制粘贴扣字的low逼写法,写到最后改一个问题,需要修改几十个文件,每个文件高达600多行,改起来十分麻烦,容易出错。
见金庸《笑傲江湖》第十章《传剑》:死招数破得再妙,遇上了活招数,免不了缚手缚脚,
只有任人屠戮。这个‘活’字,你要牢牢记住了。学招时要活学,使招时要活使。倘若拘泥不化,
便练熟了几千万手绝招,遇上了真正高手,终究还是给人家破得干干净净。”令狐冲大喜,
他生性飞扬跳脱,风清扬这几句话当真说到了他心坎里去,连称:“是,是!须得活学活
使。”风清扬道:“五岳剑派中各有无数蠢才,以为将师父传下来的剑招学得精熟,自然
而然便成高手,哼哼,熟读唐诗三百首,不会作诗也会吟!熟读了人家诗句,做几首打油
诗是可以的,但若不能自出机抒,能成大诗人么?”他这番话,自然是连岳不群也骂在其
中了,但令狐冲一来觉得这话十分有理,二来他并未直提岳不群的名字,也就没有抗辩。
风清扬道:“活学活使,只是第一步。要做到出手无招,那才真是踏入了高手的境界。你
说‘各招浑成,敌人便无法可破’,这句话还只说对了一小半。不是‘浑成’,而是根本
无招。你的剑招使得再浑成,只要有迹可寻,敌人便有隙可乘。但如你根本并无招式,敌
人如何来破你的招式?”令狐冲一颗心怦怦乱跳,手心发热,喃喃的道:“根本无招,如
何可破?根本无招,如何可破?”斗然之间,眼前出现了一个生平从所未见、连做梦也想
不到的新天地。风清扬道:“要切肉,总得有肉可切;要斩柴,总得有柴可斩;敌人要破
你剑招,你须得有剑招给人家来破才成。一个从未学过武功的常人,拿了剑乱挥乱舞,你
见闻再博,也猜不到他下一剑要刺向哪里,砍向何处。就算是剑术至精之人,也破不了他
的招式,只因并无招式,‘破招’二字,便谈不上了。只是不曾学过武功之人,虽无招式
,却会给人轻而易举的打倒。真正上乘的剑术,则是能制人而决不能为人所制。”他拾起
地下的一根死人腿骨,随手以一端对着令狐冲,道:“你如何破我这一招?”
令狐冲不知他这一下是甚么招式,一怔之下,便道:“这不是招式,因此破解不得。
”
风清扬微微一笑,道:“这就是了。学武之人使兵刃,动拳脚,总是有招式的,你只
须知道破法,一出手便能破招制敌。”令狐冲道:“要是敌人也没招式呢?”风清扬道:
“那么他也是一等一的高手了,二人打到如何便如何,说不定是你高些,也说不定是他高
些。”
有时候面向过程写的东西真的很复杂的,又不好扩展,特别是交给别人维护时候,非常多的函数高达几十个函数,到处在函数里面return和传参,接盘的人真的很难读懂代码,会造成上班工作时候成心情很差。
例如五子棋,面向过程的设计思路就是首先分析问题的步骤:
1、开始游戏,
2、黑子先走,
3、绘制画面,
4、判断输赢,
5、轮到白子,
6、绘制画面,
7、判断输赢,
8、返回步骤2,
9、输出最后结果。
把上面每个步骤用分别的函数来实现,问题就解决了。
而面向对象的设计则是从另外的思路来解决问题。整个五子棋可以分为:
1、黑白双方,这两方的行为是一模一样的,
2、棋盘系统,负责绘制画面,
3、规则系统,负责判定诸如犯规、输赢等。
第一类对象(玩家对象)负责接受用户输入,并告知第二类对象(棋盘对象)棋子布局的变化,棋盘对象接收到了棋子的变化就要负责在屏幕上面显示出这种变化,同时利用第三类对象(规则系统)来对棋局进行判定。
可 以明显地看出,面向对象是以功能来划分问题,而不是步骤。同样是绘制棋局,这样的行为在面向过程的设计中分散在了总多步骤中,很可能出现不同的绘制版本, 因为通常设计人员会考虑到实际情况进行各种各样的简化。而面向对象的设计中,绘图只可能在棋盘对象中出现,从而保证了绘图的统一。
功 能上的统一保证了面向对象设计的可扩展性。比如我要加入悔棋的功能,如果要改动面向过程的设计,那么从输入到判断到显示这一连串的步骤都要改动,甚至步骤 之间的循序都要进行大规模调整。如果是面向对象的话,只用改动棋盘对象就行了,棋盘系统保存了黑白双方的棋谱,简单回溯就可以了,而显示和规则判断则不用 顾及,同时整个对对象功能的调用顺序都没有变化,改动只是局部的。
python扩展类方面,大体包括继承 组合 mixin三种。
继承:子类继承父类,子类具有父类的属性和方法。子类还是和父类是同种东西。比如人和孩子、成年人,孩子也是属于人。is A
组合:人和手机,人可以有一个实例属性叫phone,phone的值则是一个Phone类的实例,这样通过操作人这个对象的phone属性来操作手机浏览网页和打电话。具体的打电话和浏览网页的功能在Phone类中,手机可以有打电话 发短信的功能,人本身不具备这个功能。在实例方法中操作手机是self.phone.send_mesage('你好'),而不要弄成人继承手机,然后用self.send_mesage('你好'),人不是手机的子类,不要搞成继承,人和手机的关系是has A。设计模式,大多是通过组合来变换出来的,继承要少用,除非确定子类是父类的一个更小分类。例如界(Kingdom)、门(Phylum)、纲(Class)、目(Order)、科(Family)、属(Genus)、种(Species),更小的分类是上一级父类的一个子集。
mixin: 扩展类的功能,插件类,男学生和女学生都可以继承一个上课的mixin类,成年人可以继承一个打工赚钱的mixin类。一般情况下mixin类不写__init__方法,mixin类里面的有些属性在mixin类本身中不具备,所以不可以把mixin类单独直接的实例化。mixin方式可以被组合替代,mixin类的方法可以直接访问基本类的方法和属性,组合把基本类实例绑定到组合类的实例属性或者把基本类实例作为参数传给其方法,来达到访问基本类的方法和属性。使用场景有,多个类要添加相同的功能,可以去每个类写几个方法,多少个类复制黏贴多少次,重复较多,要修改的时候又要去每个类去修改。代码太长命名空间下方法太多,类变成了上帝类。
mixin类例如:
class Person(): def __init__(self, name): self.name = name def walk(self): print '行走' class StudyMixin(): def study(self): print self.name + '...在上课...' class Student(Person,StudyMixin): def __init__(self, name,age): Person.__init__(self,name) self.age=age def eat(self): print self.name + '...在吃饭...' Student('小明',10).study() # StudyMixin().study()
这样做小明本来继承自person只能走路,但加了mixin类,小明可以学习了。StudyMixin类则不能直接实例化,因为在这个类中,没有name这个属性,运行study方法会出错。
软件工程中,设计模式是指软件设计问题的推荐方案。设计模式一般是描述如何组织代码和
使用最佳实践来解决常见的设计问题。需谨记在心的一点是:设计模式是高层次的方案,并不关
注具体的实现细节,比如算法和数据结构
创建型模式:
设计模式 -创建型模式 ,工厂模式 、抽象工厂模式
设计模式- 创建型模式, 建造者模式
设计模式-创建型模式,原型模式
设计模式-创建型模式,python享元模式 、python单例模式
python对象池模式
结构型模式:
设计模式-创结构型模式,python 桥接模式
设计模式-结构型模式,适配器模式(4)
设计模式-结构型模式,python组合模式
装饰器模式 http://www.cnblogs.com/ydf0509/p/8525692.html
外观模式 http://www.cnblogs.com/ydf0509/p/8525853.html
mvc模式 http://www.cnblogs.com/ydf0509/p/8525949.html
代理模式 http://www.cnblogs.com/ydf0509/p/8525970.html
行为型模式:
责任链模式 http://www.cnblogs.com/ydf0509/p/8525991.html
命令模式 http://www.cnblogs.com/ydf0509/p/8526012.html
解释器模式 http://www.cnblogs.com/ydf0509/p/8526064.html
观察者模式 http://www.cnblogs.com/ydf0509/p/8526100.html
状态模式 http://www.cnblogs.com/ydf0509/p/8527468.html
策略模式 http://www.cnblogs.com/ydf0509/p/8527515.html
模板模式 http://www.cnblogs.com/ydf0509/p/8527685.html
设计模式-行为型模式,python 中介者模式
设计模式-行为型模式,python备忘录模式
设计模式-行为型模式,python访问者模式
python 迭代器模式
python设计模式之猴子补丁模式 python独有模式
为保证对模式没有误解和误判,代码例子是用的从精通python 16种设计模式那本书中的,有的用的网上的。
一个在线的 http://www.pythontip.com/pythonPatterns/
github的 https://github.com/faif/python-patterns
菜鸟教程的 http://www.runoob.com/design-pattern/design-pattern-tutorial.html