@nemos
2017-05-06T02:43:57.000000Z
字数 14768
阅读 806
cs
关于示例代码 由于示例代码大概是从三四个不同的地方收集而来还有部分是我自己写的,所以代码风格不一,敬请谅解。
大部分被收集来的我强行魔改了,删掉了不影响理解的空白和注释尽,可能保持短小和易于理解。
有需求可以看详细代码,当然详细代码和我贴的示例代码不一样是很正常的事情。
ps.如果我有改错代码,欢迎提醒。
上面的所有原则用一句话来概括就是:高内聚低耦合
出自《设计模式解析》
这里只列举了一下,因为内容是一些逻辑性的推导过程,所以详细请参考上书。
模式的层次与不同的组合。
对功能和实现作聚类处理然后拼接。
用于描述类建模的图
矩形表示一个类,包含1.类名 2.类的数据成员 3.类的方法
访问权限::+
公开的 -
私有的 #
受保护的
表示动态关系
对类的各种创建行为进行控制的模式。
说明
建立一个工厂函数,对实现了同一接口的一些类进行实例的创建。
示例代码
详细代码
PS.原来的代码感觉并不好理解,被我改了
class MailSender(object):
def send(self, msg):
print('mail message {msg} sended'.format(msg=msg))
class SmsSender(object):
def send(self, msg):
print('sms message {msg} sended'.format(msg=msg))
def get_sender(sender="mail"): #The factory method
senders = dict(mail=MailSender, sms=SmsSender)
return senders[language]()
m, s = get_senderr(sender="mail"), get_sender(sender="sms")
for msg in "A B".split():
print(m.send(msg), '\n', s.send(msg))
### OUTPUT ###
# mail message A sended
# sms message A sended
# mail message B sended
# sms message B sended
说明
工厂模式中类的创建依赖的工厂方法,一旦想添加一个新类就要修改工厂方法。
在抽象工厂模式中则由工厂提供统一的接口来创建类。
添加一个新类并不需要修改工厂方法。
示例代码
详细代码
class PetShop(object):
def __init__(self, animal_factory=None):
self.pet_factory = animal_factory
def show_pet(self):
pet = self.pet_factory.get_pet()
print(pet.speak)
# Concrete classes
class Dog(object):
def speak(self):
return "woof"
class Cat(object):
def speak(self):
return "meow"
# Factory classes
class DogFactory(object):
def get_pet(self):
return Dog()
class CatFactory(object):
def get_pet(self):
return Cat()
# Create the proper family
def get_factory():
return random.choice([DogFactory, CatFactory])()
# Show pets with various factories
shop = PetShop(get_factory())
shop.show_pet()
### OUTPUT ###
# woof
说明
工厂模式只创建了单个对象,创建者模式用于创建复合对象。
示例代码
详细代码
class Director(object):
def __init__(self):
self.builder = None
def construct_building(self):
self.builder.new_building()
self.builder.build_size()
def get_building(self):
return self.builder.building
# Abstract Builder
class Builder(object):
def __init__(self):
self.building = None
def new_building(self):
self.building = Building()
def build_size(self):
raise NotImplementedError
# Concrete Builder
class BuilderHouse(Builder):
def build_size(self):
self.building.size = 'Big'
# Product
class Building(object):
def __init__(self):
self.size = None
def __repr__(self):
return 'Size: {0.size}'.format(self)
# Client
director = Director()
director.builder = BuilderHouse()
director.construct_building()
building = director.get_building()
print(building)
### OUTPUT ###
# Size: Big
说明
简化复杂而差异较小的对象的创建过程。
示例代码
详细代码
import copy
class Book(object):
def __init__(self, **info):
self.__dict__.update(info)
class Prototype(object):
def __init__(self):
self._objects = dict()
def clone(self, identifier, **attrs):
obj = copy.deepcopy(self._objects[identifier])
obj.__dict__.update(attrs)
return obj
def register(self, identifier, obj):
self._objects[identifier] = obj
### TEST ###
prototype = Prototype()
book_first_edition = Book(name='python', author='somebody', edition='first')
prototype.register('a python book', book_first_edition)
book_second_edition = prototype.clone('a python book', edition='second')
print([{key: value} for key, value in book_first_edition.__dict__.items()])
print([{key: value} for key, value in book_second_edition.__dict__.items()])
### OUTPUT ###
# [{'name': 'python'}, {'edition': 'first'}, {'author': 'somebody'}]
# [{'name': 'python'}, {'edition': 'second'}, {'author': 'somebody'}]
说明
一个只允许实例化一次的类,提供全局的使用接口。
并不建议使用该模式
代码
class Singleton(object):
cer = True
def __new__(cls):
if cls.cer:
cls.cer = False
return super().__new__(cls)
else:
raise
def __del__(self):
self.__class__.cer = True
结构行为是在原有对象的情况下对其进行应用。
说明
将拥有不同接口的对象统一成相同接口的对象。
或者为为接口作适配。
示例代码
详细代码
class Dog(object):
def bark(self):
return "woof!"
class Human(object):
def speak(self):
return "'hello'"
class Car(object):
def make_noise(self, octane_level):
return "vroom{0}".format("!" * octane_level)
class Adapter(object):
def __init__(self, obj, **adapted_methods):
self.obj = obj
self.__dict__.update(adapted_methods)
def __getattr__(self, attr):
return getattr(self.obj, attr)
### TEST ###
objects = []
objects.append(Adapter(Dog(), make_noise=dog.bark))
objects.append(Adapter(Human(), make_noise=human.speak))
objects.append(Adapter(Car(), make_noise=lambda: car.make_noise(3)))
for obj in objects:
print("A {0} goes {1}".format(obj.name, obj.make_noise()))
### OUTPUT ###
# A Dog goes woof!
# A Human goes 'hello'
# A Car goes vroom!!!
说明
即为多个过程给予一个统一的接口。
示例代码
详细代码(这里并没有用到)
class CPU(object):
def startup(self):
print('CPU startup.')
def shutdown(self);
print('CPU shutdown')
class Memory(object):
def startup(self):
print('Memory startup.')
def shutdown(self);
print('Memory shutdown')
class Computrt(object):
def __init__(self):
self.cpu = CPU()
self.memory = Memory()
def startup(self):
self.cpu.startup()
self.memory.startup()
def shutdown(self);
self.cpu.shutdown()
self.memory.shutdown()
### TEST ###
computer = Computer()
computer.startup()
computer.shutdown()
### OUTPUT ###
# CPU startup.
# Memory startup.
# CPU shutdown
# Memory shutdown
说明
可以给对象动态的增加一些功能,装饰对象与原对象接口不变且装饰对象持有原对象的实例。
python内置的@关键字实现了本模式,以下代码仅作通用性的示范。
示例代码
详细代码
class TextTag(object):
def __init__(self, text):
self._text = text
def render(self):
return self._text
class BoldWrapper(object):
def __init__(self, wrapped):
self._wrapped = wrapped
def render(self):
return "<b>{}</b>".format(self._wrapped.render())
### TEST ###
simple_hello = TextTag("hello, world!")
special_hello = BoldWrapper(simple_hello)
print("before:", simple_hello.render())
print("after:", special_hello.render())
### OUTPUT ###
# before: hello, world!
# after: <b>hello, world!</b>
说明
对原有方法行为进行控制,而不修改方法本身。
注意本模式跟装饰器模式区别,装饰器是动态的,而代理是静态的。
装饰器一般会包裹整个类而保留相同接口。
而代理可以部分包裹类。
示例代码
详细代码
class SalesManager(object):
def talk(self):
print("Sales Manager ready to talk")
class Proxy(object):
def __init__(self):
self.busy = 'No'
self.sales = None
def talk(self):
print("Proxy checking for Sales Manager availability")
if self.busy == 'No':
self.sales = SalesManager()
self.sales.talk()
else:
print("Sales Manager is busy")
### TEST ###
p = Proxy()
p.talk()
p.busy = 'Yes'
p.talk()
### OUTPUT ###
# Proxy checking for Sales Manager availability
# Sales Manager ready to talk
# Proxy checking for Sales Manager availability
# Sales Manager is busy
说明
处理树状结构的对象关联,如gui中各种窗口组件。
示例代码
详细代码
原代码太长了,这里做了大量简化处理。
class Node(object):
next_node = []
def __init__(self, name):
self.name = name
def add_node(self, node):
self.append(node)
### TEST ###
window = Node('window')
frame1 = Node('frame1')
frame2 = Node('frame2')
window.add_node(frame1)
window.add_node(frame2)
说明
利用对象池实现了对象之间的共享,在大量创建对象的情况下可以节约内存。
示例代码
详细代码
一片森林有多颗树,但是树种类相同。
class Tree:
pool = dict()
def __new__(cls, tree_type):
obj = cls.pool.get(tree_type, None)
if not obj:
obj = object.__new__(cls)
cls.pool[tree_type] = obj
obj.tree_type = tree_type
return obj
def show(self, x, y):
print('a {type} tree in ({x}, {y})'.format(type=self.tree_type, x=x, y=y))
### TEST ###
tree = Tree('apple_tree')
[tree.show(randint(0, 100), randint(0, 100)) for _ in range(10)]
### OUTPUT ###
# a apple_tree tree in (32, 57)
# a apple_tree tree in (39, 57)
# a apple_tree tree in (86, 38)
说明
将抽象与实现解耦,使得二者可以独立变化
示例代码
详细代码
class DrawingAPI1(object):
def draw(self):
print('API1 Drawing')
class DrawingAPI2(object):
def draw(self):
print('API2 Drawing')
class Shape(object):
def __init__(self,drawing_api):
self._drawing_api = drawing_api
def draw(self):
self._drawing_api.draw()
### TEST ###
shapes = (
CircleShape(DrawingAPI1()),
CircleShape(DrawingAPI2())
)
for shape in shapes:
shape.draw()
### OUTPUT ###
# API1 Drawing
# API2 Drawing
行为模式涉及了对象与算法间的分配关系。
说明
将算法的选择与实现分离。
示例代码
详细代码
import types
class Strategy(object):
def __init__(self, calculator=None):
self.name = 'Strategy 0'
if func is not None:
self.execute = types.MethodType(calculator, self) #绑定方法
def execute(self):
print(self.name)
def do_calculator1(self):
print(self.name, 'do calculator1')
def do_calculator2(self):
print(self.name, 'do calculator2')
### TEST ###
strat = Strategy(do_calculator1)
strat.execute()
### OUTPUT ###
# Strategy 0 do calculator1
说明
消除冗余,对算法的部分进行定制处理。
示例代码
详细代码
ingredients = "spam eggs apple"
line = '-' * 10
# Skeletons
def iter_elements(getter, action):
for element in getter():
action(element)
print(line)
def rev_elements(getter, action):
for element in getter()[::-1]:
action(element)
print(line)
# Getters
def get_list():
return ingredients.split()
def get_lists():
return [list(x) for x in ingredients.split()]
# Actions
def print_item(item):
print(item)
def reverse_item(item):
print(item[::-1])
# Makes templates
def make_template(skeleton, getter, action):
def template():
skeleton(getter, action)
return template
# Create our template functions
templates = [make_template(s, g, a)
for g in (get_list, get_lists)
for a in (print_item, reverse_item)
for s in (iter_elements, rev_elements)]
# Execute them
for template in templates:
template()
### OUTPUT ###
# spam
# ----------
# eggs
# ----------
# apple
# ----------
# apple
# ----------
# eggs
# ----------
# spam
# ----------
# maps
# ----------
# sgge
# ----------
# elppa
# ----------
# elppa
# ----------
# sgge
# ----------
# maps
# ----------
# ['s', 'p', 'a', 'm']
# ----------
# ['e', 'g', 'g', 's']
# ----------
# ['a', 'p', 'p', 'l', 'e']
# ----------
# ['a', 'p', 'p', 'l', 'e']
# ----------
# ['e', 'g', 'g', 's']
# ----------
# ['s', 'p', 'a', 'm']
# ----------
# ['m', 'a', 'p', 's']
# ----------
# ['s', 'g', 'g', 'e']
# ----------
# ['e', 'l', 'p', 'p', 'a']
# ----------
# ['e', 'l', 'p', 'p', 'a']
# ----------
# ['s', 'g', 'g', 'e']
# ----------
# ['m', 'a', 'p', 's']
# ----------
说明
用于消息传递的模型,每一个节点持有下一个的应用然后将一个事件沿着链一直传递下去,直到事件被处理。
示例代码
其他参考代码
详细代码
class Event(object):
def __init__(self, name):
self.name = name
def __str__(self):
return self.name
class Widget(object):
def __init__(self, parent=None):
self.parent = parent
def handler(self, event):
if not self._handle(event):
self.parent.handler(event)
def _handle(self, event):
raise NotImplementedError
class MainWindow(Widget):
def _handle(self, event):
if 'a' in str(event):
print('MainWindow handled event {}'.format(event))
return True
else:
print('in MainWindow event {} passed py'.format(event))
return False
class SendDialog(Widget):
def _handle(self, event):
if 'b' in str(event):
print('SendDialog handled event {}'.format(event))
return True
else:
print('in SendDialog event {} passed py'.format(event))
return False
class MsgText(Widget):
def _handle(self, event):
if 'c' in str(event):
print('MsgText handled event {}'.format(event))
return True
else:
print('in MsgText event {} passed py'.format(event))
return False
class Out(Widget):
def _handle(self, event):
print('event {} has no hander'.format(event))
return True
### TEST ###
mw = MainWindow(Out())
sd = SendDialog(mw)
msg = MsgText(sd)
for e in 'bd':
evt = Event(e)
msg.handler(evt)
### OUTPUT ###
# in MsgText event b passed py
# SendDialog handled event b
# in MsgText event d passed py
# in SendDialog event d passed py
# in MainWindow event d passed py
# event d has no hander
说明
比较容易理解的是文本编辑器中撤销操作的实现,即将操作封装成一个对象。然后维护一个命令的队列。
示例代码
详细代码
import os
from os.path import lexists
class MoveFileCommand(object):
def __init__(self, src, dest):
self.src = src
self.dest = dest
def execute(self):
self.rename(self.src, self.dest)
def undo(self):
self.rename(self.dest, self.src)
def rename(self, src, dest):
print('renaming {} to {}'.format(src, dest))
os.rename(src, dest)
### TEST ###
command_stack = []
command_stack.append(MoveFileCommand('foo.txt', 'bar.txt'))
command_stack.append(MoveFileCommand('bar.txt', 'baz.txt'))
for cmd in command_stack:
cmd.execute()
for cmd in reversed(command_stack):
cmd.undo()
### OUTPUT ###
# renaming foo.txt to bar.txt
# renaming bar.txt to baz.txt
# renaming baz.txt to bar.txt
# renaming bar.txt to foo.txt
说明
其实叫备份模式比较好理解。
即对对象的状态进行备份和存储以使对象在需要的时刻可以恢复到之前的状态。
如实现一个回滚的操作。
示例代码
详细代码
这里用到了一点动态语言闭包的小技巧。
from copy import deepcopy
class Memento(object):
def __init__(self, obj):
state = deepcopy(obj.__dict__)
def rollback():
obj.__dict__.clear()
obj.__dict__.update(state)
self.rollback = rollback
class Forgettable(object):
def __init__(self, value):
self.value = value
def __str__(self):
return self.value
def commit(self):
self.memo = Memento(self)
def rollback(self):
self.memo.rollback()
### TEST ###
forget_it = Forgettable('something you cant forget')
forget_it.commit()
print(forget_it)
forget_it.value = 'I forgot it'
print(forget_it)
forget_it.rollback()
print(forget_it)
### OUTPUT ###
# something you cant forget
# I forgot it
# something you cant forget
说明
当对象的状态改变时同时改变其行为。
示例代码
详细代码
class State(object):
def scan(self):
self.pos += 1
print("Scanning... Station is", self.stations[self.pos], self.name)
class AmState(State):
def __init__(self, radio):
self.radio = radio
self.stations = ["1250", "1380", "1510"]
self.pos = 0
self.name = "AM"
def toggle_amfm(self):
print("Switching to FM")
self.radio.state = self.radio.fmstate
class FmState(State):
def __init__(self, radio):
self.radio = radio
self.stations = ["81.3", "89.1", "103.9"]
self.pos = 0
self.name = "FM"
def toggle_amfm(self):
print("Switching to AM")
self.radio.state = self.radio.amstate
class Radio(object):
def __init__(self):
self.amstate = AmState(self)
self.fmstate = FmState(self)
self.state = self.amstate
def toggle_amfm(self):
self.state.toggle_amfm()
def scan(self):
self.state.scan()
### TEST ###
radio = Radio()
radio.scan()
radio.toggle_amfm()
radio.scan()
### OUTPUT ###
# Scanning... Station is 1380 AM
# Switching to FM
# Scanning... Station is 89.1 FM
说明
将数据结构及其操作解耦,用于数据结构稳定但其算法多变的系统。
示例代码
详细代码
这个例子并不是特别好理解。类的mro是固定的结构,使用visit方法对树进行遍历,如果visitor中有处理相应节点的方法则调用。
class Node(object):
pass
class A(Node):
pass
class B(Node):
pass
class C(A, B):
pass
class Visitor(object):
def visit(self, node, *args, **kwargs):
meth = None
for cls in node.__class__.__mro__:
meth_name = 'visit_' + cls.__name__
meth = getattr(self, meth_name, None)
if meth:
break
if not meth:
meth = self.generic_visit
return meth(node, *args, **kwargs)
def generic_visit(self, node, *args, **kwargs):
print('generic_visit ' + node.__class__.__name__)
def visit_B(self, node, *args, **kwargs):
print('visit_B ' + node.__class__.__name__)
### TEST ###
a = A()
b = B()
c = C()
visitor = Visitor()
visitor.visit(a)
visitor.visit(b)
visitor.visit(c)
### OUTPUT ###
# generic_visit A
# visit_B B
# visit_B C
说明
解决类与类之间的依赖关系中间加一层mediator来解耦。
即类与类之间存在依赖关系时通过来mediator来共享关系。
示例代码
详细代码
class Worker(object):
def __init__(self, mediator):
self.mediator = mediator
class Worker1(Work):
def work()
def work_with_work2():
self.mediator.work2
class Worker2(Work):
def work():
def work_with_work1():
self.mediator.work1
class Mediator(object):
def __init__(self):
self.worker1 = Worker1(self)
self.worker2 = Worker2(self)
def work();
self.worker1.work()
self.worker2.work()
说明
当对象变化时其依赖的对象都会收到通知并随之变化
示例代码
详细代码
class Subject(object):
def __init__(self):
self._observers = []
def attach(self, observer):
self._observers.append(observer)
def detach(self, observer):
self._observers.remove(observer)
def notify(self):
for observer in self._observers:
observer.update(self)
class MySubject(Subject):
def __init__(self, name=''):
super().__init__(self)
self.name = name
def subject_changed(self):
self.notify()
class Viewer1:
def update(self, subject):
print('Viewer1: Subject %s changed' % (subject.name,))
class Viewer2:
def update(self, subject):
print('Viewer2: Subject %s changed' % (subject.name,))
### TEST ###
subject1 = MySubject('MySubject')
view1 = Viewer1()
view2 = Viewer2()
subject1.attach(view1)
subject1.attach(view2)
subject1.subject_changed()
### OUTPUT ###
# Viewer1: Viewer2: Subject Mysubject changed
# Viewer2: Viewer2: Subject Mysubject changed
design-patterns-for-humans
《设计模式解析》
cnblog设计模式
python示例代码来源
精通Python设计模式(这书挺烂的,并不建议看,拿了一部分源码参考)