📄 sect12.htm
字号:
<font color=#0000ff>def</font> g(self): <font color=#0000ff>return</font> 'spam'
# So m <font color=#0000ff>is</font> synchronized, f <font color=#0000ff>and</font> g are <font color=#0000ff>not</font>.
c = C()
# On the <font color=#0000ff>class</font> level:
<font color=#0000ff>class</font> D(C):
<font color=#0000ff>def</font> __init__(self):
C.__init__(self)
# You must override an un-synchronized method
# <font color=#0000ff>in</font> order to synchronize it (just like Java):
<font color=#0000ff>def</font> f(self): C.f(self)
# Synchronize every (defined) method <font color=#0000ff>in</font> the <font color=#0000ff>class</font>:
synchronize(D)
d = D()
d.f() # Synchronized
d.g() # Not synchronized
d.m() # Synchronized (<font color=#0000ff>in</font> the base <font color=#0000ff>class</font>)
<font color=#0000ff>class</font> E(C):
<font color=#0000ff>def</font> __init__(self):
C.__init__(self)
<font color=#0000ff>def</font> m(self): C.m(self)
<font color=#0000ff>def</font> g(self): C.g(self)
<font color=#0000ff>def</font> f(self): C.f(self)
# Only synchronizes m <font color=#0000ff>and</font> g. Note that m ends up
# being doubly-wrapped <font color=#0000ff>in</font> synchronization, which
# doesn't hurt anything but <font color=#0000ff>is</font> inefficient:
synchronize(E, 'm g')
e = E()
e.f()
e.g()
e.m()
#:~</PRE></FONT></BLOCKQUOTE><DIV ALIGN="LEFT"><P><FONT FACE="Georgia">You must call the base class
constructor for <B>Synchronization</B>, but that’s all. In class <B>C</B>
you can see the use of <B>synchronized( )</B> for <B>m</B>, leaving <B>f</B> and
<B>g</B> alone. Class <B>D</B> has all it’s methods synchronized en masse,
and class <B>E</B> uses the convenience function to synchronize <B>m</B> and
<B>g</B>. Note that since <B>m</B> ends up being synchronized twice, it will be
entered and left twice for every call, which isn’t very desirable [there
may be a fix for this]
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_310">Add Comment</A></FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE>#: util:Observer.py
# Class support <font color=#0000ff>for</font> <font color=#004488>"observer"</font> pattern.
<font color=#0000ff>from</font> Synchronization <font color=#0000ff>import</font> *
<font color=#0000ff>class</font> Observer:
<font color=#0000ff>def</font> update(observable, arg):
'''Called when the observed object <font color=#0000ff>is</font>
modified. You call an Observable object's
notifyObservers method to notify all the
object's observers of the change.'''
<font color=#0000ff>pass</font>
<font color=#0000ff>class</font> Observable(Synchronization):
<font color=#0000ff>def</font> __init__(self):
self.obs = []
self.changed = 0
Synchronization.__init__(self)
<font color=#0000ff>def</font> addObserver(self, observer):
<font color=#0000ff>if</font> observer <font color=#0000ff>not</font> <font color=#0000ff>in</font> self.obs:
self.obs.append(observer)
<font color=#0000ff>def</font> deleteObserver(self, observer):
self.obs.remove(observer)
<font color=#0000ff>def</font> notifyObservers(self, arg = None):
'''If 'changed' indicates that this object
has changed, notify all its observers, then
call clearChanged(). Each observer has its
update() called with two arguments: this
observable object <font color=#0000ff>and</font> the generic 'arg'.'''
self.mutex.acquire()
<font color=#0000ff>try</font>:
<font color=#0000ff>if</font> <font color=#0000ff>not</font> self.changed: <font color=#0000ff>return</font>
# Make a local copy <font color=#0000ff>in</font> case of synchronous
# additions of observers:
localArray = self.obs[:]
self.clearChanged()
<font color=#0000ff>finally</font>:
self.mutex.release()
# Updating <font color=#0000ff>is</font> <font color=#0000ff>not</font> required to be synchronized:
<font color=#0000ff>for</font> observer <font color=#0000ff>in</font> localArray:
observer.update(self, arg)
<font color=#0000ff>def</font> deleteObservers(self): self.obs = []
<font color=#0000ff>def</font> setChanged(self): self.changed = 1
<font color=#0000ff>def</font> clearChanged(self): self.changed = 0
<font color=#0000ff>def</font> hasChanged(self): <font color=#0000ff>return</font> self.changed
<font color=#0000ff>def</font> countObservers(self): <font color=#0000ff>return</font> len(self.obs)
synchronize(Observable,
<font color=#004488>"addObserver deleteObserver deleteObservers "</font> +
<font color=#004488>"setChanged clearChanged hasChanged "</font> +
<font color=#004488>"countObservers"</font>)
#:~</PRE></FONT></BLOCKQUOTE><DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Using this library,
</FONT><FONT FACE="Georgia">here is an example of the observer pattern:
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_311">Add Comment</A></FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE>#: c10:ObservedFlower.py
# Demonstration of <font color=#004488>"observer"</font> pattern.
<font color=#0000ff>import</font> sys
sys.path += ['../util']
<font color=#0000ff>from</font> Observer <font color=#0000ff>import</font> Observer, Observable
<font color=#0000ff>class</font> Flower:
<font color=#0000ff>def</font> __init__(self):
self.isOpen = 0
self.openNotifier = Flower.OpenNotifier(self)
self.closeNotifier= Flower.CloseNotifier(self)
<font color=#0000ff>def</font> open(self): # Opens its petals
self.isOpen = 1
self.openNotifier.notifyObservers()
self.closeNotifier.open()
<font color=#0000ff>def</font> close(self): # Closes its petals
self.isOpen = 0
self.closeNotifier.notifyObservers()
self.openNotifier.close()
<font color=#0000ff>def</font> closing(self): <font color=#0000ff>return</font> self.closeNotifier
<font color=#0000ff>class</font> OpenNotifier(Observable):
<font color=#0000ff>def</font> __init__(self, outer):
Observable.__init__(self)
self.outer = outer
self.alreadyOpen = 0
<font color=#0000ff>def</font> notifyObservers(self):
<font color=#0000ff>if</font> self.outer.isOpen <font color=#0000ff>and</font> \
<font color=#0000ff>not</font> self.alreadyOpen:
self.setChanged()
Observable.notifyObservers(self)
self.alreadyOpen = 1
<font color=#0000ff>def</font> close(self):
self.alreadyOpen = 0
<font color=#0000ff>class</font> CloseNotifier(Observable):
<font color=#0000ff>def</font> __init__(self, outer):
Observable.__init__(self)
self.outer = outer
self.alreadyClosed = 0
<font color=#0000ff>def</font> notifyObservers(self):
<font color=#0000ff>if</font> <font color=#0000ff>not</font> self.outer.isOpen <font color=#0000ff>and</font> \
<font color=#0000ff>not</font> self.alreadyClosed:
self.setChanged()
Observable.notifyObservers(self)
self.alreadyClosed = 1
<font color=#0000ff>def</font> open(self):
alreadyClosed = 0
<font color=#0000ff>class</font> Bee:
<font color=#0000ff>def</font> __init__(self, name):
self.name = name
self.openObserver = Bee.OpenObserver(self)
self.closeObserver = Bee.CloseObserver(self)
# An inner <font color=#0000ff>class</font> <font color=#0000ff>for</font> observing openings:
<font color=#0000ff>class</font> OpenObserver(Observer):
<font color=#0000ff>def</font> __init__(self, outer):
self.outer = outer
<font color=#0000ff>def</font> update(self, observable, arg):
<font color=#0000ff>print</font> <font color=#004488>"Bee "</font> + self.outer.name + \
<font color=#004488>"'s breakfast time!"</font>
# Another inner <font color=#0000ff>class</font> <font color=#0000ff>for</font> closings:
<font color=#0000ff>class</font> CloseObserver(Observer):
<font color=#0000ff>def</font> __init__(self, outer):
self.outer = outer
<font color=#0000ff>def</font> update(self, observable, arg):
<font color=#0000ff>print</font> <font color=#004488>"Bee "</font> + self.outer.name + \
<font color=#004488>"'s bed time!"</font>
<font color=#0000ff>class</font> Hummingbird:
<font color=#0000ff>def</font> __init__(self, name):
self.name = name
self.openObserver = \
Hummingbird.OpenObserver(self)
self.closeObserver = \
Hummingbird.CloseObserver(self)
<font color=#0000ff>class</font> OpenObserver(Observer):
<font color=#0000ff>def</font> __init__(self, outer):
self.outer = outer
<font color=#0000ff>def</font> update(self, observable, arg):
<font color=#0000ff>print</font> <font color=#004488>"Hummingbird "</font> + self.outer.name + \
<font color=#004488>"'s breakfast time!"</font>
<font color=#0000ff>class</font> CloseObserver(Observer):
<font color=#0000ff>def</font> __init__(self, outer):
self.outer = outer
<font color=#0000ff>def</font> update(self, observable, arg):
<font color=#0000ff>print</font> <font color=#004488>"Hummingbird "</font> + self.outer.name + \
<font color=#004488>"'s bed time!"</font>
f = Flower()
ba = Bee(<font color=#004488>"Eric"</font>)
bb = Bee(<font color=#004488>"Eric 0.5"</font>)
ha = Hummingbird(<font color=#004488>"A"</font>)
hb = Hummingbird(<font color=#004488>"B"</font>)
f.openNotifier.addObserver(ha.openObserver)
f.openNotifier.addObserver(hb.openObserver)
f.openNotifier.addObserver(ba.openObserver)
f.openNotifier.addObserver(bb.openObserver)
f.closeNotifier.addObserver(ha.closeObserver)
f.closeNotifier.addObserver(hb.closeObserver)
f.closeNotifier.addObserver(ba.closeObserver)
f.closeNotifier.addObserver(bb.closeObserver)
# Hummingbird 2 decides to sleep <font color=#0000ff>in</font>:
f.openNotifier.deleteObserver(hb.openObserver)
# A change that interests observers:
f.open()
f.open() # It's already open, no change.
# Bee 1 doesn't want to go to bed:
f.closeNotifier.deleteObserver(ba.closeObserver)
f.close()
f.close() # It's already closed; no change
f.openNotifier.deleteObservers()
f.open()
f.close()
#:~</PRE></FONT></BLOCKQUOTE><DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The events of interest are that
a <B>Flower</B> can open or close. Because of the use of the inner class idiom,
both these events can be separately observable phenomena. <B>OpenNotifier</B>
and <B>CloseNotifier</B> both inherit <B>Observable</B>, so they have access to
<B>setChanged( )</B> and can be handed to anything that needs an
<B>Observable</B>.
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_312">Add Comment</A></FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The inner class idiom also comes in handy
to define more than one kind of <B>Observer</B>, in <B>Bee</B> and
<B>Hummingbird</B>, since both those classes may want to independently observe
<B>Flower</B> openings and closings. Notice how the inner class idiom provides
something that has most of the benefits of inheritance (the ability to access
the <B>private</B> data in the outer class, for example) without the same
restrictions.
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_313">Add Comment</A></FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">In <B>main( )</B>, you can see one
of the prime benefits of the observer pattern: the ability to change behavior at
run time by dynamically registering and un-registering <B>Observer</B>s with
<B>Observable</B>s.
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_314">Add Comment</A></FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">If you study the code above you’ll
see that <B>OpenNotifier </B>and <B>CloseNotifier</B> use the basic
<B>Observable</B> interface. This means that you could inherit other completely
different <B>Observer</B> classes; the only connection the <B>Observer</B>s have
with <B>Flower</B>s is the <B>Observer</B> interface.
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_315">Add Comment</A></FONT><A NAME="_Toc462393596"></A><A NAME="_Toc476705915"></A><A NAME="_Toc534420126"></A><BR></P></DIV>
<A NAME="Heading77"></A><FONT FACE = "Verdana, Tahoma, Arial, Helvetica, Sans"><H2 ALIGN="LEFT">
A visual example of observers</H2></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The following example is similar to the
<B>ColorBoxes</B> example from Chapter 14 in <I>Thinking in Java, 2<SUP>nd</SUP>
Edition</I>. Boxes are placed in a grid on the screen and each one is
initialized to a random color. In addition, each box <B>implements</B> the
<A NAME="Index24"></A><B>Observer</B> interface and is registered with an
<B>Observable</B> object. When you click on a box, all of the other boxes are
notified that a change has been made because the <B>Observable</B> object
automatically calls each <B>Observer </B>object’s <B>update( )</B>
method. Inside this method, the box checks to see if it’s adjacent to the
one that was clicked, and if so it changes its color to match the clicked box.
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_316">Add Comment</A></FONT><BR></P></DIV>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -