Design patterns are a set of common programming design elements that can be used to simplify the solution of recurring problems. With the use of OO techniques, design patterns can be cleanly implemented as a set of classes that work toward the solution of a common goal. These designs can then be reused and shared across applications.
Over the last few years, design patterns have been developed for common problems occurring in several areas of programming. When designing algorithms for options and other derivatives, design patterns can provide solutions that are elegant and reusable (when supporting libraries are employed). Thanks to the inherent ability of the C++ language to create efficient code, these solutions also have high performance.
Overview of design patterns: You will learn how design patterns can help in the development of complex applications, with the ability to reuse common patterns of programming behavior. Using design patterns can also make solutions more robust and easier to understand, because patterns provide a common language that allows developers to discuss complex problems. Such design techniques have also been made available through libraries that implement some of the best-known design patterns.
Factory method pattern: A factory method is a design pattern that allows objects to be created in a polymorphic way, so the client doesn’t need to know the exact type of the returned object, only the base class that provides the desired interface. It also helps to hide a complex set of creation steps to instantiate particular classes.
Singleton pattern: The singleton pattern is used to model situations in which you know that only one instance of a particular class can validly exist. This is a situation that occurs in several applications, and in finance, I present the example of a clearing house for options trading.
Observer pattern: Another common application of design patterns is in processing financial events such as trades. The observer design patterns allow you to decouple the classes that receive trading transactions from the classes that process the results, which are the observers. Through the observer design pattern, it is possible to simplify the logic and the amount of code necessary to support these common operations, such as the development of a trading ledger, for example.
Visitor pattern: We also investigate the visitor pattern that allows two or more class hierarchies to cooperate in performing dynamic method dispatching.
Introduction to Design Patterns
Design patterns have been introduced as a set of programming practices that simplify the implementation of common coding problems. As you study the behavior of OO applications, there are tasks and solution strategies that occur frequently and can be captured as a set of reusable classes.
Object-oriented programming provides a set of principles that can facilitate the development of computer software. Using OO programming techniques, you can easily organize your code and create high-level abstractions for application logic and commonly used component libraries. In this way, OO techniques can be used to improve and reuse existing components, as well as simplify the overall development. OO programming promotes a way of creating software that uses logical elements operating at a higher level of abstraction.
Factory method: In the factory method design pattern, the objective is to hide the complexity and introduce indirection when creating an instance of a particular class. Instead of asking clients to perform the initialization steps, factory methods provide a simple interface that can be called to create the object and return a reference.
Singleton: A singleton is a class that can have at most one active instance. The singleton design pattern is used to control access to this single object and avoid creating copies of this unique instance.
Observer: The observer pattern allows objects to receive notifications for important events occurring in the system. This pattern also reduces the coupling between objects in the system, since the generator of notification events doesn’t need to know the details of the observers.
- Visitor: The visitor pattern allows a member function of an object to be called in response to another dynamic invocation implemented in a separate class. The visitor pattern therefore provides the mechanism for dispatching messages based on a combination of two objects, instead of the single object-based dispatch that is common with OO languages.
In the next few sections, you will see how these design patterns can be implemented in C++, with examples of how they occur in options and derivatives applications.
The Factory Method Design Pattern
A factory design pattern is a technique used to indirectly create objects of a particular class. This pattern is important because it is frequently useful to access newly allocated objects without having to directly perform the work necessary to create them. For example, using the factory method design pattern, it is possible to avoid the use of the new keyword to create an object, along with the parameters required by the constructor.
Most of the time, there is no need for the client to provide parameters for construction of the object. For example, if the objects require the allocation of additional resources, such as a file or a network connection, the client is relieved from acquiring these resources.
Sometimes the object depends on internal implementation details, such as a private class, that are not available to clients. In this case, providing a factory method is the only way to create new instances of the object.
The exact sequence of events necessary to create an object may change. In that case, it is better to provide a factory method that hides this complexity. Users of the class will not have to worry if the way the object is created is updated.
More importantly, factory methods can be used to simplify polymorphic object creation . For example, when an object is created using the new operator, the concrete type of the returned object has to be known by the client. On some applications, this might be undesirable, because the real type of the needed object could be any one within a set of derived classes. Using a factory method, it is possible to delegate the creation of the object so that the client code doesn’t need to know about the concrete type. As a result, the returned object may be any one of the subtypes of the original type.
Factory methods in C++ are declared as static member functions. Such a member function doesn’t depend on an instance of the class to be executed. The syntax for member functions is simply ClassName::functionName() , with parameters added as needed.
The factory method design pattern is also used as a foundation for more complex design patterns. For example, you will notice that other patterns such as singleton use a factory method to control the creation of new instances of a particular class.
In options and derivatives applications, the factory method is commonly used. A situation where the use of a factory method is desirable is when you need to load data objects. The data source used can vary from a local file to a URL, and the parsing of that data is not an important part of the overall algorithm. In that case, abstracting the creation of the data source can be an important application of the factory method.
In the example that follows, you can see how a DataSource class can be implemented. The goal of this class is to hide the process of creating a new data source, so the clients have no access to the real constructor of the class. Instead, clients need to use a factory method, which is implemented as a static member function of the DataSource class.
When using factory methods, it is frequently useful to hide the real implementation of the constructor. This can be done through careful use of the private modifier. The goal is to grant access to the constructor only to the class itself (and to any declared friends of the class). This is done to the standard constructor as well as to the copy constructor.
Declaration of the DataSource Class
The implementation of the DataSource class is shown in Listing 5-2. The constructors and destructor are standard, considering the fact that the constructor is private. The interesting part of the DataSource implementation is the getInstance method , which returns a new data source. This implementation receives only one parameter that is created by the method, but consider the general case in which a list of complex or implementation-dependent objects need to be retrieved in order to call the new operator for the DataSource class.
At the end of getInstance, the member function returns a pointer to the newly created object. Another option is to return a smart pointer, such as std::shared_ptr, which would make it easier to manage the lifetime of the allocated object.
Implementation of the DataSource Class
The Singleton Pattern
One of the simplest and most used design patterns is the singleton. With this design pattern, a single object is used to represent a whole class, so that there is a central location where services managed by that class can be directed.
Unlike standard classes, a singleton class represents a single resource that cannot be replicated. Because of this, the singleton pattern restricts the ability to create new objects of a particular class, using a few techniques that will be discussed later in this section. C++ provides all the features necessary to implement singleton patterns with high performance.
In programming, the notion of an entity that is unique across the application is frequently encountered. An example in options programming is an entity called a clearing house. A clearing house is an institution that provides clearing services for trades on options and derivatives. The clearing house makes sure that every trade has collateral so that counterpart risk is reduced, among other attributions. For example, if a trader sells options in a particular instrument, the clearing house will make sure that the trader has enough margin to satisfy the requirements of that particular trade.
Example Objects That Can Be Implemented As a Singleton Design Pattern
Object | Notes |
---|---|
Clearing house (finance) | A single clearing house is used for all trades. |
Root window (GUI) | Each GUI application communicates with only one root window. |
Operating system | An object representing operating system services is unique through the application. |
Company CEO | An object representing the CEO has only one instance. |
Memory allocator (system services) | Each application uses a single memory allocator, which can be represented by a singleton. |
To implement a singleton in C++, the first step is to make sure that there is only one object of that class in the application. To do this, it is necessary to disallow the creation of new objects of that particular class. You can take advantage of the ability provided by C++ to make class members inaccessible to users of the class through the private keyword. Users then cannot use the new keyword to generate new objects of that particular class.
On the other hand, it is necessary to create some mechanism for clients to access an instance of the singleton class. This is usually done using a static member function that returns the single existing object or creates a new object if necessary before returning it. Using such an access member function, clients can access the public interface of the singleton object. At the same time, they’re not allowed to create or manage the lifecycle of that object.
Clearing House Implementation in C++
A possible implementation for the clearing house class using the singleton pattern is presented in Listings 5-1 and 5-2. The class has two parts: the first part deals with the management of the singleton object. This is done through the definition of private constructor and destructors, as well as the presence of a static member function getClearingHouse, which returns a reference to the singleton instance.
The second part of the implementation deals with the responsibilities of the clearing house, represented here as the member function clearTrade. This function receives as an argument a Trade object, which is not defined here but contains all the data associated with the transaction.
Header File for the ClearingHouse Class, Which Implements the Singleton Design Pattern
The implementation file contains the member function ClearingHouse::getClearingHouse. This function first checks the static variable s_clearingHouse to determine if it has been previously allocated. If the object doesn’t exist, then the static function can create a new object, store it for further use, and return a reference.
Implementation File for ClearingHouse Class, Which Uses the Singleton Design Pattern
The Observer Design Pattern
A frequent situation that occurs in complex systems is the occurrence of events that trigger further actions. For example, an event that happens on financial systems is the completion of an options trade. When a new trade is completed, several actions need to be performed to update the system and reflect the new positions in the ledger.
The observer design pattern is a very powerful strategy to manage event updates, based on a standard technique that gives clients the ability to listen to events and updates to a particular object and react accordingly.
The Subject class has at least three member functions that enable the functionality of the observer design pattern. The first function is addObserver, which takes as a parameter a reference to an observer object. The addObserver function maintains the reference in an internal list of objects that are interested in receiving notifications.
The second member function in the subject interface is removeObserver, which simply removes a given observer from the notification list. Finally, there is a member function called triggerNotifications that is used to send the notifications to all objects that registered with the Subject class.
The observer design pattern can readily be implemented in C++ using abstract classes. You can see a sample implementation in Listings 5-5 and 5-6. The first class that is considered is the Observer class. This class has the purpose of providing a simple interface for the observer. Its only nontrivial member function is notify, which is an abstract function called by the subject when a new event occurs. As a result, any class deriving from observer needs to process the notification in a user-defined way.
Consider how the Observer class is independent of any implementation detail for the trading ledger system. This definition could be reused as part of a design pattern’s library. Similar techniques can be used to simplify the creation of other design patterns as well.
Here, the notification implementation just calls the processNewTrade function , which stores the trade returned by the ledger object.
The addObserver and removeObserver functions operate with std::shared_ptr templates for the observer object. The goal is to avoid unnecessary memory issues by delegating the memory deallocation to shared pointers from the standard library. These two functions operate as an interface to the internal m_observers container.
It simply loops through all elements stored in the m_observers set and sends a notification to these registered objects. Each such object that implements the observer interface can now respond to the event as needed.
Complete Code
Header File Containing Interfaces for the Observer Design Pattern
Implementation File with C++ Definitions for the Observer Design Pattern
The Visitor Pattern
Another useful pattern that has been used in several real-life applications is the visitor pattern. In this pattern, the goal is to allow dynamic dispatching of objects in two separate hierarchies of types. This design pattern has application in many common problems occurring in finance.
The problem solved by the visitor pattern is the application of dynamic rules to two or more polymorphic objects at the same time. This is necessary because C++, like some other object-oriented languages, uses single dispatch to process polymorphic calls.
Consider, for example, the case of a class representing derivative contracts. The class can have several polymorphic (virtual) methods, including one for displaying the profit/loss chart.
The SimpleDerivativeContract class has a virtual method that is able to present a chart with profit/loss for the position. But to do this, the derivative object needs to coordinate with a second class, called ChartDisplay. Both ChartDisplay and SimpleDerivativeContract have polymorphic methods that interact with each other, but in C++ the virtual dispatch is done in just a single method. For example, ChartDisplay might have specialized subclasses such as PDFChart and HTMLChart.
Conclusion
Design patterns are commonly used to develop reusable code, especially when OO techniques are employed. C++ provides strong support for the creation of classes that follow designed patterns such as the ones discussed in the preceding sections.
In this chapter, you saw examples and implementation in C++ for three common design patterns. First, I presented an overview of design patterns, listing some of the patterns that are most commonly used in the implementation of algorithms for options and derivatives. Then, you learned about the factory method design pattern, which is one of the easiest and most widely used patterns of OO programming.
The singleton pattern is used when it is necessary to enforce the existence of a single instance for a particular class. You saw the example of a clearing house implementation, where the single instance must be accessible to all clients in the application.
The observer pattern is a third example of how to implement such designs in C++. You saw how this pattern can be employed to solve the problem of trading processing. Using this design pattern, it is possible to decouple the classes that receive the events from specific classes that listen to the events and perform further processing.
While object-oriented design patterns provide several elegant solutions for commonly found problems in financial programming, there are situations in which a non-OO strategy may be a better solution. In these situations, C++ promotes the use of templates, an implementation technique in which the compiler is allowed to generate code based on parameterized types. In the next chapter, you will see several examples in which template-based algorithms can be used to improve the performance and flexibility of algorithms for options and derivatives trading.