为什么Python不用设计模式?

 在遥远的Python王国,有一位少年,非常热爱编程,他的父母想给他报一个班,问了***的朋友圈以后,发现大家都推荐同一个老师,人称吉先生。

于是他的父母毫不犹豫就交了一笔不菲的学费,每周六日下午让孩子去学习。

少年学习非常刻苦,很快就学会了Python语法、工具和框架。

老师像是见到了可以雕刻的美玉, 倾囊相授,告诉他不仅要把代码写对,还要让代码漂亮、优雅、可读、可维护。

少年又学会了单元测试,TDD,重构,努力让自己的代码达到老师所要求的标准。

他还把“Python 之禅”贴在了自己的墙上,经常对照自己的代码,从来都不敢违反。

  • The Zen of Python, by Tim Peters
  • Beautiful is better than ugly.
  • Explicit is better than implicit.
  • Simple is better than complex.
  • Complex is better than complicated.
  • Flat is better than nested.
  • Sparse is better than dense.
  • Readability counts.
  • ......

三年以后,少年以为自己成为了Python的大师,直到有一天,老师给他布置了一个大作业,其实是个大项目,业务非常复杂。

少年通宵达旦地编程,可他悲惨地发现,无论他怎么努力,他的代码都是乱糟糟的,没有美感,他所写出的类,模块混成了一团。

于是他只好去请教老师: “老师,我的Python和Flask框架已经用得滚瓜烂熟了,为什么完成不了这个项目呢?”

老师说:“孩子,原来你只需要把框架的类给import进来,稍微写点儿代码就行了,现在你需要自己去设计类,自己去做出抽象了!”

“怎么设计呢?”

“为师送你一本古书,《设计模式》 ,你回去好好看看吧。”

少年如获至宝, 废寝忘食地去研究这本20多年前出的、泛黄的古书,还是用C++描述的。

他看得云里雾里,似乎明白,又似乎不明白,只好再去请教老师。

这一次,老师给了他另外一本书, 《Head First 设计模式》

少年翻开一看,这本书是用Java写的,于是又一头扎到了Java语言当中。

这本书比较通俗易懂,少年看得大呼过瘾。

终于,他信心十足地用Python开始那个大项目了。

他用Python语言实现设计模式,解决一些设计问题,可是总觉得不对劲,和Java , C++相比,感觉怪怪的。

另外他感觉到了动态语言的不爽之处,每次想重构的时候,总是不敢下手,他把困惑给老师说了。

老师笑道:“我在Java王国的时候,人们总是说‘动态一时爽,重构火葬场’, 现在你体会到了吧!”

“Java就能避免这个问题吗?”

“Java是一门静态语言,变量类型一旦确定就不能改变,对重构的支持非常好,你有没有兴趣去看看?那里有很多的框架,像Spring,Spring Boot,MyBatis, Dubbo, Netty,非常繁荣发达。”

少年心生向往,于是老师就给他写了个条子,告诉他说到了Java王国,找到IO大臣,一切事情都会畅通无阻。

少年辞别老师,奔向了Java帝国,老师整了整衣冠, 望着东方Java帝国的方向,庄严地拜了三拜:“五年了,IO大人,我没有辜负您的重托,又忽悠了一个人去做Java了!”

原来这位老师就是吉森! IO大臣派来传播Java文化和价值观的传教士,入境后不幸被识破,软禁在了Python王国。

吉森的故事请移步《Java帝国对Python的渗透能成功吗?》

Python没有接口?

Python国王收到边关的奏报,说是最近有不少年轻人奔向了Java王国,不知道是不是国内政策有变,导致人心浮动。

Python国王震怒,下令严查。 查来查去,所有的线索都指向了一个人:吉森。

这一天,Python特使带着士兵来到了吉森的住所,果然发现他又在忽悠年轻人了。

特使又气又笑:“你学了半吊子的Python,居然敢来蛊惑人心,实在是可笑。”

吉森看到自己的计谋已被识破,依然很镇静:“大人误会了,我教的就是正宗的面向对象的设计和设计模式啊,这设计模式用Python实现起来很别扭,我就推荐他们去学Java啊。”

“胡说,Python写设计模式怎么会很别扭? Java 由于语法所限,表达能力比较弱,对于一些问题,只好用笨拙的设计模式来解决,我们Python有可能在语法层面就解决问题了!”

“那你说说,设计模式的原则是什么?” 吉森问道。

“1. 面向接口编程,而不是面向实现编程。2. 优先使用组合而不是继承。” 这是难不住特使的。

“Python连接口都没有,怎么面向接口编程?” 吉森问道。

特使哈哈大笑:“说你是半吊子吧,你还不服,你以为这里的接口就是你们Java的interface啊!你忘了Python的Duck Typing了?”

 
 
 
 
  1. class Duck:
  2.     def fly(self):
  3.         print("Duck flying")
  4. class Airplane:
  5.     def fly(self):
  6.         print("Airplane flying")
  7. def lift_off(entity):
  8.     entity.fly()
  9. duck = Duck()
  10. plane = Airplane()
  11. lift_off(duck)
  12. lift_off(plane)

“看到没有, Duck和Airplane都没有实现你所谓的接口,但是都可以调用fly()方法,这难道不是面向接口编程, 如果你非要类比的话,这个fly就是一个自动化的接口啊。”

吉森确实没想到这一层,至于第二个原则,优先使用组合而不是继承,可以是每个面向对象的语言都可以实现的,他叹了口气,也就不问了。

Adapter模式

特使接着说:“Duck Typing非常强大,你不是提到了设计模式吗,在Duck Typing面前,很多设计模式纯属多此一举。我来给你举个例子,Adapter模式。假设客户端有这么一段代码,可以把一段日志写入文件当中。”

 
 
 
 
  1. def log(file,msg):
  2.     file.write('[{}] - {}'.format(datetime.now(), msg))

“现在来了新的需求,要把日志写入数据库, 而数据库并没有write 方法,怎么办? 那就写个Adapter吧。”

 
 
 
 
  1. class DBAdapter:
  2.     def __init__(self, db):
  3.         self.db = db
  4.     def write(self, msg):
  5.         self.db.insert(msg)

“注意这个DBAdapter并不需要实现什么接口(我大Python也没有接口),就是一个单独的类,只需要有个write方法就可以了。”

 
 
 
 
  1. db_adapter = DBAdapter(db)
  2. log(db_adapter, "sev1 error occurred")

确实是很简单,只要有write 方法, 不管你是任何对象,都可以进行调用, 典型的Duck Typing 。

既然Adapter可以这么写,那Proxy模式也是类似了,只要你的Proxy类和被代理的类的方法一样,那就可以被客户使用。

但是这种方法的弊端就是,不知道log方法的参数类型,想要重构可就难了。

单例模式

吉森又想到了一个问题,继续挑战特使:“Python连个private 关键字都没有,怎么隐藏一个类的构造函数,怎么去实现单例?”

特使不屑地说:“忘掉你那套Java思维吧,在Python中想写个singleton有很多办法,我给你展示一个比较Python的方式,用module的方式来实现。”

 
 
 
 
  1. #singleton.py
  2. class Singleton:
  3.     def __init__(self):
  4.         self.name = "i'm singleton"
  5. instance = Singleton()
  6. del Singleton  # 把构造函数删除

使用Singleton:

 
 
 
 
  1. import singleton
  2. print(singleton.instance.name)  # i'm singleton
  3. instance = Singleton() # NameError: name 'Singleton' is not defined

吉森确实没有想到这种写法,利用Python的module来实现信息的隐藏。

Visitor模式

不是每个设计模式都能这么干吧? 吉森心中暗想,他脑海中浮现了一个难于理解的模式:Visitor,自己当初为了学习它可是下了苦工。

吉森说:“那你说说,对于Visitor,怎么利用Python的特色?”

“我知道你心里想的是什么,无非就是想让我写一个类,然后在写个Visitor对它进行访问,是不是?”

 
 
 
 
  1. class TreeNode:
  2.     def __init__(self, data):
  3.         self.data = data
  4.         self.left = None
  5.         self.right = None
  6.     def accept(self, visitor):
  7.         if self.left is not None:
  8.             self.left.accept(visitor)
  9.         visitor.visit(self)
  10.         if self.right is not None:
  11.             self.right.accept(visitor)
  12. class PrintVisitor:
  13.     def visit(self,node):
  14.         print(node.data)
  15. root = TreeNode('1')
  16. root.left = TreeNode('2')
  17. root.right = TreeNode('3')
  18. visitor = PrintVisitor()
  19. root.accept(visitor)   #输出2, 1, 3

吉森说:“是啊, 难道Visitor模式不是这么写的吗? ”

"我就说你的Python只是学了点皮毛吧,Visitor的本质是在分离结构和操作, 在Python中使用generator可以更加优雅地实现。”

 
 
 
 
  1. class TreeNode:
  2.     def __iter__(self):
  3.         return self.__generator()
  4.     def __generator(self):
  5.         if self.left is not None:
  6.             yield from iter(self.left) 
  7.         yield from self.data
  8.         if self.right is not None:
  9.             yield from iter(self.right) 
  10. root = TreeNode('1')
  11. root.left = TreeNode('2')
  12. root.right = TreeNode('3')
  13. for ele in root:
  14.     print(ele)

不得不承认,这种方式使用起来更加简洁,同时达到了结构和操作进行分离的目的。

特使说道: “看到了吧,Python在语言层面对一些模式提供了支持,所以很多设计模式在我大Python看起来非常笨拙,我们这里并不提倡,当然我们还是要掌握面向对象设计的原则SOLID和设计模式的思想,发现变化并且封装变化,这样才能写出优雅的程序出来。”

吉森叹了一口气,感慨自己学艺不精,不再反抗,束手就擒。

尾声

Python王国审判了吉森,本来要判他死刑,但是Java帝国重兵压境,要求释放,否则就开战。

吉森被送回Java王国,成为了人们心目中的英雄,回家他仔细对比了Java和Python,在Java虚拟机上把Python语言给实现了!国王为了表彰他的英勇事迹,把这个语言叫做Jython。

【本文为专栏作者“刘欣”的原创稿件,转载请通过作者微信公众号coderising获取授权】

新闻标题:为什么Python不用设计模式?
本文网址:http://www.hantingmc.com/qtweb/news40/371090.html

网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联