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

📄 pat5h-1.htm

📁 四人帮《设计模式》一书英文版本
💻 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         = #FFFFFF
onLoad="setFocus();">

<A NAME="top"></A>
<A NAME="State"></A>
<A NAME="intent"></A>
<H2><A HREF="#alsoknownas"><IMG SRC="down3-1.gif" tppabs="http://ultra/development/DesignPatterns/lowres/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="down3-1.gif" tppabs="http://ultra/development/DesignPatterns/lowres/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="down3-1.gif" tppabs="http://ultra/development/DesignPatterns/lowres/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 receives
requests from other objects, it responds differently depending on its
current state.  For example, the effect of an Open request depends on
whether the connection is in its Closed state or its Established
state.  The State pattern describes how TCPConnection can exhibit
different behavior in each state.</P>

<A NAME="tcpstate"></A>
<P>The key idea in this pattern is to introduce an abstract class called
TCPState to represent the states of the network connection.  The
TCPState class declares an interface common to all classes that
represent different operational states.  Subclasses of TCPState
implement state-specific behavior. For example, the classes
TCPEstablished and TCPClosed implement behavior particular to the
Established and Closed states of TCPConnection.</P>

<A NAME="tcpconnect-305c"></A>
<P ALIGN=CENTER><IMG SRC="state-eg-1.gif" tppabs="http://ultra/development/DesignPatterns/lowres/Pictures/state-eg.gif"></P>

<A NAME="auto1003"></A>
<P>The class TCPConnection maintains a state object (an instance of a
subclass of TCPState) that represents the current state of the TCP
connection.  The class TCPConnection delegates all state-specific
requests to this state object.  TCPConnection uses its TCPState
subclass instance to perform operations particular to the state of the
connection.</P>

<A NAME="auto1004"></A>
<P>Whenever the connection changes state, the TCPConnection object
changes the state object it uses.  When the connection goes from
established to closed, for example, TCPConnection will replace its
TCPEstablished instance with a TCPClosed instance.</P>

<A NAME="applicability"></A>
<H2><A HREF="#structure"><IMG SRC="down3-1.gif" tppabs="http://ultra/development/DesignPatterns/lowres/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 its
behavior 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 on
the object's state.  This state is usually represented by one or more
enumerated constants.  Often, several operations will contain this
same conditional structure.  The State pattern puts each branch of the
conditional in a separate class.  This lets you treat the object's
state as an object in its own right that can vary independently from
other objects.</LI>

</UL>

<A NAME="structure"></A>
<H2><A HREF="#participants"><IMG SRC="down3-1.gif" tppabs="http://ultra/development/DesignPatterns/lowres/gifsb/down3.gif" BORDER=0 ALT="next: 
Participants"></A> Structure</H2> 

<P ALIGN=CENTER><IMG SRC="state-1.gif" tppabs="http://ultra/development/DesignPatterns/lowres/Pictures/state.gif"></P>

<A NAME="participants"></A>
<H2><A HREF="#collaborations"><IMG SRC="down3-1.gif" tppabs="http://ultra/development/DesignPatterns/lowres/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 the
current 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 a
particular 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 of
the Context.</LI>

</UL>

</UL>

<A NAME="collaborations"></A>
<H2><A HREF="#consequences"><IMG SRC="down3-1.gif" tppabs="http://ultra/development/DesignPatterns/lowres/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 ConcreteState
object.</LI>
<A NAME="auto1024"></A>
<P></P>
<A NAME="auto1025"></A>
<LI>A context may pass itself as an argument to the State object
handling the request.  This lets the State object access
the 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 a
context 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 state
succeeds another and under what circumstances.</LI>

</UL>

<A NAME="consequences"></A>
<H2><A HREF="#implementation"><IMG SRC="down3-1.gif" tppabs="http://ultra/development/DesignPatterns/lowres/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 partitions
behavior for different states.</EM>
The State pattern puts all behavior associated with a particular state
into one object.  Because all state-specific code lives in a State
subclass, new states and transitions can be added easily by defining
new subclasses.

<A NAME="auto1032"></A>
<P>An alternative is to use data values to define internal states and
have Context operations check the data explicitly.  But then we'd
have look-alike conditional or case statements scattered throughout
Context's implementation.  Adding a new state could require
changing 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 across
several State subclasses. This increases the number of classes and is
less compact than a single class.  But such distribution is actually
good if there are many states, which would otherwise necessitate large
conditional 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, which
in turn makes them difficult to modify and extend.  The State pattern
offers a better way to structure state-specific code.  The logic that
determines the state transitions doesn't reside in monolithic
<CODE>if</CODE> or <CODE>switch</CODE> statements but instead is partitioned
between the State subclasses.  Encapsulating each state transition and
action in a class elevates the idea of an execution state to full
object status.  That imposes structure on the code and makes its
intent 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 internal
data values, its state transitions have no explicit representation;
they only show up as assignments to some variables.  Introducing
separate objects for different states makes the transitions more
explicit.  Also, State objects can protect the Context from
inconsistent internal states, because state transitions are atomic
from the Context's perspective&#151;they happen by rebinding <EM>one</EM>
variable (the Context's State object variable), not
several [<A HREF="bibfs-1.htm#dechampeaux_oosd" tppabs="http://ultra/development/DesignPatterns/lowres/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 they
represent is encoded entirely in their type&#151;then contexts can share
a State object. When states are shared in this way, they are
essentially flyweights (see <A HREF="pat4ffs-1.htm" tppabs="http://ultra/development/DesignPatterns/lowres/pat4ffs.htm" TARGET="_mainDisplayFrame">Flyweight (195</A>)) with no
intrinsic state, only behavior.</LI>

</OL>

<A NAME="implementation"></A>
<H2><A HREF="#samplecode"><IMG SRC="down3-1.gif" tppabs="http://ultra/development/DesignPatterns/lowres/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 the
criteria for state transitions.  If the criteria are fixed, then they
can be implemented entirely in the Context.  It is generally more
flexible and appropriate, however, to let the State subclasses
themselves specify their successor state and when to make the
transition.  This requires adding an interface to the Context that
lets State objects set the Context's current state explicitly.

<A NAME="auto1039"></A>
<P>Decentralizing the transition logic in this way makes it easy to
modify or extend the logic by defining new State subclasses.  A
disadvantage of decentralization is that one State subclass will have
knowledge of at least one other, which introduces implementation
dependencies 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-1.htm#cargill_c++style" tppabs="http://ultra/development/DesignPatterns/lowres/bibfs.htm#cargill_c++style" TARGET="_mainDisplayFrame">Car92</A>], Cargill
describes another way to impose structure on state-driven code: He
uses tables to map inputs to state transitions.  For each state, a
table maps every possible input to a succeeding state.  In effect,
this approach converts conditional code (and virtual functions, in the
case 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 the
transition criteria by modifying data instead of changing program
code.  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 the
transition 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 state
transitions.  The table-driven approach captures the states and their
transitions, but it must be augmented to perform arbitrary computation
on each transition.

</UL>

<A NAME="auto1048"></A>

⌨️ 快捷键说明

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