Day 26 of Learning C++: Exploring Design Patterns
Hello, eager learners! It's Day 26 of your fantastic 100-day C++ learning journey, and today, we're exploring design patterns. Design patterns are reusable solutions to common problems encountered in software design. They provide a structured approach to solving design issues and can significantly enhance the maintainability and flexibility of your code.
1. Creational Design Patterns: Object Creation
Singleton Pattern:
Ensures a class has only one instance and provides a global point of access to it. This is useful when exactly one object is needed to coordinate actions across the system.
class Singleton {
public:
static Singleton& getInstance() {
static Singleton instance;
return instance;
}
// Other member functions...
private:
Singleton() {} // Private constructor to prevent instantiation
};
Factory Method Pattern:
Defines an interface for creating an object but leaves the choice of its type to the subclasses, creating an instance of one of several possible classes.
class Product {
public:
virtual void display() = 0;
};
class ConcreteProductA : public Product {
public:
void display() override {
// Display implementation for Product A
}
};
class ConcreteProductB : public Product {
public:
void display() override {
// Display implementation for Product B
}
};
class Creator {
public:
virtual Product* createProduct() = 0;
};
class ConcreteCreatorA : public Creator {
public:
Product* createProduct() override {
return new ConcreteProductA();
}
};
class ConcreteCreatorB : public Creator {
public:
Product* createProduct() override {
return new ConcreteProductB();
}
};
2. Structural Design Patterns: Object Composition
Adapter Pattern:
Allows the interface of an existing class to be used as another interface. It is often used to make existing classes work with others without modifying their source code.
class OldInterface {
public:
virtual void request() {
// Old interface implementation
}
};
class NewInterface {
public:
virtual void specificRequest() = 0;
};
class Adapter : public NewInterface, private OldInterface {
public:
void specificRequest() override {
request(); // Calls the old interface method
}
};
Decorator Pattern:
Attaches additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.
领英推荐
class Component {
public:
virtual void operation() = 0;
};
class ConcreteComponent : public Component {
public:
void operation() override {
// Basic operation implementation
}
};
class Decorator : public Component {
public:
Decorator(Component* component) : component(component) {}
void operation() override {
component->operation(); // Delegate to the wrapped component
}
private:
Component* component;
};
class ConcreteDecorator : public Decorator {
public:
ConcreteDecorator(Component* component) : Decorator(component) {}
void operation() override {
Decorator::operation();
// Additional operation
}
};
3. Behavioral Design Patterns: Object Interaction
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.
#include <iostream>
#include <vector>
class Observer {
public:
virtual void update() = 0;
};
class Subject {
public:
void addObserver(Observer* observer) {
observers.push_back(observer);
}
void notifyObservers() {
for (Observer* observer : observers) {
observer->update();
}
}
private:
std::vector<Observer*> observers;
};
class ConcreteObserver : public Observer {
public:
void update() override {
std::cout << "Received update notification." << std::endl;
}
};
Strategy Pattern:
Defines a family of algorithms, encapsulates each algorithm, and makes them interchangeable. Strategy lets the algorithm vary independently from clients that use it.
class Strategy {
public:
virtual void execute() = 0;
};
class ConcreteStrategyA : public Strategy {
public:
void execute() override {
// Implementation of strategy A
}
};
class ConcreteStrategyB : public Strategy {
public:
void execute() override {
// Implementation of strategy B
}
};
class Context {
public:
void setStrategy(Strategy* strategy) {
this->strategy = strategy;
}
void executeStrategy() {
strategy->execute();
}
private:
Strategy* strategy;
};
Key Takeaways for Day 26:
Creational design patterns deal with object creation mechanisms, providing flexibility in object creation.
Structural design patterns focus on object composition, facilitating the creation of complex structures.
Behavioral design patterns address object interaction and responsibility delegation, improving the flexibility and maintainability of code.
Next Steps:
For Day 27, let's explore error handling and exception handling in C++. Understanding how to handle errors gracefully is a crucial aspect of robust software development.
Keep up the fantastic work on your C++ journey! If you have questions or insights to share, feel free to reach out. Happy coding with design patterns! ????
#CppJourneyWithLee #cpp #CPP #cplusplus #programming #learningjourney #designpatterns #creationalpatterns #structuralpatterns #behavioralpatterns