Applying Strategy Pattern in C++ Applications

原创 2004年10月05日 11:44:00

Applying Strategy Pattern in C++ Applications
By T. Kulathu Sarma

When it is possible to have several different algorithms for performing a process Strategy Pattern can be used to determine the best solution.  <?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />


Software consulting companies do projects for their customers on a "Fixed Price basis" or on a "Time and Material basis". Also, the projects can be either onsite or offsite. Usually, the customers specify how they want the project to be done (Fixed price or Time and Material basis, onsite or offsite). The ultimate aim of the consulting company is to complete the project in the scheduled time, however the Strategy (or the policy) they adapt in doing the project may differ, depending on how they do the project. This is a real life example, where a Strategy Pattern is applied.

Strategy Pattern can also be used in the software design. When it is possible to have several different algorithms for performing a process, each of which is the best solution depending on the situation, then a Strategy Pattern can be used. This article is all about Strategy Pattern. It uses a programming example to explain what, when and why a Strategy Pattern is needed. Benefits and drawbacks of using Strategy Pattern in software design is discussed. Three different approaches for implementing the Pattern in C++ and known uses of Strategy Pattern are also presented in this article.

Design Patterns are meant to provide a common vocabulary for communicating design principles. Strategy Pattern is classified under Behavioral Patterns in the book, Design Patterns: Elements of Reusable Object-Oriented Software by Erich Gamma et al. (Addison-Wesley, 1995). In this article, I will be using the terms used by 'Gang of Four (GoF)' to explain Strategy Pattern.

An Example

A progress indicator is a window that an application can use to indicate the progress of a lengthy operation (for example, an Installation Process). It is usually a rectangular window that is gradually filled, from left to right, with the highlight color as the operation progresses. It has a range and a current position. The range represents the entire duration of the operation, and the current position represents the progress the application has made towards completing the operation. The range and the current position are used to determine the percentage of the progress indicator to fill with the highlight color.

Even though left to right direction is commonly used for filling in most progress indicators, other directions like right to left, top to bottom and bottom to top can also be used for filling. I have seen some progress indicators using a bottom to top filling. Also, different types of fills like continuous fill, broken fill or pattern based fills can be used with a given filling direction.

In short, the purpose of the progress indicator remains unchanged; however, the filling direction or the filling algorithm can change. Therefore, the family of algorithms used for filling can be encapsulated in a separate filler class hierarchy and the application can configure the progress indicator with a concrete filler class. An algorithm that is encapsulated in this way is called a Strategy. So, what is a Strategy Pattern? The Strategy Pattern is a design pattern to encapsulate the variants (algorithms) and swap them strategically to alter system behavior without changing its architecture. According to GoF, Strategy Pattern is intended to, Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it.

Strategy Pattern has three participants that include Strategy, Concrete Strategy and Context. In this example, the abstract filler class CFiller, is referred as the Strategy, the concrete filler classes CLToRFiller (for providing Left to Right fill) and CRToLFiller (for providing Right to Left fill) are referred as Concrete Strategies and the progress indicator CProgressIndicator, is referred as the Context using Strategy. The application using the progress indicator is the client for the Context. Depending on the situation, the client specifies the progress indicator (Context) with a concrete filler class object (Concrete Strategy).

CProgressIndicator maintains a reference to the CFiller object. Whenever there is a progress in the operation, the application notifies CProgressIndicator (by calling a method like SetPos); the CProgressIndicator forwards the request to the CFiller object to visually indicate the change. CFiller subclasses, CLToRFiller and CRToLFiller implement the filling algorithm (in DoFill method). By isolating the filling algorithm from the progress indicator, new filling strategies can be used without changing the progress indicator. Encapsulating the filling algorithm separately eliminates the need for multiple conditional statements to choose the right Strategy for filling. UML diagram showing the relationship between the participants of the Strategy Pattern is presented below.

<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" />

Approaches for implementing Strategy Pattern in C++

Push and Pull methods can be used to provide a means of safe data exchange and reduce the coupling between the Context and Strategy objects. In the Push method, the Context pushes the data to the Strategy object and the Strategy uses the data to implement the algorithm. In this method, Context might pass some unwanted data to the Strategy object, as all Concrete Strategy objects might not require all the data. On the other hand, in the Pull method, the Context, registers itself with the Strategy which in-turn maintains a reference to the Context object and pulls the required data from it. In this method, the Context must define an elaborate set of Get methods for the Strategy objects to pull the required data. Since, the Strategy maintains a reference to the Context, both the classes are tightly coupled. The choice of Push or Pull method purely depends on the requirement.

This article discusses three different approaches for implementing the Strategy Pattern in C++. The approaches described below can use either a Push or Pull method.

Strategy object as a required parameter to the Context
Strategy object as an optional parameter to the Context
Strategy as a template class parameter to the Context

Strategy object as a required parameter to the context

