?? pat5i.htm
字號:
<HTML><HEAD><TITLE>Strategy</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="Strategy"></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>Define a family of algorithms, encapsulate each one, and make theminterchangeable. Strategy lets the algorithm vary independently fromclients that use it.</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>Policy</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>Many algorithms exist for breaking a stream of text into lines.Hard-wiring all such algorithms into the classes that require themisn't desirable for several reasons:</P><UL><A NAME="auto1003"></A><LI>Clients that need linebreaking get more complex if they includethe linebreaking code. That makes clients bigger and harder tomaintain, especially if they support multiple linebreaking algorithms.</LI><A NAME="auto1004"></A><P></P><A NAME="auto1005"></A><LI>Different algorithms will be appropriate at different times. We don'twant to support multiple linebreaking algorithms if we don't use themall.</LI><A NAME="auto1006"></A><P></P><A NAME="auto1007"></A><LI>It's difficult to add new algorithms and vary existing ones whenlinebreaking is an integral part of a client.</LI></UL><A NAME="def-strategy"></A><P>We can avoid these problems by defining classes that encapsulatedifferent linebreaking algorithms. An algorithm that's encapsulated inthis way is called a <STRONG>strategy</STRONG>.</P><A NAME="315c"></A><P ALIGN=CENTER><IMG SRC="Pictures/strat011.gif"></P><A NAME="compositor"></A><P>Suppose a Composition class is responsible for maintaining andupdating the linebreaks of text displayed in a text viewer.Linebreaking strategies aren't implemented by the class Composition.Instead, they are implemented separately by subclasses of the abstractCompositor class. Compositor subclasses implement different strategies:</P><UL><A NAME="simplecompositor"></A><LI><STRONG>SimpleCompositor</STRONG>implements a simple strategy that determines linebreaks one at atime.</LI><A NAME="auto1008"></A><P></P><A NAME="tex-comp"></A><LI><STRONG>TeXCompositor</STRONG>implements the TeX algorithm for finding linebreaks. This strategytries to optimize linebreaks globally, that is, one paragraph at atime.</LI><A NAME="auto1009"></A><P></P><A NAME="auto1010"></A><LI><STRONG>ArrayCompositor</STRONG>implements a strategy that selects breaks so that each row has a fixednumber of items. It's useful for breaking a collection of icons intorows, for example.</LI></UL><A NAME="auto1011"></A><P>A Composition maintains a reference to a Compositor object. Whenever aComposition reformats its text, it forwards this responsibility to itsCompositor object. The client of Composition specifies whichCompositor should be used by installing the Compositor it desires intothe Composition.</P><A NAME="applicability"></A><H2><A HREF="#structure"><IMG SRC="gifsb/down3.gif" BORDER=0 ALT="next: Structure"></A> Applicability</H2> <A NAME="auto1012"></A><P>Use the Strategy pattern when</P><UL><A NAME="auto1013"></A><LI>many related classes differ only in their behavior. Strategiesprovide a way to configure a class with one of many behaviors.</LI><A NAME="auto1014"></A><P></P><A NAME="auto1015"></A><LI>you need different variants of an algorithm. For example, you might definealgorithms reflecting different space/time trade-offs.Strategies can be used when these variants are implemented as a classhierarchy of algorithms [<A HREF="bibfs.htm#halbert-obrien" TARGET="_mainDisplayFrame">HO87</A>].</LI><A NAME="auto1016"></A><P></P><A NAME="auto1017"></A><LI>an algorithm uses data that clients shouldn't know about. Use theStrategy pattern to avoid exposing complex, algorithm-specific datastructures.</LI><A NAME="auto1018"></A><P></P><A NAME="auto1019"></A><LI>a class defines many behaviors, and these appear as multipleconditional statements in its operations. Instead of manyconditionals, move related conditional branches into their ownStrategy class.</LI></UL><A NAME="structure"></A><H2><A HREF="#participants"><IMG SRC="gifsb/down3.gif" BORDER=0 ALT="next: Participants"></A> Structure</H2> <A NAME="strat-316c"></A><P ALIGN=CENTER><IMG SRC="Pictures/strategy.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="auto1020"></A><LI><B>Strategy</B> (Compositor)</LI><A NAME="auto1021"></A><P></P> <UL> <A NAME="auto1022"></A><LI>declares an interface common to all supported algorithms. Context uses this interface to call the algorithm defined by a ConcreteStrategy.</LI> </UL><A NAME="auto1023"></A><P></P><A NAME="auto1024"></A><LI><B>ConcreteStrategy</B> (SimpleCompositor, TeXCompositor,ArrayCompositor)</LI><A NAME="auto1025"></A><P></P> <UL> <A NAME="auto1026"></A><LI>implements the algorithm using the Strategy interface.</LI> </UL><A NAME="auto1027"></A><P></P><A NAME="auto1028"></A><LI><B>Context</B> (Composition)<A NAME="auto1029"></A><P></P> <UL> <A NAME="auto1030"></A><LI>is configured with a ConcreteStrategy object.</LI> <A NAME="auto1031"></A><P><!-- extra space --></P> <A NAME="auto1032"></A><LI>maintains a reference to a Strategy object.</LI> <A NAME="auto1033"></A><P><!-- extra space --></P> <A NAME="auto1034"></A><LI>may define an interface that lets Strategy access its data.</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="auto1035"></A><LI>Strategy and Context interact to implement the chosen algorithm. Acontext may pass all data required by the algorithm to the strategywhen the algorithm is called. Alternatively, the context can passitself as an argument to Strategy operations. That lets the strategycall back on the context as required.</LI><A NAME="auto1036"></A><P></P><A NAME="auto1037"></A><LI>A context forwards requests from its clients to its strategy. Clientsusually create and pass a ConcreteStrategy object to the context;thereafter, clients interact with the context exclusively. There isoften a family of ConcreteStrategy classes for a client to choosefrom.</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="auto1038"></A><P>The Strategy pattern has the following benefits and drawbacks:</P><OL><A NAME="families"></A><LI><EM>Families of related algorithms.</EM>Hierarchies of Strategy classes define a family of algorithms orbehaviors for contexts to reuse. Inheritance canhelp factor out common functionality of the algorithms.</LI><A NAME="auto1039"></A><P></P><A NAME="auto1040"></A><LI><EM>An alternative to subclassing.</EM>Inheritance offers another way to support a variety of algorithms orbehaviors. You can subclass a Context class directly to give itdifferent behaviors. But this hard-wires the behavior into Context.It mixes the algorithm implementation with Context's, making Contextharder to understand, maintain, and extend. And you can't vary thealgorithm dynamically. You wind up with many related classes whoseonly difference is the algorithm or behavior they employ.Encapsulating the algorithm in separate Strategy classes lets you varythe algorithm independently of its context, making it easier toswitch, understand, and extend.</LI><A NAME="auto1041"></A><P></P><A NAME="auto1042"></A><LI><EM>Strategies eliminate conditional statements.</EM>The Strategy pattern offers an alternative to conditional statements forselecting desired behavior. When different behaviors are lumped into oneclass, it's hard to avoid using conditional statements to select theright behavior. Encapsulating the behavior in separate Strategy classeseliminates these conditional statements.<A NAME="auto1043"></A><P>For example, without strategies, the code for breakingtext into lines could look like<A NAME="auto1044"></A><PRE> void Composition::Repair () { switch (_breakingStrategy) { case SimpleStrategy: ComposeWithSimpleCompositor(); break; case TeXStrategy: ComposeWithTeXCompositor(); break; // ... } // merge results with existing composition, if necessary }</PRE><A NAME="auto1045"></A><P>The Strategy pattern eliminates this case statement by delegating thelinebreaking task to a Strategy object:</P><A NAME="auto1046"></A><PRE> void Composition::Repair () { _compositor->Compose(); // merge results with existing composition, if necessary }</PRE><A NAME="auto1047"></A><P>Code containing many conditional statements often indicatesthe need to apply the Strategy pattern.</P></LI><A NAME="auto1048"></A><P></P><A NAME="auto1049"></A><LI><EM>A choice of implementations.</EM>Strategies can provide different implementations of the <EM>same</EM>behavior. The client can choose among strategies with differenttime and space trade-offs.</LI><A NAME="auto1050"></A><P></P><A NAME="auto1051"></A><LI><EM>Clients must be aware of different Strategies.</EM>The pattern has a potential drawback in that a client must understandhow Strategies differ before it can select the appropriate one.Clients might be exposed to implementation issues. Therefore youshould use the Strategy pattern only when the variation in behavior isrelevant to clients.</LI><A NAME="auto1052"></A><P></P><A NAME="auto1053"></A><LI><EM>Communication overhead between Strategy and Context.</EM>The Strategy interface is shared by all ConcreteStrategy classeswhether the algorithms they implement are trivial or complex. Henceit's likely that some ConcreteStrategies won't use all the informationpassed to them through this interface; simple ConcreteStrategies mayuse none of it! That means there will be times when the contextcreates and initializes parameters that never get used. If this is anissue, then you'll need tighter coupling between Strategy and Context.</LI><A NAME="auto1054"></A><P></P><A NAME="auto1055"></A><LI><EM>Increased number of objects.</EM>Strategies increase the number of objects in an application. Sometimesyou can reduce this overhead by implementing strategies as statelessobjects that contexts can share. Any residual state is maintained by thecontext, which passes it in each request to the Strategy object. Sharedstrategies should not maintain state across invocations. The<A HREF="pat4ffs.htm" TARGET="_mainDisplayFrame">Flyweight (195</A>) pattern describes this approach in more
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -