Pure Virtual Functions

Design Patterns with Abstract Classes

What are some common design patterns that utilize abstract classes and interfaces?

Abstract art representing computer programming

Abstract classes and interfaces are fundamental in many object-oriented design patterns.

Here are a few common design patterns that heavily utilize these concepts:

1. Factory Method

The Factory Method pattern uses abstract classes to define a method for creating objects but allows subclasses to alter the type of objects that will be created.

#include <iostream>
#include <memory>

class Product {
public:
  virtual void Use() = 0; 
};

class ConcreteProductA : public Product {
public:
  void Use() override {
    std::cout << "Using Product A\n";
  }
};

class ConcreteProductB : public Product {
public:
  void Use() override {
    std::cout << "Using Product B\n";
  }
};

class Creator {
public:
  virtual std::unique_ptr<Product> FactoryMethod() = 0; 

  void AnOperation() {
    auto product = FactoryMethod();
    product->Use();
  }
};

class ConcreteCreatorA : public Creator {
public:
  std::unique_ptr<Product> FactoryMethod() override {
    return std::make_unique<ConcreteProductA>();
  }
};

class ConcreteCreatorB : public Creator {
public:
  std::unique_ptr<Product> FactoryMethod() override {
    return std::make_unique<ConcreteProductB>();
  }
};

int main() {
  ConcreteCreatorA creatorA;
  ConcreteCreatorB creatorB;

  creatorA.AnOperation(); 
  creatorB.AnOperation(); 
}
Using Product A
Using Product B

2. Strategy

The Strategy pattern defines a family of algorithms, encapsulates each one, and makes them interchangeable. It uses interfaces to define a common interface for all strategies.

#include <iostream>
#include <memory>

class Strategy {
public:
  virtual void Execute() = 0; 
};

class ConcreteStrategyA : public Strategy {
public:
  void Execute() override {
    std::cout << "Executing Strategy A\n";
  }
};

class ConcreteStrategyB : public Strategy {
public:
  void Execute() override {
    std::cout << "Executing Strategy B\n";
  }
};

class Context {
public:
  Context(std::unique_ptr<Strategy> strategy)
    : strategy_(std::move(strategy)) {}

  void SetStrategy(
    std::unique_ptr<Strategy> strategy) {
    strategy_ = std::move(strategy);
  }

  void ExecuteStrategy() {
    strategy_->Execute(); 
  }

private:
  std::unique_ptr<Strategy> strategy_;
};

int main() {
  auto strategyA =
    std::make_unique<ConcreteStrategyA>();
  auto strategyB =
    std::make_unique<ConcreteStrategyB>();

  Context context(std::move(strategyA));
  context.ExecuteStrategy(); 

  context.SetStrategy(std::move(strategyB));
  context.ExecuteStrategy(); 
}
Executing Strategy A
Executing Strategy B

3. Observer

The Observer pattern defines a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.

This pattern uses interfaces to define the subject and observer roles.

#include <iostream>
#include <vector>
#include <memory>

class Observer {
public:
  virtual void Update(int state) = 0; 
};

class Subject {
public:
  void Attach(std::shared_ptr<Observer> observer) {
    observers_.push_back(observer);
  }

  void SetState(int state) {
    state_ = state;
    Notify();
  }

  void Notify() {
    for (auto& observer : observers_) {
      observer->Update(state_);
    }
  }

private:
  std::vector<std::shared_ptr<Observer>> observers_;
  int state_;
};

class ConcreteObserver : public Observer {
public:
  void Update(int state) override {
    std::cout << "Observer updated with state: "
      << state << "\n";
  }
};

int main() {
  Subject subject;
  auto observer1 =
    std::make_shared<ConcreteObserver>();
  auto observer2 =
    std::make_shared<ConcreteObserver>();

  subject.Attach(observer1);
  subject.Attach(observer2);

  subject.SetState(1); 
  subject.SetState(2); 
}
Observer updated with state: 1
Observer updated with state: 1
Observer updated with state: 2
Observer updated with state: 2

These examples demonstrate how abstract classes and interfaces provide a flexible and powerful way to design and implement various design patterns, promoting code reusability and maintainability.

This Question is from the Lesson:

Pure Virtual Functions

Learn how to create interfaces and abstract classes using pure virtual functions

Answers to questions are automatically generated and may not have been reviewed.

This Question is from the Lesson:

Pure Virtual Functions

Learn how to create interfaces and abstract classes using pure virtual functions

A computer programmer
Part of the course:

Professional C++

Comprehensive course covering advanced concepts, and how to use them on large-scale projects.

Free, unlimited access

This course includes:

  • 124 Lessons
  • 550+ Code Samples
  • 96% Positive Reviews
  • Regularly Updated
  • Help and FAQ
Free, Unlimited Access

Professional C++

Comprehensive course covering advanced concepts, and how to use them on large-scale projects.

Screenshot from Warhammer: Total War
Screenshot from Tomb Raider
Screenshot from Jedi: Fallen Order
Contact|Privacy Policy|Terms of Use
Copyright © 2024 - All Rights Reserved