In this approach, the progress indicator (Context) takes a filler (Strategy) object as a parameter in its constructor and maintains a reference to it. The progress indicator delegates the request to the filler object when SetPos method is called. Listing 1 shows this approach. Also, Layout Manager in Java uses this approach, see Java and Strategy Pattern for explanation.


  1. The progress indicator depends only on the interface of the filler class and does not interact directly with the concrete subclasses of the filler class.

  2. Application can select the required filler class object at run-time. SetFiller method can be used to change the filler class object after creating the progress indicator.


  1. Application using the progress indicator must be aware of all the filler classes and must supply the progress indicator with the required filler class object.

  2. Progress indicator is not having any control on the scope or the lifetime of the filler class object.

Strategy object as an optional parameter to the Context

This approach is similar to the first approach, but the filler object (Strategy) is taken as an optional parameter when progress indicator (Context) is created. The progress indicator creates a default filler object (Left to Right filler), if the application did not specify the filler object during construction. Listing 2 contains C++ sample showing this approach. Demo application provided with this article uses this technique.


  1. Application can specify the filler object only when it needs to change the default filler object.

  2. Application can select the required filler class object at run-time. SetFiller method can be used to change the filler class object after creating the progress indicator.


  1. Progress indicator must be aware of the concrete filler class CLToRFiller, for providing the default behavior. This increases the coupling between the CProgressIndiator and CLToRFiller classes.

  2. Progress indicator has control only on the lifetime of the default filler object, which is CLToRFiller object in this case. But, it is not having any control on the scope or the lifetime of other filler class objects.

Strategy as a template class parameter to the Context

If there is no need to change the filler class (Strategy) at run time, it can be passed as a template parameter to the progress indicator (Context) class at compile time. Listing 3 shows this approach. Active Template Library (ATL) uses a variation of this approach to select the required CCOMObjectxxx<> in which the Context is passed as a parameter to the Strategy class (Pull method). See ATL and Strategy Pattern for explanation.


  1. Progress indicator template class is instantiated only with concrete filler classes, so there is no need for the abstract CFiller class.

  2. Passing filler class as a template parameter provides an early binding between the progress indicator and the filler classes. This avoids runtime overhead and increases the efficiency.

  3. Progress indicator is responsible for the creation of the filler class object. Therefore, it has full control on the lifetime of the object.


Selecting filler class at compile time provides no room for changing the object at runtime.

Benefits in using Strategy Pattern

  1. A family of algorithms can be defined as a class hierarchy and can be used interchangeably to alter application behavior without changing its architecture.

  2. By encapsulating the algorithm separately, new algorithms complying with the same interface can be easily introduced.

  3. The application can switch strategies at run-time.

  4. Strategy enables the clients to choose the required algorithm, without using a "switch" statement or a series of "if-else" statements.

  5. Data structures used for implementing the algorithm is completely encapsulated in Strategy classes. Therefore, the implementation of an algorithm can be changed without affecting the Context class.

  6. Strategy Pattern can be used instead of sub-classing the Context class. Inheritance hardwires the behavior with the Context and the behavior cannot be changed dynamically.

  7. The same Strategy object can be strategically shared between different Context objects. However, the shared Strategy object should not maintain states across invocations.

Drawbacks in using Strategy Pattern

  1. The application must be aware of all the strategies to select the right one for the right situation.

  2. Strategy and Context classes may be tightly coupled. The Context must supply the relevant data to the Strategy for implementing the algorithm and sometimes, all the data passed by the Context may not be relevant to all the Concrete Strategies.

  3. Context and the Strategy classes normally communicate through the interface specified by the abstract Strategy base class. Strategy base class must expose interface for all the required behaviors, which some concrete Strategy classes might not implement.

  4. In most cases, the application configures the Context with the required Strategy object. Therefore, the application needs to create and maintain two objects in place of one.

  5. Since, the Strategy object is created by the application in most cases; the Context has no control on lifetime of the Strategy object. However, the Context can make a local copy of the Strategy object. But, this increases the memory requirement and has a sure performance impact.

Known Uses

This section presents known uses of Strategy Pattern. Some of the known uses presented in this section are taken from the GoF book on Design Patterns.

ATL and Strategy Pattern

ATL stands for Active Template Library. It is a collection of template based classes intended to hide most of the complexities behind COM development and provide a small footprint for the component itself.

In ATL, the class of the COM object is not instantiated directly. It acts as a base class for a CComObjectxxx<> class. For example, if CMyClass is the COM object class, then the most derived class in the class hierarchy will be a CComObjectxxx<CMyClass>. CComObjectxxx<> provides the implementation of IUnknown methods. However, these classes not only handle the basics of reference counting, but also interact appropriately with the lock count of the module. CComObjectxxx<> classes differ slightly in their behavior and the choice of the CComObjectxxx<> depends on the aggregation, locking and destruction models. These are generic and optional features that can be applied to any COM object. For example, some COM Objects can support aggregation, some may not and some may only support aggregation. This is again true with the other two features - locking and destruction. These features can be accommodated and easily switched around without changing the functionality of the COM object. CComObject<>, CComAggObject<>, CComObjectCached<>, CComObjectNoLock<> are some of CComObjectxxx<> classes.

