⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pat3d.htm

📁 Design Pattern 设计模式
💻 HTM
📖 第 1 页 / 共 2 页
字号:
<SCRIPT>
function setFocus() {	
	if ((navigator.appName != "Netscape") && (parseFloat(navigator.appVersion) == 2)) {
	return;
	} else {
	self.focus();
	}
}
</SCRIPT><HTML><HEAD>	<TITLE>Prototype</TITLE></HEAD><BODY	BGCOLOR	= #FFFFFF	TEXT = #000000
onLoad="setFocus()";><A NAME="top"></A><A NAME="Prototype"></A><A NAME="intent"></A><H2><A HREF="#motivation"><IMG SRC="gifsb/down3.gif" BORDER=0 ALT="next: Motivation"></A> Intent</H2> <A NAME="auto1000"></A><P>Specify the kinds of objects to create using a prototypicalinstance, and create new objects by copying this prototype.</P><A NAME="motivation"></A><H2><A HREF="#applicability"><IMG SRC="gifsb/down3.gif" BORDER=0 ALT="next: Applicability"></A> Motivation</H2> <A NAME="auto1001"></A><P>You could build an editor for music scores by customizing a generalframework for graphical editors and adding new objects that representnotes, rests, and staves.  The editor framework may have a palette oftools for adding these music objects to the score.  The palette wouldalso include tools for selecting, moving, and otherwise manipulatingmusic objects.  Users will click on the quarter-note tool and use itto add quarter notes to the score.  Or they can use the move tool tomove a note up or down on the staff, thereby changing its pitch.</P><A NAME="tool-class"></A><P>Let's assume the framework provides an abstract Graphic class forgraphical components, like notes and staves.  Moreover, it'll providean abstract Tool class for defining tools like those in the palette.The framework also predefines a GraphicTool subclass for tools thatcreate instances of graphical objects and add them to the document.</P><A NAME="auto1002"></A><P>But GraphicTool presents a problem to the framework designer.  Theclasses for notes and staves are specific to our application, but theGraphicTool class belongs to the framework.  GraphicTool doesn't knowhow to create instances of our music classes to add to the score.  Wecould subclass GraphicTool for each kind of music object, but thatwould produce lots of subclasses that differ only in the kind of musicobject they instantiate.  We know object composition is a flexiblealternative to subclassing.  The question is, how can the frameworkuse it to parameterize instances of GraphicTool by the <EM>class</EM> ofGraphic they're supposed to create?</P><A NAME="def-proto"></A><P>The solution lies in making GraphicTool create a new Graphic bycopying or "cloning" an instance of a Graphic subclass.  We callthis instance a <B>prototype</B>.  GraphicTool is parameterized by theprototype it should clone and add to the document.  If all Graphicsubclasses support a Clone operation, then the GraphicTool can cloneany kind of Graphic.</P><A NAME="auto1003"></A><P>So in our music editor, each tool for creating a music object is aninstance of GraphicTool that's initialized with a different prototype.Each GraphicTool instance will produce a music object by cloning itsprototype and adding the clone to the score.</P><A NAME="tool-118c"></A><P ALIGN=CENTER><IMG SRC="Pictures/proto019.gif"></P><A NAME="auto1004"></A><P>We can use the Prototype pattern to reduce the number of classes evenfurther.  We have separate classes for whole notes and half notes, butthat's probably unnecessary.  Instead they could be instances of thesame class initialized with different bitmaps and durations.  A toolfor creating whole notes becomes just a GraphicTool whose prototype isa MusicalNote initialized to be a whole note.  This can reduce thenumber of classes in the system dramatically.  It also makes it easierto add a new kind of note to the music editor.</P><A NAME="applicability"></A><H2><A HREF="#structure"><IMG SRC="gifsb/down3.gif" BORDER=0 ALT="next: Structure"></A> Applicability</H2> <A NAME="auto1005"></A><P>Use the Prototype pattern when a system should be independent of howits products are created, composed, and represented; <EM>and</EM></P><UL><A NAME="auto1006"></A><LI>when the classes to instantiate are specified at run-time, forexample, by dynamic loading; <EM>or</EM></LI><A NAME="auto1007"></A><P></P><A NAME="auto1008"></A><LI>to avoid building a class hierarchy of factories thatparallels the class hierarchy of products; <EM>or</EM></LI><A NAME="auto1009"></A><P></P><A NAME="auto1010"></A><LI>when instances of a class can have one of only a few differentcombinations of state.  It may be more convenient to install acorresponding number of prototypes and clone them rather thaninstantiating the class manually, each time with the appropriate state.</LI></UL><A NAME="structure"></A><H2><A HREF="#participants"><IMG SRC="gifsb/down3.gif" BORDER=0 ALT="next: Participants"></A> Structure</H2> <P ALIGN=CENTER><IMG SRC="Pictures/proto018.gif"></P><A NAME="participants"></A><H2><A HREF="#collaborations"><IMG SRC="gifsb/down3.gif" BORDER=0 ALT="next: Collaborations"></A> Participants</H2><UL><A NAME="auto1011"></A><LI><B>Prototype</B> (Graphic)<A NAME="auto1012"></A><P></P>    <UL>    <A NAME="auto1013"></A><LI>declares an interface for cloning itself.    </UL><A NAME="auto1014"></A><P></P><A NAME="auto1015"></A><LI><B>ConcretePrototype</B> (Staff, WholeNote, HalfNote)<A NAME="auto1016"></A><P></P>    <UL>    <A NAME="auto1017"></A><LI>implements an operation for cloning itself.    </UL><A NAME="auto1018"></A><P></P><A NAME="auto1019"></A><LI><B>Client</B> (GraphicTool)<A NAME="auto1020"></A><P></P>    <UL>     <A NAME="auto1021"></A><LI>creates a new object by asking a prototype to clone itself.    </UL></UL><A NAME="collaborations"></A><H2><A HREF="#consequences"><IMG SRC="gifsb/down3.gif" BORDER=0 ALT="next: Consequences"></A> Collaborations</H2><UL><A NAME="auto1022"></A><LI>A client asks a prototype to clone itself.</UL><A NAME="consequences"></A><H2><A HREF="#implementation"><IMG SRC="gifsb/down3.gif" BORDER=0 ALT="next: Implementaion"></A> Consequences</H2> <A NAME="auto1023"></A><P>Prototype has many of the same consequences that <A HREF="pat3afs.htm" TARGET="_mainDisplayFrame">Abstract Factory (87)</A> and <A HREF="pat3bfs.htm" TARGET="_mainDisplayFrame">Builder (97)</A>have: It hides the concrete product classes from the client, therebyreducing the number of names clients know about.  Moreover, thesepatterns let a client work with application-specific classes withoutmodification.</P><A NAME="auto1024"></A><P>Additional benefits of the Prototype pattern are listed below.</P><OL><A NAME="prodobj-change-runtime"></A><LI><EM>Adding and removing products at run-time.</EM>Prototypes let you incorporate a new concrete product class into asystem simply by registering a prototypical instance with the client.That's a bit more flexible than other creational patterns, because aclient can install and remove prototypes at run-time.</LI><A NAME="auto1025"></A><P></P><A NAME="auto1026"></A><LI><EM>Specifying new objects by varying values.</EM>Highly dynamic systems let you define new behavior through objectcomposition&#151;by specifying values for an object's variables, forexample&#151;and not by defining new classes.  You effectively define newkinds of objects by instantiating existing classes and registering theinstances as prototypes of client objects.  A client can exhibit newbehavior by delegating responsibility to the prototype.<A NAME="auto1027"></A><P>This kind of design lets users define new "classes" withoutprogramming.  In fact, cloning a prototype is similar to instantiatinga class.  The Prototype pattern can greatly reduce the number ofclasses a system needs.  In our music editor, one GraphicTool classcan create a limitless variety of music objects.</P></LI><A NAME="auto1028"></A><P></P><A NAME="auto1029"></A><LI><EM>Specifying new objects by varying structure.</EM>Many applications build objects from parts and subparts.  Editors forcircuit design, for example, build circuits out ofsubcircuits.<A NAME="fn1"></A><A HREF="#footnote1"><SUP>1</SUP></A>For convenience, such applications often let youinstantiate complex, user-defined structures, say, to use a specificsubcircuit again and again.<A NAME="auto1030"></A><P>The Prototype pattern supports this as well.  We simply add thissubcircuit as a prototype to the palette of available circuitelements.  As long as the composite circuit object implements Clone asa deep copy, circuits with different structures can be prototypes.</LI><A NAME="auto1031"></A><P></P><A NAME="proto-vs-factmeth"></A><LI><EM>Reduced subclassing.</EM><A HREF="pat3cfs.htm" TARGET="_mainDisplayFrame">Factory Method (107)</A> often produces a hierarchy ofCreator classes that parallels the product class hierarchy.  ThePrototype pattern lets you clone a prototype instead of asking afactory method to make a new object.  Hence you don't need a Creatorclass hierarchy at all.  This benefit applies primarily to languageslike C++ that don't treat classes as first-class objects.  Languagesthat do, like Smalltalk and Objective C, derive less benefit, sinceyou can always use a class object as a creator.  Class objects alreadyact like prototypes in these languages.</LI><A NAME="auto1032"></A><P></P><A NAME="auto1033"></A><LI><EM>Configuring an application with classes dynamically.</EM>Some run-time environments let you load classes into an applicationdynamically.  The Prototype pattern is the key to exploiting suchfacilities in a language like C++.<A NAME="et-use-proto"></A><P>An application that wants to create instances of a dynamically loadedclass won't be able to reference its constructor statically.  Instead,the run-time environment creates an instance of each classautomatically when it's loaded, and it registers the instance with aprototype manager (see the Implementation section).  Then theapplication can ask the prototype manager for instances ofnewly loaded classes, classes that weren't linked with the programoriginally.  The ET++ application framework [<A HREF="bibfs.htm#et++" TARGET="_mainDisplayFrame">WGM88</A>] has a run-timesystem that uses this scheme.</LI></OL><A NAME="auto1034"></A><P>The main liability of the Prototype pattern is that each subclass ofPrototype must implement the <CODE>Clone</CODE> operation, which may bedifficult.  For example, adding <CODE>Clone</CODE> is difficult when theclasses under consideration already exist.  Implementing <CODE>Clone</CODE> can bedifficult when their internals include objects that don't supportcopying or have circular references.</P><A NAME="implementation"></A><H2><A HREF="#samplecode"><IMG SRC="gifsb/down3.gif" BORDER=0 ALT="next: Sample Code"></A> Implementation</H2> <A NAME="self"></A><P>Prototype is particularly useful with static languages like C++, whereclasses are not objects, and little or no type information isavailable at run-time.  It's less important in languages likeSmalltalk or Objective C that provide what amounts to a prototype(i.e., a class object) for creating instances of each class.  Thispattern is built into prototype-based languages likeSelf [<A HREF="bibfs.htm#ungar_self" TARGET="_mainDisplayFrame">US87</A>], in which all object creation happens bycloning a prototype.</P><A NAME="auto1035"></A><P>Consider the following issues when implementing prototypes:</P><OL><A NAME="proto-manager"></A><LI><EM>Using a prototype manager.</EM>When the number of prototypes in a system isn't fixed (that is, theycan be created and destroyed dynamically), keep a registry ofavailable prototypes.  Clients won't manage prototypes themselves butwill store and retrieve them from the registry.  A client will ask theregistry for a prototype before cloning it.  We call this registry a<STRONG>prototype manager</STRONG>.<A NAME="auto1036"></A><P>A prototype manager is an associative store that returns the prototypematching a given key.  It has operations for registering a prototypeunder a key and for unregistering it.  Clients can change or evenbrowse through the registry at run-time.  This lets clients extend andtake inventory on the system without writing code.</LI><A NAME="auto1037"></A><P></P><A NAME="auto1038"></A><LI><EM>Implementing the Clone operation.</EM>The hardest part of the Prototype pattern is implementing the Cloneoperation correctly.  It's particularly tricky when object structurescontain circular references.<A NAME="auto1039"></A><P>Most languages provide some support for cloning objects.  For example,Smalltalk provides an implementation of <CODE>copy</CODE> that'sinherited by all subclasses of Object.  C++ provides a copyconstructor.  But these facilities don't solve the "shallow copyversus deep copy" problem [<A HREF="bibfs.htm#st_lang" TARGET="_mainDisplayFrame">GR83</A>].  That is, does cloning anobject in turn clone its instance variables, or do the clone andoriginal just share the variables?<A NAME="auto1040"></A><P>A shallow copy is simple and often sufficient, and that's whatSmalltalk provides by default.  The default copy constructor in C++does a member-wise copy, which means pointers will be shared betweenthe copy and the original.  But cloning prototypes with complexstructures usually requires a deep copy, because the clone and theoriginal must be independent.  Therefore you must ensure that theclone's components are clones of the prototype's components.  Cloningforces you to decide what if anything will be shared.<A NAME="auto1041"></A>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -