Open/Closed design principle explained with simple example

Open/Closed design principle is a software design principle which states that every module, class or function of a software should be open for extension but closed for modification. This design principle ensures any new functionality can be added via new classes which means minimum code changes required in existing classes.

Before going ahead we should know why do we need software design principle and what is software design principle.

Open/Closed design principle advantages:

  • Intact existing functionalities as new changes are being done by new methods/classes.
  • Low maintenance time as new changes are being done by new methods/classes.

Let’s understand Open/Close principle with a simple example:

Consider a problem where we have to draw a car.

// Sample code
class car
{
	private:
		int m_year;

	public:
		car (int year): m_year (year)
		{
		}

		int getYear ()
		{
			return m_year;
		}
};

class draw_vehicle
{
	public:
		void draw (car *c)
		{
			cout << "Drawing a car with model year: " << c -> getYear () << endl;
		}
};

Above classes looks like doing the job as each class is following SRP (one responsibility per class) principle too. However, let’s look above classes more closely from extension and modification perspective.

  • If we need to add a new vehicle class “Train” then we need to modify class “draw_vehicle” along with a new class creation.
  • Since “draw_vehicle” class is modified, hence these modification might fail existing functionality related to class “car” also.

Above points are violation of Open/Closed principle which states that “class should be open for extension but closed for modification“.

Let’s redesign the classes keeping Open/Closed principle in mind.

// sample code
class shape
{
	public:
		virtual void draw () = 0;
};

class shape_car: public shape
{
	private:
		int m_year;

	public:
		shape_car (int year): m_year (year)
		{}

		virtual void draw ()
		{
			cout << "Drawing a car with model year: " << m_year << endl;
		}
};

class shape_train: public shape
{
	private:
		int m_year;
		int m_bogies;

	public:
		shape_train (int year, int bogies): m_year (year), m_bogies (bogies)
		{
		}

		virtual void draw ()
		{
			cout << "Drawing a train with model year: " << m_year << " and bogies: " << m_bogies << endl;
		}
};

Let’s analyse above classes from Open/Close principle

  • If we have to add a new vehicle class “bike” then none of the existing class will be modified and new functionality will be supported via extension of existing class “shape“. This ensures that Open/Close Principle is being followed.
// Sample code
class shape_bike: public shape
{
	private:
		int m_year;
		int m_engine_cc;

	public:
		shape_train (int year, int engine_cc): m_year (year), m_engine_cc (engine_cc)
		{
		}

		virtual void draw ()
		{
			cout << "Drawing a bike with model year: " << m_year << " and engine: " << m_engine_cc << " CC "<< endl;
		}
};

Leave a Reply

Your email address will not be published. Required fields are marked *