ATL uses the Strategy Pattern to encapsulate the behavior in different CComObjectxxx<> classes and the COM class can select the required CComObjectxxx<> based on the functionality needed. Since, there is no need to change a Strategy at run-time; ATL uses C++ template for the implementation of the Strategy Pattern. ATL selects a Strategy (CComObjectxxx<>) and passes the Context (CMyClass) as a parameter to the Strategy.

Java and Strategy Pattern

Strategy Pattern is also used in the implementation of the Layout Manager in Java. The Layout manager can be configured with a layout object, which can be an object of a FlowLayout, a CardLayout, a GridLayout or a GridBagLayout class. These classes encapsulate the algorithms for laying out visual components and they provide several different layouts for viewing the same visual widgets.

Other known uses

Borland's ObjectWindows uses strategies to encapsulate validation algorithms for dialog box entry fields. For example, a numeric field might have a validator to check proper range, a date field might have a validator to check the correctness of the input date and string field might have a validator for proper syntax.

ET++ uses the Strategy Pattern to encapsulate layout algorithms for text viewers.

Strategy Pattern is also used in many popular sorting algorithms, graph layout algorithms and memory allocation algorithms.

Bridge and Strategy

Often, the Strategy Pattern is confused with the Bridge Pattern. Even though, these two patterns are similar in structure, they are trying to solve two different design problems. Strategy is mainly concerned in encapsulating algorithms, whereas Bridge decouples the abstraction from the implementation, to provide different implementation for the same abstraction.


This article is all about the Strategy Pattern, it not only talked about what Strategy Pattern is, but also emphasized why and when it is needed. I have used this pattern in many of my projects including the implementation of Lexical Analyzer and Parser classes. This pattern can be applied wherever there are several different ways of performing the same task. In short, the Strategy Pattern can be used to encapsulate varying algorithms and use them to change the system behavior without altering its architecture.


Special thanks to my friend Sree Meenakshi for her helpful suggestions in improving the clarity and presentation of this article.

Listing 1 - Strategy object as a required parameter to the Context





Listing 2 - Strategy object as an optional parameter to the Context







Listing 3 - Strategy as a template class parameter






设计模式 - 策略模式(Strategy Pattern) 详解

策略模式(Strategy Pattern) 详解 本文地址: 本文版...
  • u012515223
  • u012515223
  • 2014年05月22日 13:31
  • 3001

设计模式之三 --- 策略模式(Strategy Pattern)

策略模式(Strategy):它定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户。 【1】基本概念           策略模式是一种定义一系列算...
  • cjjky
  • cjjky
  • 2012年03月05日 22:27
  • 12829

Java设计模式——策略模式(Strategy Pattern)

Java设计模式——策略模式(Strategy Pattern) 场景一 描述:刘备要到江东娶老婆了,走之前诸葛亮给赵云(伴郎)三个锦囊妙计,说是按天机拆开解决棘手问题,嘿,还别说,真是解决了大问题,...
  • u012401711
  • u012401711
  • 2016年09月07日 21:16
  • 1351

浅谈设计模式(Bridge pattern和 Strategy pattern)

  这段时间做项目,需要用到多种设计模式的结合,之前菜菜本人只用过简单工厂和单态模式,于是又抓紧多学了些,以下,菜菜将就Bridge pattern和Strategy pattern两者的比较,来一起...
  • hust_yh
  • hust_yh
  • 2011年01月10日 19:55
  • 2369


  • a137268431
  • a137268431
  • 2014年03月03日 14:33
  • 1157

《Java与模式》学习笔记之九-----策略模式(Strategy Pattern)

策略模式是对算法的包装,把使用算法的责任和算法本身分隔开,委派给不同的对象管理。策略模式通常把一系列的算法包装到一系列的策略类里面,作为一个抽象策略类的子类。何时使用策略模式:1)  如果在一个系统里...
  • surprisesdu
  • surprisesdu
  • 2006年03月24日 10:48
  • 7948

Head First 设计模式——策略模式(Strategy Pattern)——Python实现

  本作品采用知识共享署名-非商业性使用-相同方式共享 3.0 Unported许可协议进行许可。允许非商业转载,但应注明作者及出处。 作者:liuyuan_jq2011-06-13 策略模式定义 定...
  • liuyuan_jq
  • liuyuan_jq
  • 2011年06月13日 17:41
  • 1498

Applying Domain-Driven Design and Patterns(ADDDP) With examples in C# and .NET

Applying Domain-Driven Design and Patterns(ADDDP) With examples in C# and .NET是在Martin Fowler的PoE...
  • shanyou
  • shanyou
  • 2007年07月06日 21:08
  • 657


  • MonroeD
  • MonroeD
  • 2016年04月08日 01:16
  • 444

设计模式总结之Composite Pattern(组合模式)

  • cooldragon
  • cooldragon
  • 2016年08月11日 00:49
  • 1322
您举报文章:Applying Strategy Pattern in C++ Applications