Python 设计模式
for sleek and fashionable code
概述
两天重要原则
- Program to an interface not an implementation
- Favor object composition over inheritacne
鸭子类型Duck Typing
如果该对象的行为像鸭子, 就可以认为是鸭子
鸭子类型出现在动态语言中(dynamic languages
)不具备强类型, 不需要指定类型就可以调用对象的一个存在的方法.
更喜欢对象的组织,而不是继承
如下: 为业务向的代码, 有两种实现方法:
- 直接继承
DBclass
然后重写父类的方法 - 以
object composition
的形式去组织
inheritance.py
class User(Dbclass):
pass
object composition
class User(object):
_persist_methods = ['get', 'save', 'delete']
def __init__(self, persister):
self._persister = persister
def __getattr__(self, attribute):
if attribute in self._persist_methods:
return getattr(self._persister, attribute)
Behavioral Patterns
Behavioral Patterns
为对象之间的交互而生. 根据GOF principles, 有11种
Chain of responsibility, Command, Interpreter, Iterator, Mediator, Memento, Observer, State, Strategy, Template, Visitor.
Iterator
Iterators
是Python的内建模式, 可以通过了解Python iterators, generators
来学习Iterators
Chain of responsibility
Chain of responsibility
举例: 设计一个网页屏蔽器, 具体屏蔽内容有: 广告, 色情内容, 等等, 可以设计如下: 通过ContentFilter
来统一管理和组织不同的过滤器.
class ContentFilter(object):
def __init__(self, filters=None):
self._filters = list()
if filters is not None:
self._filters += filters
def filter(self, content):
for filter in self._filters:
content = filter(content)
return content
filter = ContentFilter([
offensive_filter,
ads_filter,
porno_video_filter])
filtered_content = filter.filter(content)
Command
Command
: 举例: 设计python命令行, 可以如下设计: 定义基本命令类, 然后使用History
封装队列来统一处理
class RenameFileCommand(object):
def __init__(self, from_name, to_name):
self._from = from_name
self._to = to_name
def execute(self):
os.rename(self._from, self._to)
def undo(self):
os.rename(self._to, self._from)
class History(object):
def __init__(self):
self._commands = list()
def execute(self, command):
self._commands.append(command)
command.execute()
def undo(self):
self._commands.pop().undo()
history = History()
history.execute(RenameFileCommand('docs/cv.doc', 'docs/cv-en.doc'))
history.execute(RenameFileCommand('docs/cv1.doc', 'docs/cv-bg.doc'))
history.undo()
history.undo()
Singleton
Singleton
: 保证了给定的类在运行期只有一个实例. 在Python中我们可以修改实例化的进程通过修改 __new__()
, 如cls._logger存在则返回, 不存在则调用__new__
其中 cls._logger
:为类变量
class Logger(object):
def __new__(cls, *args, **kwargs):
if not hasattr(cls, '_logger'):
cls._logger = super(Logger, cls).__new__(cls, *args, **kwargs)
return cls._logger
python 单例模式使用有如下三种:
- 使用一个模块
- 在
top-level
创建app, 或者在config.py
文件中 - 直接传递实例因为,
dependency injection
依赖注入是一种有效的简单控制的机制
facabe
用来暴露一部分API接口, 封装的API接口给客户