📄 sect14.htm
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<!--
This document was converted from RTF source:
By rtftohtml 4.19
See http://www.sunpack.com/RTF
Filename:TIPython.rtf
Application Directory:c:\tools\rtf2html\
Subject:
Author:Bruce Eckel
Operator:Bruce Eckel
Document Comments:
Version Comments:
Comments:
Keywords:
Translation Date:12/31/2001
Translation Time:08:24:14
Translation Platform:Win32
Number of Output files:18
This File:Sect14.htm
SplitDepth=1
SkipNavPanel=1
SkipLeadingToc=1
SkipTrailingToc=1
GenContents=1
GenFrames=1
GenIndex=1
-->
<HEAD lang="en"><META http-equiv="Content-Type" content="text/html">
<TITLE>12: Pattern refactoring</TITLE>
<script language="JavaScript">
</script>
</head>
<BODY BGCOLOR="#FFFFFF"><DIV ALIGN="CENTER">
<a href="http://www.MindView.net">
<img src="mindview.gif" alt="MindView Inc." BORDER = "0"></a>
<CENTER>
<FONT FACE="Verdana, Tahoma, Arial, Helvetica, Sans" size = "-1">
<!-- [ <a href="README.txt">Viewing Hints</a> ]
[ <a href="RevisionHistory.htm">Revision History</a> ] -->
[ <a href="http://www.mindview.net/Books/TIPython/">Book Home Page</a> ]
[ <a href="http://www.mindview.net/Etc/MailingList.html">Free Newsletter</a> ] <br>
[ <a href="http://www.mindview.net/Seminars">Seminars</a> ]
[ <a href="http://www.mindview.net/CDs">Seminars on CD ROM</a> ]
[ <a href="http://www.mindview.net/Services">Consulting</a> ]
</FONT>
<H2><FONT FACE="Verdana, Tahoma, Arial, Helvetica, Sans">
Thinking in Python<br>
<small>Revision 0.1.2 (12/31/01) -- Incomplete and Unfinished</small></FONT></H2>
<H3><FONT FACE="Verdana, Tahoma, Arial, Helvetica, Sans">
by Bruce Eckel ©2002 MindView, Inc.</FONT></H3>
<FONT FACE="Verdana, Tahoma, Arial, Helvetica, Sans" size = "-1">
[ <a href="Sect13.htm">Previous Chapter</a> ]
[ <a href="javascript:window.location.href = 'Index.htm';">Table of Contents</a> ]
[ <a href="DocIdx.htm">Index</a> ]
[ <a href="Sect15.htm">Next Chapter</a> ]
</FONT>
</CENTER>
</P></DIV><A NAME="_Toc476705918"></A><A NAME="_Toc534420131"></A><A NAME="Heading82"></A><FONT FACE = "Verdana, Tahoma, Arial, Helvetica, Sans"><H1 ALIGN="LEFT">
12: Pattern refactoring</H1></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia" SIZE=4 COLOR="Red">This chapter has not
had any significant translation yet.
</FONT><FONT FACE="Georgia" SIZE=4><A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_336">Add Comment</A></FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">This chapter will look at the process of
solving a problem by applying design patterns in an evolutionary fashion. That
is, a first cut design will be used for the initial solution, and then this
solution will be examined and various design patterns will be applied to the
problem (some of which will work, and some of which won’t). The key
question that will always be asked in seeking improved solutions is “what
will change?”
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_337">Add Comment</A></FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">This process is similar to what Martin
Fowler talks about in his book <I>Refactoring: Improving the Design of Existing
Code</I></FONT><A NAME="fnB16" HREF="#fn16">[16]</A><FONT FACE="Georgia">
(although he tends to talk about pieces of code more than pattern-level
designs). You start with a solution, and then when you discover that it
doesn’t continue to meet your needs, you fix it. Of course, this is a
natural tendency but in computer programming it’s been extremely difficult
to accomplish with procedural programs, and the acceptance of the idea that we
<I>can</I> refactor code and designs adds to the body of proof that
object-oriented programming is “a good thing.”
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_338">Add Comment</A></FONT><A NAME="_Toc476705919"></A><A NAME="_Toc534420132"></A><BR></P></DIV>
<A NAME="Heading83"></A><FONT FACE = "Verdana, Tahoma, Arial, Helvetica, Sans"><H2 ALIGN="LEFT">
Simulating the trash recycler</H2></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The nature of this problem is that the
trash is thrown unclassified into a single bin, so the specific type information
is lost. But later, the specific type information must be recovered to properly
sort the trash. In the initial solution, RTTI (described in Chapter 12 of
<I>Thinking in Java, 2<SUP>nd</SUP> edition</I>) is used.
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_339">Add Comment</A></FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">This is not a trivial design because it
has an added constraint. That’s what makes it interesting—it’s
more like the messy problems you’re likely to encounter in your work. The
extra constraint is that the trash arrives at the trash recycling plant all
mixed together. The program must model the sorting of that trash. This is where
RTTI comes in: you have a bunch of anonymous pieces of trash, and the program
figures out exactly what type they are.
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_340">Add Comment</A></FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE># c12:recyclea:RecycleA.py
# Recycling with RTTI.
<font color=#0000ff>class</font> Trash:
private double weight
<font color=#0000ff>def</font> __init__(self, double wt): weight = wt
abstract double getValue()
double getWeight(): <font color=#0000ff>return</font> weight
# Sums the value of Trash <font color=#0000ff>in</font> a bin:
static void sumValue(Iterator it):
double val = 0.0f
<font color=#0000ff>while</font>(it.hasNext()):
# One kind of RTTI:
# A dynamically-checked cast
Trash t = (Trash)it.next()
# Polymorphism <font color=#0000ff>in</font> action:
val += t.getWeight() * t.getValue()
<font color=#0000ff>print</font> (
<font color=#004488>"weight of "</font> +
# Using RTTI to get type
# information about the <font color=#0000ff>class</font>:
t.getClass().getName() +
<font color=#004488>" = "</font> + t.getWeight())
<font color=#0000ff>print</font> <font color=#004488>"Total value = "</font> + val
<font color=#0000ff>class</font> Aluminum(Trash):
static double val = 1.67f
<font color=#0000ff>def</font> __init__(self, double wt): .__init__(wt)
double getValue(): <font color=#0000ff>return</font> val
static void setValue(double newval):
val = newval
<font color=#0000ff>class</font> Paper(Trash):
static double val = 0.10f
<font color=#0000ff>def</font> __init__(self, double wt): .__init__(wt)
double getValue(): <font color=#0000ff>return</font> val
static void setValue(double newval):
val = newval
<font color=#0000ff>class</font> Glass(Trash):
static double val = 0.23f
<font color=#0000ff>def</font> __init__(self, double wt): .__init__(wt)
double getValue(): <font color=#0000ff>return</font> val
static void setValue(double newval):
val = newval
<font color=#0000ff>class</font> RecycleA(UnitTest):
Collection
bin = ArrayList(),
glassBin = ArrayList(),
paperBin = ArrayList(),
alBin = ArrayList()
<font color=#0000ff>def</font> __init__(self):
# Fill up the Trash bin:
<font color=#0000ff>for</font>(int i = 0 i < 30 i++)
switch((int)(Math.random() * 3)):
case 0 :
bin.add(new
Aluminum(Math.random() * 100))
<font color=#0000ff>break</font>
case 1 :
bin.add(new
Paper(Math.random() * 100))
<font color=#0000ff>break</font>
case 2 :
bin.add(new
Glass(Math.random() * 100))
<font color=#0000ff>def</font> test(self):
Iterator sorter = bin.iterator()
# Sort the Trash:
<font color=#0000ff>while</font>(sorter.hasNext()):
Object t = sorter.next()
# RTTI to show <font color=#0000ff>class</font> membership:
<font color=#0000ff>if</font>(t instanceof Aluminum)
alBin.add(t)
<font color=#0000ff>if</font>(t instanceof Paper)
paperBin.add(t)
<font color=#0000ff>if</font>(t instanceof Glass)
glassBin.add(t)
Trash.sumValue(alBin.iterator())
Trash.sumValue(paperBin.iterator())
Trash.sumValue(glassBin.iterator())
Trash.sumValue(bin.iterator())
<font color=#0000ff>def</font> main(self, String args[]):
RecycleA().test()
# :~</PRE></FONT></BLOCKQUOTE><DIV ALIGN="LEFT"><P><A NAME="_Toc305593314"></A><A NAME="_Toc305628786"></A><FONT FACE="Georgia">In
the source code listings available for this book, this file will be placed in
the subdirectory <B>recyclea</B> that branches off from the subdirectory
<B>c12</B> (for Chapter 12). The unpacking tool takes care of placing it into
the correct subdirectory. The reason for doing this is that this chapter
rewrites this particular example a number of times and by putting each version
in its own directory (using the default package in each directory so that
invoking the program is easy), the class names will not clash.
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_341">Add Comment</A></FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Several
<A NAME="Index33"></A><B>ArrayList</B> objects are created to hold <B>Trash</B>
references. Of course, <B>ArrayList</B>s<B> </B>actually hold <B>Object</B>s so
they’ll hold anything at all. The reason they hold <B>Trash </B>(or
something derived from <B>Trash</B>) is only because you’ve been careful
to not put in anything except <B>Trash</B>. If you do put something
“wrong” into the <B>ArrayList</B>, you won’t get any
compile-time warnings or errors—you’ll find out only via an
exception at run time.
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_342">Add Comment</A></FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">When the <B>Trash</B> references are
added, they lose their specific identities and become simply <B>Object
reference</B>s (they are <A NAME="Index34"></A><I>upcast</I>). However, because
of polymorphism <A NAME="Index35"></A>the proper behavior still occurs when the
dynamically-bound methods<A NAME="Index36"></A> are called through the
<A NAME="Index37"></A><B>Iterator</B> <B>sorter</B>, once the resulting
<A NAME="Index38"></A><B>Object</B> has been cast back to <B>Trash</B>.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -