<<TableOfContents>> ## 请删除此页面 = 设计模式 = == 介绍 == == 创建型模式 == === 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(代理) === ==== 意图 ==== 为其他对象提供一种代理以控制对这个对象的访问。<<BR>> {{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对消息的处理:<<BR>> {{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(解释器) === ==== 意图 ==== 给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示 来解释语言中的句子。