Wiki Home

Strategy Pattern


Namespace: SoftwareEng
Strategy Pattern is one of the 23 Design Patterns elucidated in the most excellent Gamma And Helm book, Design Patterns: Elements of Reusable Object - Oriented Software by Gamma and Helm et al. ISBN 0201633612 , which is cited below:
Intent: Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it. (Also known as Policy)

Design Pattern Classification: Object Behavioral

Applicability:
Use the Strategy pattern when -
Structure:

Collaborations:
Strategy – INTL Example (by Steven Black)
According to Gamma And Helm, the intent of the Strategy pattern is: Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it.

Problem
Not all localizations are alike. For example, a port from the US to the UK or Canada probably needs only minor interface adjustments, along with perhaps local currency support. A port from the US to Germany, on the other hand, requires extensive interface along with, potentially, localizing images and data sources. A port further afield may require changing fonts and most of the other localizable things. How to do this?

Context
The application localization must be configurable, in the field, on the fly.

Forces
  • The user must be able to configure localizations to suit needs
  • The user should be able to create new localization strategies without much difficulty.
    Solution
    Separate individual localization tasks into atomic processes, then give each process the same interface so as to make them interchangeable. Give the controlling process a clean inteface for loading strategies, and design the process to call each loaded “strategy” in turn.

    Resulting Context
    A modular set of strategies that can be applied as appropriate. In the case of INTL, certain parts of the localization strategies are so common – lookups in STRINGS.DBF for example – that this capability was migrated up the hierarchy to avoid loading redundant capabilities in each strategy.

    Rationale
    Separating the localization tasks into separate strategies, and creating a mechanism to iterate through the loaded strategies, allows for much configuration flexibility. The downside is a performance penalty arising from the some inevitable common elements and from an increase in messaging traffic.
    The INTL class Strategy branch.
    Layered Strategies anyone?
    ( Attempting to take another stab here at adding some content with value to this topic =D) )

    I've begun seeing a bigger picture with some of my strategy patterns, and I'm trying to decide if it's a good thing or bad thing. I'm finding that on occaision, sometimes I hit a situation where I have a ConcreteStrategy (SimpleCompositor type class, lower leg of inheritance branch) that isnt exactly needed in runtime as a concrete class, but rather becomes the Strategy (Compositor type class, upper leg in inheritance branch) in a second layer of a related strategy pattern. This second layer of ConcreteStategy classes is tied to a different Context interface (Composition type class, usually a form class in my case) than the layer above it. ( Please tell me if I make no sense here & I'll post up a diagram...)

    For example 2-tier Business Objects:
    First layer strategy pattern is my run of the mill business classes to interact with my forms. From my BaseBizObj class (Strategy or "Compositor") I inherit to my SimpleCompositor type WizardBaseBizOBj. WizardBase becomes the Strategy or "Compositor" for a few ConcreteStrategy classes, each for a specific wizard utilty. So now I have 2 layers of Strategies, with WizardBase warping things a little bit.

    I beat up on myself that something wasn't right here... didn't feel like a "classic" strategy. Then it dawned on me I've done this before without realizing it. And with a few days to stew on it, I found similar examples in Mere Mortals flavor of Codebook. In fact this layered strategy scenario is usually evident in the class diagrams where it feels like you have a cobweb when trying to lay everything out to fit on one piece of paper. Yet, when working with the concrete classes it still feels clean, like a strategy should.

    So now I'm curious, what do other folks think of layered strategies like this? Too much of good thing? Am I defeating the purpose here perhaps, or is my recent conclusion that "hey this isnt just me, it is commonly found" more accurate? -- Rox
    A nice article on the Strategy Pattern vs the Template:

    http://www.objectmentor.com/resources/articles/inheritanceVsDelegation.pdf

    and a Fox version one of the strategies in the article:
    * main
    LOCAL loApp
    loApp = CREATEOBJECT("ApplicationRunner", CREATEOBJECT("ftocStrategy"))
    loApp.Run()
    	
    DEFINE CLASS ApplicationRunner as Line
    	ItsApplication = NULL
    	*-------------------------
    	FUNCTION Init
    	LPARAMETERS toApp
    		This.ItsApplication = toApp
    	ENDFUNC
    	*-----------
    	FUNCTION Run
    *		This.ItsApplication.Init()
    		DO WHILE !This.ItsApplication.Done()
    			This.ItsApplication.Idle()
    		ENDDO
    		This.ItsApplication.CleanUp()
    	ENDFUNC
    ENDDEFINE
    
    * needed to be sure each function is defined
    DEFINE CLASS Stragety as Line
    	FUNCTION Init
    	FUNCTION Idle
    	FUNCTION Done
    	FUNCTION Cleanup
    ENDDEFINE
    
    DEFINE CLASS ftocStrategy as Stragety
    	FileHandle = 0
    	IsDone = .F.
    	*------------
    	FUNCTION Init
    	LOCAL lcFile
    		lcFile = GETFILE()
    		IF FILE(lcFile)
    			This.FileHandle = FOPEN(lcFile)
    		ENDIF
    	ENDFUNC
    	*------------
    	FUNCTION Idle
    	LOCAL lcFahrStr, lnFahr, lnCelcius
    		IF FEOF(This.FileHandle)
    			This.IsDone = .T.
    		ELSE
    			lcFahrStr = FGETS(This.FileHandle)
    			IF !EMPTY(lcFahrStr)
    				lnFahr = VAL(lcFahrStr)
    				lnCelcius = 5.0/9.0 * (lnFahr - 32.0)
    				MESSAGEBOX("Fahr " + lcFahrStr + " = " + TRANSFORM(lnCelcius) + " Celcius")
    			ENDIF
    		ENDIF
    	ENDFUNC
    	*---------------
    	FUNCTION Cleanup
    		FCLOSE(This.FileHandle)
    	ENDFUNC
    	*------------
    	FUNCTION Done
    		RETURN This.IsDone
    	ENDFUNC
    ENDDEFINE
    

    Joe Kuhn
    See also: VFP Design Pattern Catalog
    Category Design Patterns
  • ( Topic last updated: 2002.11.01 08:33:20 PM )