前言

虽然没有学习过Java,但是Java里那一直挂在嘴边的设计模式听到的次数就太多了,听的多了不代表就懂了。

所谓设计模式,主要是三个原则:

  • 面向接口编程,而不是面向实现编程
  • 优先使用组合,而不是继承

Python时间也不短了,但一直都是用成熟的库,很少自己去封装一套,最多也就是改写一些方法,几乎没听见过Python大佬提过设计模式的事。

那么Python的设计模式是啥样的呢?

Python的接口

区别于JAVA的接口(interface),Python没有所谓的接口,但动态语言有一种语法称为Duck Typing,可以实现接口的功能。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Pig():
def eat(self):
print("pig eat all!")

class Cat():
def eat(self):
print("cat eat!")


def eat(entity):
entity.eat()


pig = Pig()
cat = Cat()

eat(pig)
eat(cat)

这串代码中PigCat两个类都没去做特意的接口,但是可以通过同一个方式调用eat这个方法,简单明了的实现。

适配器模式(Adapter)

假设目前有个需求是把日志记录到文件,现在有如下完成方法:

1
2
def log(f, msg):
f.write(mag)

某天,需求变更,需要将日志记录到数据库,但是数据库根本没有write方法,那么就尝试添加数据库write方法:

1
2
3
4
5
6
class DBAdapter():
def __inti__(self, db):
self.db = db

def writer(self, msg):
self.db.insert(msg)

具体的实现如下:

1
2
db_adapter = DBAdapter(db)
log(db_adater, "ABCDEFG")

通过简单的添加write的方法即可简单实现变更后的需求。

代理模式(Proxy Pattern)

假设目前需求要求实现一个访问器:

1
2
3
4
5
6
7
8
9
class Visitor():
def __init__(self, ip):
self.connect = connect((localhost, 9999), ip)

def see(self):
self.connect.getinfo()


visitor = Visitor()

现在变更需求,要求只能本地主机访问这个服务:

1
2
3
4
5
6
7
8
9
class ProxyVistor():
def __init__(self, ip):
self.connect = Vistor(localhost)

def see():
self.connecet.see()

visitor = ProxyVistor(ip)
visitor.see()

代理模式不是太懂,这部分的实现应该就是这样吧。哈哈哈哈~~

单例模式(Singleton Pattern)

尝试新建一个文件,命名single.py

1
2
3
4
5
6
7
8
class Single():
def __init__(self):
print("AAA")


instance = Single()

del Single() # 这个操作是真的骚,删除构造函数!!!

使用single:

1
2
3
4
5
import single

single.instance

instance = Singele() # 运行这步会报错

这步操作是真的骚!我特么完全没想到还有这操作!!!!!!!!!!!!!!!

访问者模式(Visitor)

参考:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class TreeNode:
def __init__(self, data):
self.data = data
self.left = None
self.right = None
def accept(self, visitor):
if self.left is not None:
self.left.accept(visitor)

visitor.visit(self)

if self.right is not None:
self.right.accept(visitor)

class PrintVisitor:
def visit(self,node):
print(node.data)

root = TreeNode('1')
root.left = TreeNode('2')
root.right = TreeNode('3')

visitor = PrintVisitor()

root.accept(visitor) #输出2, 1, 3

逻辑这么复杂纯粹是反人类…

采用generator改写:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class TreeNode:
def __init__(self, data):
self.data = data
self.left = None
self.right = None

def __iter__(self):
return self.__generator()

def __generator(self):
if self.left is not None:
yield from iter(self.left)
yield from self.data

if self.right is not None:
yield from iter(self.right)

root = TreeNode('1')
root.left = TreeNode('2')
root.right = TreeNode('3')

for ele in root:
print(ele)

文章参考:

相关文章
评论
分享
  • python类反射

    起因 最近一直在写数据构造器,所有的虚假数据均调用的是一个Methor类,需要用到类反射。 采取的做法方法一 为了方便,采取了eval()将组合成的方法名字符串运行成函数,刚开始很正常,但是一看速度,心态炸了啊!!!!!平均需要0....

    python类反射
  • Python小技巧

    列表推导123456# 列表推导l = [x for x in range(10)]# 集合推导s = {x for x in range(10)}# 字典推导d = {x:x/2 for x in r...

    Python小技巧