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

📄 pat5h.htm

📁 Design Pattern 设计模式
💻 HTM
📖 第 1 页 / 共 2 页
字号:
<HTML><HEAD>	<TITLE>State</TITLE><SCRIPT>function setFocus() {		if ((navigator.appName != "Netscape") && (parseFloat(navigator.appVersion) == 2)) {	return;	} else {	self.focus();	}}</SCRIPT></HEAD><BODY   BGCOLOR         = #FFFFFFonLoad="setFocus();"><A NAME="top"></A><A NAME="State"></A><A NAME="intent"></A><H2><A HREF="#alsoknownas"><IMG SRC="gifsb/down3.gif" BORDER=0 ALT="next: Also Known As"></A> Intent</H2> <A NAME="auto1000"></A><P>Allow an object to alter its behavior when its internal state changes.The object will appear to change its class.</P><A NAME="alsoknownas"><A><H2><A HREF="#motivation"><IMG SRC="gifsb/down3.gif" BORDER=0 ALT="next: Motivation"></A> Also Known As</H2> <A NAME="auto1001"></A><P>Objects for States</P><A NAME="motivation"></A><H2><A HREF="#applicability"><IMG SRC="gifsb/down3.gif" BORDER=0 ALT="next: Applicability"></A> Motivation</H2> <A NAME="auto1002"></A><P>Consider a class TCPConnection that represents a network connection.A TCPConnection object can be in one of several different states:Established, Listening, Closed.  When a TCPConnection object receivesrequests from other objects, it responds differently depending on itscurrent state.  For example, the effect of an Open request depends onwhether the connection is in its Closed state or its Establishedstate.  The State pattern describes how TCPConnection can exhibitdifferent behavior in each state.</P><A NAME="tcpstate"></A><P>The key idea in this pattern is to introduce an abstract class calledTCPState to represent the states of the network connection.  TheTCPState class declares an interface common to all classes thatrepresent different operational states.  Subclasses of TCPStateimplement state-specific behavior. For example, the classesTCPEstablished and TCPClosed implement behavior particular to theEstablished and Closed states of TCPConnection.</P><A NAME="tcpconnect-305c"></A><P ALIGN=CENTER><IMG SRC="Pictures/state-eg.gif"></P><A NAME="auto1003"></A><P>The class TCPConnection maintains a state object (an instance of asubclass of TCPState) that represents the current state of the TCPconnection.  The class TCPConnection delegates all state-specificrequests to this state object.  TCPConnection uses its TCPStatesubclass instance to perform operations particular to the state of theconnection.</P><A NAME="auto1004"></A><P>Whenever the connection changes state, the TCPConnection objectchanges the state object it uses.  When the connection goes fromestablished to closed, for example, TCPConnection will replace itsTCPEstablished instance with a TCPClosed instance.</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 State pattern in either of the following cases:</P><UL><A NAME="auto1006"></A><LI>An object's behavior depends on its state, and it must change itsbehavior at run-time depending on that state.</LI><A NAME="auto1007"></A><P></P><A NAME="auto1008"></A><LI>Operations have large, multipart conditional statements that depend onthe object's state.  This state is usually represented by one or moreenumerated constants.  Often, several operations will contain thissame conditional structure.  The State pattern puts each branch of theconditional in a separate class.  This lets you treat the object'sstate as an object in its own right that can vary independently fromother objects.</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/state.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="auto1009"></A><P></P><A NAME="auto1010"></A><LI><B>Context</B> (TCPConnection)</LI><A NAME="auto1011"></A><P></P><UL><A NAME="auto1012"></A><LI>defines the interface of interest to clients.    <A NAME="auto1013"></A><P><!-- extra space --></P><A NAME="auto1014"></A><LI>maintains an instance of a ConcreteState subclass that defines thecurrent state.</UL><A NAME="auto1015"></A><P></P><A NAME="auto1016"></A><LI><B>State</B> (TCPState)</LI><A NAME="auto1017"></A><P></P><UL><A NAME="auto1018"></A><LI>defines an interface for encapsulating the behavior associated with aparticular state of the Context.</LI></UL><A NAME="auto1019"></A><P></P><A NAME="auto1020"></A><LI><B>ConcreteState subclasses</B> (TCPEstablished, TCPListen, TCPClosed)</LI><A NAME="auto1021"></A><P></P><UL><A NAME="auto1022"></A><LI>each subclass implements a behavior associated with a state ofthe Context.</LI></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="auto1023"></A><LI>Context delegates state-specific requests to the current ConcreteStateobject.</LI><A NAME="auto1024"></A><P></P><A NAME="auto1025"></A><LI>A context may pass itself as an argument to the State objecthandling the request.  This lets the State object accessthe context if necessary.</LI><A NAME="auto1026"></A><P></P><A NAME="auto1027"></A><LI>Context is the primary interface for clients. Clients can configure acontext with State objects. Once a context is configured, its clients don't have to deal with the State objects directly. </LI><A NAME="auto1028"></A><P></P><A NAME="auto1029"></A><LI>Either Context or the ConcreteState subclasses can decide which statesucceeds another and under what circumstances.</LI></UL><A NAME="consequences"></A><H2><A HREF="#implementation"><IMG SRC="gifsb/down3.gif" BORDER=0 ALT="next: Implementation"></A> Consequences</H2> <A NAME="auto1030"></A><P>The State pattern has the following consequences:</P><OL><A NAME="auto1031"></A><LI><EM>It localizes state-specific behavior and partitionsbehavior for different states.</EM>The State pattern puts all behavior associated with a particular stateinto one object.  Because all state-specific code lives in a Statesubclass, new states and transitions can be added easily by definingnew subclasses.<A NAME="auto1032"></A><P>An alternative is to use data values to define internal states andhave Context operations check the data explicitly.  But then we'dhave look-alike conditional or case statements scattered throughoutContext's implementation.  Adding a new state could requirechanging several operations, which complicates maintenance.</P><A NAME="auto1033"></A><P>The State pattern avoids this problem but might introduce another,because the pattern distributes behavior for different states acrossseveral State subclasses. This increases the number of classes and isless compact than a single class.  But such distribution is actuallygood if there are many states, which would otherwise necessitate largeconditional statements.</P><A NAME="auto1034"></A><P>Like long procedures, large conditional statements are undesirable.They're monolithic and tend to make the code less explicit, whichin turn makes them difficult to modify and extend.  The State patternoffers a better way to structure state-specific code.  The logic thatdetermines the state transitions doesn't reside in monolithic<CODE>if</CODE> or <CODE>switch</CODE> statements but instead is partitionedbetween the State subclasses.  Encapsulating each state transition andaction in a class elevates the idea of an execution state to fullobject status.  That imposes structure on the code and makes itsintent clearer.</P></LI><A NAME="auto1035"></A><P></P><A NAME="state-avoid-inconsistent"></A><A NAME="state-atomic"></A><LI><EM>It makes state transitions explicit.</EM>When an object defines its current state solely in terms of internaldata values, its state transitions have no explicit representation;they only show up as assignments to some variables.  Introducingseparate objects for different states makes the transitions moreexplicit.  Also, State objects can protect the Context frominconsistent internal states, because state transitions are atomicfrom the Context's perspective&#151;they happen by rebinding <EM>one</EM>variable (the Context's State object variable), notseveral [<A HREF="bibfs.htm#dechampeaux_oosd" TARGET="_mainDisplayFrame">dCLF93</A>].</LI><A NAME="auto1036"></A><P></P><A NAME="flywt-w-state"></A><A NAME="state-sharing"></A><LI><EM>State objects can be shared.</EM>If State objects have no instance variables&#151;that is, the state theyrepresent is encoded entirely in their type&#151;then contexts can sharea State object. When states are shared in this way, they areessentially flyweights (see <A HREF="pat4ffs.htm" TARGET="_mainDisplayFrame">Flyweight (195</A>)) with nointrinsic state, only behavior.</LI></OL><A NAME="implementation"></A><H2><A HREF="#samplecode"><IMG SRC="gifsb/down3.gif" BORDER=0 ALT="next: Sample Code"></A> Implementation</H2> <A NAME="auto1037"></A><P>The State pattern raises a variety of implementation issues:</P><OL><A NAME="auto1038"></A><LI><EM>Who defines the state transitions?</EM>The State pattern does not specify which participant defines thecriteria for state transitions.  If the criteria are fixed, then theycan be implemented entirely in the Context.  It is generally moreflexible and appropriate, however, to let the State subclassesthemselves specify their successor state and when to make thetransition.  This requires adding an interface to the Context thatlets State objects set the Context's current state explicitly.<A NAME="auto1039"></A><P>Decentralizing the transition logic in this way makes it easy tomodify or extend the logic by defining new State subclasses.  Adisadvantage of decentralization is that one State subclass will haveknowledge of at least one other, which introduces implementationdependencies between subclasses.</P></LI><A NAME="auto1040"></A><P></P><A NAME="state-tablebased"></A><LI><EM>A table-based alternative.</EM>In <EM>C++ Programming Style</EM> [<A HREF="bibfs.htm#cargill_c++style" TARGET="_mainDisplayFrame">Car92</A>], Cargilldescribes another way to impose structure on state-driven code: Heuses tables to map inputs to state transitions.  For each state, atable maps every possible input to a succeeding state.  In effect,this approach converts conditional code (and virtual functions, in thecase of the State pattern) into a table look-up.<A NAME="auto1041"></A><P>The main advantage of tables is their regularity: You can change thetransition criteria by modifying data instead of changing programcode.  There are some disadvantages, however:</P><A NAME="auto1042"></A><P></P><UL><A NAME="auto1043"></A><LI>A table look-up is often less efficient than a (virtual)function call.<A NAME="auto1044"></A><P></P><A NAME="auto1045"></A><LI>Putting transition logic into a uniform, tabular format makes thetransition criteria less explicit and therefore harder to understand.<A NAME="auto1046"></A><P></P><A NAME="auto1047"></A><LI>It's usually difficult to add actions to accompany the statetransitions.  The table-driven approach captures the states and theirtransitions, but it must be augmented to perform arbitrary computationon each transition.</UL><A NAME="auto1048"></A>

⌨️ 快捷键说明

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