📄 sect02.htm
字号:
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_34">Add Comment</A></FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Here</FONT><A NAME="fnB5" HREF="#fn5">[5]</A><FONT FACE="Georgia">
is the present list of candidates, only some of which will make it to the final
list. Feel free to suggest others, or possibly relationships with patterns.
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_35">Add Comment</A></FONT><BR></P></DIV>
<UL>
<LI><FONT FACE="Symbol"> </FONT><FONT FACE="Georgia"><B>Encapsulation</B>: self
containment and embodying a model of
usage</FONT><LI><FONT FACE="Symbol"> </FONT><FONT FACE="Georgia"><B>Gathering
</B><A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_36">Add Comment</A></FONT><LI><FONT FACE="Symbol"> </FONT><FONT FACE="Georgia"><B>Localization
</B><A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_37">Add Comment</A></FONT><LI><FONT FACE="Symbol"> </FONT><FONT FACE="Georgia"><B>Separation
</B><A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_38">Add Comment</A></FONT><LI><FONT FACE="Symbol"> </FONT><FONT FACE="Georgia"><B>Hiding
</B><A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_39">Add Comment</A></FONT><LI><FONT FACE="Symbol"> </FONT><FONT FACE="Georgia"><B>Guarding
</B><A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_40">Add Comment</A></FONT><LI><FONT FACE="Symbol"> </FONT><FONT FACE="Georgia"><B>Connector
</B><A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_41">Add Comment</A></FONT><LI><FONT FACE="Symbol"> </FONT><FONT FACE="Georgia"><B>Barrier/fence
</B><A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_42">Add Comment</A></FONT><LI><FONT FACE="Symbol"> </FONT><FONT FACE="Georgia"><B>Variation
in behavior
</B><A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_43">Add Comment</A></FONT><LI><FONT FACE="Symbol"> </FONT><FONT FACE="Georgia"><B>Notification
</B><A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_44">Add Comment</A></FONT><LI><FONT FACE="Symbol"> </FONT><FONT FACE="Georgia"><B>Transaction
</B><A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_45">Add Comment</A></FONT><LI><FONT FACE="Symbol"> </FONT><FONT FACE="Georgia"><B>Mirror</B>:
“the ability to keep a parallel universe(s) in step with the golden
world”
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_46">Add Comment</A></FONT><LI><FONT FACE="Symbol"> </FONT><FONT FACE="Georgia"><B>Shadow</B>
“follows your movement and does something different in a different
medium” (May be a variation on Proxy).
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_47">Add Comment</A></FONT><A NAME="_Toc534420066"></A></UL><A NAME="Heading16"></A><FONT FACE = "Verdana, Tahoma, Arial, Helvetica, Sans"><H2 ALIGN="LEFT">
Design principles</H2></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">When I put out a call for ideas in my
newsletter</FONT><A NAME="fnB6" HREF="#fn6">[6]</A><FONT FACE="Georgia">, a
number of suggestions came back which turned out to be very useful, but
different than the above classification, and I realized that a list of design
principles is at least as important as design structures, but for a different
reason: these allow you to ask questions about your proposed design, to apply
tests for quality.
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_48">Add Comment</A></FONT><BR></P></DIV>
<UL>
<LI><FONT FACE="Symbol"> </FONT><FONT FACE="Georgia"><B>Principle of least
astonishment</B> (don’t be astonishing).
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_49">Add Comment</A></FONT><LI><FONT FACE="Symbol"> </FONT><FONT FACE="Georgia"><B>Make
common things easy, and rare things possible
</B><A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_50">Add Comment</A></FONT><LI><FONT FACE="Symbol"> </FONT><FONT FACE="Georgia"><B>Consistency</B>.
One thing has become very clear to me, especially because of Python: the more
random rules you pile onto the programmer, rules that have nothing to do with
solving the problem at hand, the slower the programmer can produce. And this
does not appear to be a linear factor, but an exponential one.
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_51">Add Comment</A></FONT><LI><FONT FACE="Symbol"> </FONT><FONT FACE="Georgia"><B>Law
of Demeter</B>: a.k.a. “Don’t talk to strangers.” An object
should only reference itself, its attributes, and the arguments of its methods.
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_52">Add Comment</A></FONT><LI><FONT FACE="Symbol"> </FONT><FONT FACE="Georgia"><B>Subtraction</B>:
a design is finished when you cannot take anything else
away</FONT><A NAME="fnB7" HREF="#fn7">[7]</A><FONT FACE="Georgia">.
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_53">Add Comment</A></FONT><LI><FONT FACE="Symbol"> </FONT><FONT FACE="Georgia"><B>Simplicity
before
generality</B></FONT><A NAME="fnB8" HREF="#fn8">[8]</A><FONT FACE="Georgia">. (A
variation of <I>Occam’s Razor</I>, which says “the simplest solution
is the best”). A common problem we find in frameworks is that they are
designed to be general purpose without reference to actual systems. This leads
to a dizzying array of options that are often unused, misused or just not
useful. However, most developers work on specific systems, and the quest for
generality does not always serve them well. The best route to generality is
through understanding well-defined specific examples. So, this principle acts as
the tie breaker between otherwise equally viable design alternatives. Of course,
it is entirely possible that the simpler solution is the more general one.
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_54">Add Comment</A></FONT><LI><FONT FACE="Symbol"> </FONT><FONT FACE="Georgia"><B>Reflexivity</B>
(my suggested term). One abstraction per class, one class per abstraction. Might
also be called <B>Isomorphism</B>.
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_55">Add Comment</A></FONT><LI><FONT FACE="Symbol"> </FONT><FONT FACE="Georgia"><B>Independence</B>
or <B>Orthogonality</B>. Express independent ideas independently. This
complements Separation, Encapsulation and Variation, and is part of the
Low-Coupling-High-Cohesion message.
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_56">Add Comment</A></FONT><LI><FONT FACE="Symbol"> </FONT><FONT FACE="Georgia"><B>Once
and once only</B>: Avoid duplication of logic and structure where the
duplication is not accidental, ie where both pieces of code express the same
intent for the same reason.
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_57">Add Comment</A></FONT></UL><DIV ALIGN="LEFT"><P><FONT FACE="Georgia">In
the process of brainstorming this idea, I hope to come up with a small handful
of fundamental ideas that can be held in your head while you analyze a problem.
However, other ideas that come from this list may end up being useful as a
checklist while walking through and analyzing your design.
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_58">Add Comment</A></FONT><A NAME="_Toc534420067"></A><BR></P></DIV>
<A NAME="Heading17"></A><FONT FACE = "Verdana, Tahoma, Arial, Helvetica, Sans"><H2 ALIGN="LEFT">
The Singleton</H2></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Possibly the simplest design pattern is
the <A NAME="Index11"></A><I>singleton</I>, which is a way to provide one and
only one object of a particular type. To accomplish this, you must take control
of object creation out of the hands of the programmer. One convenient way to do
this is to delegate to a single instance of a private nested inner class:
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_59">Add Comment</A></FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE>#: c01:SingletonPattern.py
<font color=#0000ff>class</font> OnlyOne:
<font color=#0000ff>class</font> __OnlyOne:
<font color=#0000ff>def</font> __init__(self, arg):
self.val = arg
<font color=#0000ff>def</font> __str__(self):
<font color=#0000ff>return</font> ´self´ + self.val
instance = None
<font color=#0000ff>def</font> __init__(self, arg):
<font color=#0000ff>if</font> <font color=#0000ff>not</font> OnlyOne.instance:
OnlyOne.instance = OnlyOne.__OnlyOne(arg)
<font color=#0000ff>else</font>:
OnlyOne.instance.val = arg
<font color=#0000ff>def</font> __getattr__(self, name):
<font color=#0000ff>return</font> getattr(self.instance, name)
x = OnlyOne('sausage')
<font color=#0000ff>print</font> x
y = OnlyOne('eggs')
<font color=#0000ff>print</font> y
z = OnlyOne('spam')
<font color=#0000ff>print</font> z
<font color=#0000ff>print</font> x
<font color=#0000ff>print</font> y
<font color=#0000ff>print</font> ´x´
<font color=#0000ff>print</font> ´y´
<font color=#0000ff>print</font> ´z´
output = '''
<__main__.__OnlyOne instance at 0076B7AC>sausage
<__main__.__OnlyOne instance at 0076B7AC>eggs
<__main__.__OnlyOne instance at 0076B7AC>spam
<__main__.__OnlyOne instance at 0076B7AC>spam
<__main__.__OnlyOne instance at 0076B7AC>spam
<__main__.OnlyOne instance at 0076C54C>
<__main__.OnlyOne instance at 0076DAAC>
<__main__.OnlyOne instance at 0076AA3C>
'''
#:~</PRE></FONT></BLOCKQUOTE><DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Because the inner class is named
with a double underscore, it is private so the user cannot directly access it.
The inner class contains all the methods that you would normally put in the
class if it weren’t going to be a singleton, and then it is wrapped in the
outer class which controls creation by using its constructor. The first time you
create an <B>OnlyOne</B>, it initializes <B>instance</B>, but after that it just
ignores you.
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_60">Add Comment</A></FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Access comes through delegation, using
the <B>__getattr__( )</B> method to redirect calls to the single instance.
You can see from the output that even though it appears that multiple objects
have been created, the same <B>__OnlyOne</B> object is used for both. The
instances of <B>OnlyOne</B> are distinct but they all proxy to the same
<B>__OnlyOne</B> object.
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_61">Add Comment</A></FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Note that the above approach
doesn’t restrict you to creating only one object. This is also a technique
to create a limited pool of objects. In that situation, however, you can be
confronted with the problem of sharing objects in the pool. If this is an issue,
you can create a solution involving a check-out and check-in of the shared
objects.
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_62">Add Comment</A></FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">A variation on this technique uses the
class method <B>__new__</B> added in Python 2.2:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE>#: c01:NewSingleton.py
<font color=#0000ff>class</font> OnlyOne(object):
<font color=#0000ff>class</font> __OnlyOne:
<font color=#0000ff>def</font> __init__(self):
self.val = None
<font color=#0000ff>def</font> __str__(self):
<font color=#0000ff>return</font> ´self´ + self.val
instance = None
<font color=#0000ff>def</font> __new__(cls): # __new__ always a classmethod
<font color=#0000ff>if</font> <font color=#0000ff>not</font> OnlyOne.instance:
OnlyOne.instance = OnlyOne.__OnlyOne()
<font color=#0000ff>return</font> OnlyOne.instance
<font color=#0000ff>def</font> __getattr__(self, name):
<font color=#0000ff>return</font> getattr(self.instance, name)
<font color=#0000ff>def</font> __setattr__(self, name):
<font color=#0000ff>return</font> setattr(self.instance, name)
x = OnlyOne()
x.val = 'sausage'
<font color=#0000ff>print</font> x
y = OnlyOne()
y.val = 'eggs'
<font color=#0000ff>print</font> y
z = OnlyOne()
z.val = 'spam'
<font color=#0000ff>print</font> z
<font color=#0000ff>print</font> x
<font color=#0000ff>print</font> y
#<hr>
output = '''
<__main__.__OnlyOne instance at 0x00798900>sausage
<__main__.__OnlyOne instance at 0x00798900>eggs
<__main__.__OnlyOne instance at 0x00798900>spam
<__main__.__OnlyOne instance at 0x00798900>spam
<__main__.__OnlyOne instance at 0x00798900>spam
'''
#:~</PRE></FONT></BLOCKQUOTE><DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Alex Martelli makes the
<A HREF="http://www.aleax.it/Python/5ep.html">observation</A> that what we
really want with a Singleton is to have a single set of state data for all
objects. That is, you could create as many objects as you want and as long as
they all refer to the same state information then you achieve the effect of
Singleton. He accomplishes this with what he calls the
<I>Borg</I></FONT><A NAME="fnB9" HREF="#fn9">[9]</A><FONT FACE="Georgia">, which
is accomplished by setting all the <B>__dict__</B>s to the same static piece of
storage:
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_63">Add Comment</A></FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE>#: c01:BorgSingleton.py
# Alex Martelli's 'Borg'
<font color=#0000ff>class</font> Borg:
_shared_state = {}
<font color=#0000ff>def</font> __init__(self):
self.__dict__ = self._shared_state
<font color=#0000ff>class</font> Singleton(Borg):
<font color=#0000ff>def</font> __init__(self, arg):
Borg.__init__(self)
self.val = arg
<font color=#0000ff>def</font> __str__(self): <font color=#0000ff>return</font> self.val
x = Singleton('sausage')
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -