>
## 请删除此页面
= 设计模式 =
== 介绍 ==
== 创建型模式 ==
=== singleton(单件) ===
==== 意图 ====
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
==== 经典应用 ====
MFC中的App类,一般程序中用到的全局变量。
==== 实现代码 ====
{{{
#!python
class Singleton:
""" A python singleton """
class __impl:
""" Implementation of the singleton interface """
def spam(self):
""" Test method, return singleton id """
return id(self)
# storage for the instance reference
__instance = None
def __init__(self):
""" Create singleton instance """
# Check whether we already have an instance
if Singleton.__instance is None:
# Create and remember instance
Singleton.__instance = Singleton.__impl()
# Store instance reference as the only member in the handle
self.__dict__['_Singleton__instance'] = Singleton.__instance
def __getattr__(self, attr):
""" Delegate access to implementation """
return getattr(self.__instance, attr)
def __setattr__(self, attr, value):
""" Delegate access to implementation """
return setattr(self.__instance, attr, value)
# Test it
s1 = Singleton()
print id(s1), s1.spam()
s2 = Singleton()
print id(s2), s2.spam()
# Sample output, the second (inner) id is constant:
# 8172684 8176268
# 8168588 8176268
}}}
==== 另一个实现代码 ====
从[[http://members.chello.nl/f.niessink/|TaskCoach]]的代码中摘抄,因此许可证为GPL。
-- QiangningHong
{{{
#!python
class Singleton(type):
"""Singleton Metaclass"""
def __init__(cls, name, bases, dic):
super(Singleton, cls).__init__(name, bases, dic)
cls.instance = None
def __call__(cls, *args, **kwargs):
if cls.instance is None:
cls.instance = super(Singleton, cls).__call__(*args, **kwargs)
return cls.instance
}}}
使用方法:
{{{
#!python
class MyClass(object):
__metaclass__ = Singleton
ob1 = MyClass()
ob2 = MyClass()
assert ob1 is ob2
}}}
== 结构型模式 ==
=== Proxy(代理) ===
==== 意图 ====
为其他对象提供一种代理以控制对这个对象的访问。<
>
{{attachment:ProxyPattern.gif}}
==== 代码 ====
{{{
#!python
class Proxy:
def __init__( self, subject ):
self.__subject = subject
def __getattr__( self, name ):
return getattr( self.__subject, name )
}}}
==== 例子 ====
{{{
#!python
class RGB:
def __init__( self, red, green, blue ):
self.__red = red
self.__green = green
self.__blue = blue
def Red( self ):
return self.__red
def Green( self ):
return self.__green
def Blue( self ):
return self.__blue
}}}
使用Proxy改变Blue函数:
{{{
#!python
class NoBlueProxy( Proxy ):
def Blue( self ):
return 0
}}}
使用:
>>> rgb = RGB( 100, 192, 240 )
>>> rgb.Red()
100
>>> proxy = Proxy( rgb )
>>> proxy.Green()
192
>>> noblue = NoBlueProxy( rgb )
>>> noblue.Green()
192
>>> noblue.Blue()
0
}}}
使用:
>>> rgb = RGB( 100, 192, 240 )
>>> rgb.Red()
100
>>> proxy = Proxy( rgb )
>>> proxy.Green()
192
>>> noblue = NoBlueProxy( rgb )
>>> noblue.Green()
192
>>> noblue.Blue()
0
==== 特殊说明 ====
* 因为在Proxy中没有__setattr__函数,因此只可以得到rgb中的值,但不能改变,比如可以"r = noblue._RBG__red",但不能写"noblue._RBG__red = 255",如果要想改变RBG中的值,只有在RBG中定义一些函数如"setBlue...",在noblue中直接调用。
* 在Proxy中也不能定义__setattr__,否则在__init__中会发生死循环。
=== flyweight ===
==== 意图 ====
运用共享技术有效地支持大量细粒度的对象。
==== 实现代码 ====
{{{
#!python
#实现过程类似于singleton模式
import weakref
#weekref产生的value不能保持对象存在。当对象不包括weakref在内的引用计数达到0时,对象将被删除。
class Instrument(object):
_InstrumentPool = weakref.WeakValueDictionary()
def __new__(cls, name):
'''Instrument(name)
Create a new instrument object, or return an existing one'''
obj = Instrument._InstrumentPool.get(name, None)
if not obj:
print "new",name
obj = object.__new__(cls)
Instrument._InstrumentPool[name] = obj
return obj
def __init__(self, name):
'''Complete object construction'''
self.name = name
print "New instrument @%04x, %s" % (id(self), name)
# ... connect instrument to datasource ...
#测试
import unittest
class InstrumentTests(unittest.TestCase):
def testInstrument(self):
ibm1 = Instrument("IBM")
ms = Instrument("MS")
ibm2 = Instrument("IBM")
self.assertEquals(id(ibm1), id(ibm2))
self.assertNotEquals(id(ibm1), id(ms))
self.assertEquals(2, len(Instrument._InstrumentPool),
"Total instruments allocated")
# This bit assumes CPython memory allocation:
del(ibm1)
del(ibm2)
# 每一次调用Instrument,因其函数__new__中的Instrument._InstrumentPool[name]是weakref,只有obj = object.__new__(cls)引用一次。所以del(ibm1)和del(imb2)后引用计数达到0,对象被清理。
self.assertEquals(1, len(Instrument._InstrumentPool),
"Total instruments allocated")
if __name__=='__main__':
unittest.main()
}}}
== 行为模式 ==
=== Chain of Responsibility(职责链) ===
==== 意图 ====
使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。
==== 说明 ====
用一系列类(classes)试图处理一个请求request,这些类之间是一个松散的耦合,唯一共同点是在他们之间传递request. 也就是说,来了一个请求,A类先处理,如果没有处理,就传递到B类处理,如果没有处理,就传递到C类处理,就这样象一个链条(chain)一样传递下去。
例如,窗口UI对消息的处理:<
>
{{attachment:CORPattern.gif}}
==== 代码实现 ====
模拟UI对消息的处理
{{{
#!python
class Event:
def __init__( self, name ):
self.name = name
class Widget:
def __init__( self, parent = None ):
self.__parent = parent
def Handle( self, event ):
handler = 'Handle_' + event.name
if hasattr( self, handler ):
method = getattr( self, handler )
method( event )
elif self.__parent:
self.__parent.Handle( event )
elif hasattr( self, 'HandleDefault' ):
self.HandleDefault( event )
}}}
使用:
当用一个event被Handle,将调用Handle_"event.name",如果没有此函数就调用parent来处理此event,如果还没有被处理,就试着交给HandleDefault()。
例如:
{{{
#!python
class MainWindow(Widget):
def Handle_close( self, event ):
print 'MainWindow: ' + event.name
def HandleDefault( self, event ):
print 'Default: ' + event.name
class Button( Widget ):
def Handle_click( self, event ):
print 'Button: ' + event.name
}}}
=== Observer(观察者) ===
==== 意图 ====
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
==== 经典应用 ====
MFC中document类对所有view的更新,ddx/ddv对窗口上控件的更新。
==== 代码实现 ====
{{{
#!python
class Subject:
def __init__(self):
self._observers = []
def attach(self, observer):
if not observer in self._observers:
self._observers.append(observer)
def detach(self, observer):
try:
self._observers.remove(observer)
except ValueError:
pass
def notify(self, modifier=None):
for observer in self._observers:
if modifier != observer:
observer.update(self)
}}}
==== 例子,用法 ====
{{{
#!python
# Example usage
class Data(Subject):
def __init__(self, name=''):
Subject.__init__(self)
self.name = name
self.data = 0
def setData(self, data):
self.data = data
self.notify()
def getData(self):
return self.data
class HexViewer:
def update(self, subject):
print 'HexViewer: Subject %s has data 0x%x' % (subject.name, subject.getData())
class DecimalViewer:
def update(self, subject):
print 'DecimalViewer: Subject %s has data %d' % (subject.name, subject.getData())
# Example usage...
def main():
data1 = Data('Data 1')
data2 = Data('Data 2')
view1 = DecimalViewer()
view2 = HexViewer()
data1.attach(view1)
data1.attach(view2)
data2.attach(view2)
data2.attach(view1)
print "Setting Data 1 = 10"
data1.setData(10)
print "Setting Data 2 = 15"
data2.setData(15)
print "Setting Data 1 = 3"
data1.setData(3)
print "Setting Data 2 = 5"
data2.setData(5)
print "Detach HexViewer from data1 and data2."
data1.detach(view2)
data2.detach(view2)
print "Setting Data 1 = 10"
data1.setData(10)
print "Setting Data 2 = 15"
data2.setData(15)
}}}
=== Template Method(模板方法) ===
==== 意图 ====
定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。
==== 实现代码 ====
{{{
#!python
class Base:
def doAll(self):
self.doThis()
self.doThat()
class Foo(Base):
def doThis(self):
print "do this"
def doThat(self):
print "do that"
#测试
Foo a
a.doAll()
#输出
#do this
#do that
}}}
=== Visitor(访问者) ===
==== 意图 ====
作用于某个对象群中各个对象的操作. 它可以使你在不改变这些对象本身的情况下,定义作用于这些对象的新操作.
==== 实现代码 ====
{{{
#!python
class Visitor:
def __init__(self):
self._methodDic={}
def default(self, other):
print "What's this:", other
def addMethod(self, method):
self._methodDic[method.getKey()]=method
def __call__(self, other):
method=self._methodDic.get(\
other.__class__.__name__,self.default)
return method(other)
}}}
==== 用法、例子 ====
在MyVisit的函数__call__中定义对target的具体访问操作。
{{{
#!python
class MyVisit:
"""
Instead of deriving from Visitor the work is
done by instances with this interface.
"""
def __init__(self, otherClass):
self._msg='Visit: %s'%otherClass.__name__
self._key=otherClass.__name__
def __call__(self, target):
print self._msg, target
def getKey(self):
return self._key
# 被访问者
class E1:pass
class E2:pass
class E3:pass
# 用法
collection=[E1(), E1(), E2(), E3()]
visitor=Visitor()
visitor.addMethod(MyVisit(E1))
visitor.addMethod(MyVisit(E2))
map(visitor, collection)
}}}
###########################
输出:
Visit: E1 <__main__.E1 instance at 7ff6d0>
Visit: E1 <__main__.E1 instance at 7ff730>
Visit: E2 <__main__.E2 instance at 7ff780>
What's this: <__main__.E3 instance at 7ff7b0>
# 简化用法
{{{
#!python
visitor = Visitor()
visitor.addMethod(MyVisit(E1))
a = E1()
visitor(a)
}}}
#########################
输出:
Visit: E1 <__main__.E1 instance at 0x00A91EE0>
=== Command(命令) ===
==== 意图 ====
将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤消的操作。在python中叫“Command Dispatch Pattern”,也不需要将请求封装成对象,直接用字符串作命令请求。
==== 实现代码 ====
{{{
#!python
class Dispatcher:
def do_get(self):
print("do_get")
def do_put(self):
print("d0_put")
def error(self):
print("error")
def dispatch(self, command):
mname = 'do_' + command
if hasattr(self, mname):
method = getattr(self, mname)
method()
else:
self.error()
}}}
==== 用法 ====
{{{
#!python
Dispatcher a
a.dispatch("get")
a.dispatch("put")
}}}
=== state(代理) ===
==== 意图 ====
允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。
==== 实现代码 ====
{{{
#!python
class NetworkCardState:
"""Abstract State Object"""
def send(self):
raise "NetworkCardState.send - not overwritten"
def receive(self):
raise "NetworkCardState.receive - not overwritten"
class Online(NetworkCardState):
"""Online state for NetworkCard"""
def send(self):
print "sending Data"
def receive(self):
print "receiving Data"
class Offline(NetworkCardState):
"""Offline state for NetworkCard"""
def send(self):
print "cannot send...Offline"
def receive(self):
print "cannot receive...Offline"
class NetworkCard:
def __init__(self):
self.online = Online()
self.offline = Offline()
##default state is Offline
self.currentState = self.offline
def startConnection(self):
self.currentState = self.online
def stopConnection(self):
self.currentState = self.offline
def send(self):
self.currentState.send()
def receive(self):
self.currentState.receive()
def main():
myNetworkCard = NetworkCard()
print "without connection:"
myNetworkCard.send()
myNetworkCard.receive()
print "starting connection"
myNetworkCard.startConnection()
myNetworkCard.send()
myNetworkCard.receive()
if __name__ == '__main__':
main()
}}}
=== interpreter(解释器) ===
==== 意图 ====
给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示
来解释语言中的句子。