“Strategy Design Pattern” — Supports the ‘O’ of SOLID Principle

Sohini Dhar
2 min readJun 9, 2021

--

The “O” of SOLID Principles stands for “Open for Extension and Closed for Modification”. In Object-Oriented Programming, good code should contain classes that follow the SOLID Principles. So where exactly can we use this design pattern and what is the problem we will be solving?

Let us assume we have some data in a text file and the same data in a binary file. The caller should not be bothered about how to read the data, it should have a method that says getData() and should know the type of file from where the data has to be parsed. A strategy interface solves this problem very easily. And, in later stages, the developer can also extend the interface to read data from an XML file. This shows the code supports both the Open-Close Principle and implements a proper Design Pattern to solve a problem. Another example where Strategy patterns can be used effectively would be if we want to build an application irrespective of the Operating system. We know there are methods/functions which are OS-specific. We can encapsulate them into classes, derive the OS Specific classes from an interface, and write a factory method which the caller can call to run the function without bothering about the inner implementation. Let us try to understand the concept with some pseudo-code.

Interface Class

namespace
{
enum class DataFormatType
{
TextFile,
BinaryFile,
};
class IDataReader
{
public:
virtual const int getData() const= 0;
}
}

Text File Reader Concrete Class

namespace
{
class TextFileReader : public IDataReader
{
public:
TextFileReader(std::ifstream& inputFile) : inputFile(inputFile)
{
}
const int getData() const override
{
//Text File Reader Implementation
}
private:
ifstream& inputFile;
};
}

Binary File Reader Concrete Class

namespace
{
class BinaryFileReader : public IDataReader
{
public:
BinaryFileReader(std::ifstream& inputFile) : inputFile(inputFile)
{
}
const int getData() const override
{
//Binary File Reader Implementation
}
private:
ifstream& inputFile;
};
}

Factory Method to call the concrete classes

namespace
{
std::unique_ptr< IDataReader > createDataReaderFactory( DataFormatType d , std::ifstream& in)
{
switch(d)
{
case DataFormatType::TextFile : return std::make_unique< TextFileReader > (in);
case DataFormatType::BinaryFile : return make_unique < BinaryFileReader > (in);
default: return nullptr;
}
}
}

caller

int main()
{
//can have a text file called TestTextFile.txt containing one integer type data
.....
auto p = createDataReaderFactory( DataFormatType::TextFile, input); // input here is the ifstream object
int val = p->getData(); // We will get the value from the text file here without bothering about the inner details.
....
return 0;
}

Knowing and implementing this pattern can solve a lot of complex issues, and save the developer from a lot of if/else statements that would be used otherwise.

int main()
{
//can have a text file called TestTextFile.txt containing one integer type data

auto p = createDataReaderFactory( DataFormatType::TextFile, input); // input here is the ifstream object
int val = p->getData(); // We will get the value from the text file here without bothering about the inner details.
}

Please follow, like, comment, share if you like this.

--

--

Sohini Dhar
Sohini Dhar

Written by Sohini Dhar

Programmer, Traveler, Adventurer!!!!

No responses yet