Category: C++ Design Patterns

https://zain.sweetdishy.com/wp-content/uploads/2026/02/Design-Patterns.png

  • Behavioural Design Patterns in C++

    Behavioural design patterns are ways of organising how different objects in a program communicate with each other. When a program becomes large, many objects need to exchange information or react to certain actions. If this communication is random or unplanned, the code becomes confusing. Behavioural design patterns give a simple and organised approach so every object knows when to speak, when to listen, and what its role is. This makes the whole program easier to understand and work with.

    A good way to understand this is to picture a restaurant. A restaurant runs smoothly only because everyone inside knows how to behave and how to talk to each other. The waiter takes orders from customers, the chef cooks food, the cashier handles bills, and the manager watches over everything. The waiter does not suddenly start cooking, the chef does not run to take orders, and the customers don’t go into the kitchen to ask what is happening. Everyone has a specific job and a clear way to interact. This simple structure keeps the restaurant calm even when many people are involved.

    Now imagine if the behaviour rules inside the restaurant didn’t exist. Customers might walk straight into the kitchen, chefs might run to tables arguing about orders, waiters might forget who to serve because everyone is shouting instructions. It would be a disaster. The same thing happens inside a program when communication is not planned properly. Behavioural design patterns prevent this problem by defining clean paths of communication, just like a restaurant defines who talks to whom and when.

    For example, in the restaurant, when a customer gives an order, the waiter handles it. The chef reacts when the waiter passes the order. The cashier reacts only after the meal is finished and the bill is needed. Everyone responds at the right moment without unnecessary connections or confusion. Behavioural design patterns create this same kind of controlled flow between objects in a program.

    They help cut down those super tight connections between objects, which makes it way easier to change things later. If you want to add a new feature or tweak how something works, you only touch the part that actually needs the change, not the whole project. This keeps the program easier to manage and stops random things from breaking for no reason.

    In short, behavioural design patterns give a simple and natural way for objects to interact, just like people in a well-managed restaurant. They help keep communication clear, roles separate, and the overall system easy to maintain.

    Behavioural Design Patterns Analogy Illustration

    Types of Behavioural Design Patterns

    We have total 11 types of Behavioural Design Patterns in C++. They are −

    • Chain of Responsibility Design Pattern
    • Command Design Pattern
    • Interpreter Design Pattern
    • Iterator Design Pattern
    • Mediator Design Pattern
    • Memento Design Pattern
    • Observer Design Pattern
    • State Design Pattern
    • Strategy Design Pattern
    • Template Method Design Pattern
    • Visitor Design Pattern

    We will cover each of these design patterns in detail in the upcoming chapters. but, for the moment let’s have a quick overview of each of these design patterns −

    Chain of Responsibility Design Pattern

    The Chain of Responsibility design pattern is all about passing a request through a series of handlers until one of them decides to handle it. Instead of one object trying to do everything, the request moves step by step through a chain. Each handler gets a chance to check the request. If it can handle it, it does so. If not, it simply passes it to the next handler in the chain. This makes the system flexible because you can easily add, remove, or rearrange handlers without changing how the request is made.

    A simple example is customer support. When someone sends a support message, it may first go to a basic support agent. If that agent can’t fix the issue, the message goes to a senior agent, and if needed, it moves further to a manager. Each person in the chain checks the problem and handles it only if it matches their level.

    Command Design Pattern

    The Command design pattern is all about turning a request into a simple object. Think of it like writing a small note that says, “Do this task,” and handing that note to someone who knows how to execute it. This pattern separates the person asking for the work from the person who actually does the work. It’s useful when you want tasks to run laterundo tasks, or store a list of actions.

    A real example is a TV remote. When you press the “volume up” button, the remote doesn’t directly change the TV’s volume. Instead, each button has a command object behind it. The remote only triggers the command. The TV carries out the actual work. Because of this, you can add new buttons (new commands) without changing how the remote works. It keeps things flexible and avoids connecting too many things directly.

    Interpreter Design Pattern

    The Interpreter pattern helps you deal with situations where you need to read, process, or understand a small language or set of rules. It breaks down expressions into pieces, and each piece knows how to explain itself.

    A real example is a calculator that handles simple math like “2 + 5 – 3.” The calculator doesn’t memorise every possible calculation. Instead, each symbol (+, -, numbers) has its own meaning. The interpreter reads the whole expression step by step and evaluates it.

    This pattern is useful when you have repeating rules that look like a language. It could be formulas, filters, search queries, or even instructions in a game. Instead of writing long if-else conditions, you build tiny interpreters that understand the rules. It keeps the code clean and allows you to add more rules easily.

    Iterator Design Pattern

    The Iterator pattern gives you a clean way to move through a collection (like a list or array) without exposing how that collection is built. It’s like being given a remote control to move through items one by one without opening the machine.

    A real example is flipping through a photo album using next and previous buttons. You don’t care where the photos are stored, how the system saves them, or what format they’re in. You only move to the next photo, then the next, and so on.

    The iterator pattern keeps things neat. It gives you a consistent way to browse through any collection, even if the collection changes internally. You don’t break the structure because you’re not touching it directly. You just use the iterator to travel through the elements safely and simply.

    Mediator Design Pattern

    The Mediator pattern is like having a friendly coordinator in the middle who makes objects talk to each other without letting them talk directly.

    Imagine a classroom where students want to ask questions. Instead of shouting at each other, they talk to the teacher (the mediator). The teacher controls the flow—who speaks, who responds, who gets attention. Students don’t communicate directly, which keeps order in the room. This pattern helps in avoiding messy connections where every object talks to every other object directly. That causes confusion and also causes too many dependencies.

    With a mediator, everything becomes simpler. Objects only talk to the mediator, and the mediator decides what happens. This makes your code easier to manage, and changes don’t break everything.

    Memento Design Pattern

    The Memento pattern is about saving and restoring an object’s previous state without exposing its internal details.

    Think of a video game’s save feature. When you press “Save Game,” the game stores your location, health, inventory, and progress. Later, when you click “Load Game,” the game puts everything back exactly the way it was.

    The player doesn’t know or care how the game stores all this data—they just know their progress is safe.

    This pattern is very useful when you want undo featureshistory tracking, checkpoints, or safe rollbacks. It keeps the internal information hidden, but still lets you move backward when needed.

    Observer Design Pattern

    The Observer pattern connects one main object (subject) to many observers. When something changes in the subject, all observers get updated automatically.

    A real-life example is subscribing to YouTube channels. When the channel uploads a new video, subscribers get notified instantly. The channel doesn’t message each subscriber manually; the system does it for you.

    This pattern helps when many parts of your program need to know about one event—such as UI updates, notifications, logs, or status changes. It avoids hard connections and makes adding or removing observers easy.

    State Design Pattern

    The State pattern lets an object change its behaviour depending on its current state. A good example is a mobile phone. When it’s locked, pressing the button shows the lock screen. When it’s unlocked, pressing the same button does something different. When it’s in power-saving mode, it behaves differently again.

    The phone is one device, but the behavior changes based on its internal state. This pattern keeps code tidy and avoids big, messy if-else statements everywhere.

    Strategy Design Pattern

    The Strategy pattern lets you swap algorithms or methods at runtime. Imagine choosing travel options in Google Maps: car, bus, walking, bike. The destination is the same, but the route changes.

    Each travel mode is a “strategy.” You pick the one you want. In code, this lets you change behaviour easily—sorting methods, payment methods, filtering styles, etc.—without rewriting everything.

    Template Method Design Pattern

    The Template Method pattern defines the main steps of a process but lets subclasses fill in the details.

    Think of making tea or coffee. The steps are similar: boil water, add ingredients, pour. But tea and coffee differ in the middle step. The “template” is the common structure. This pattern avoids rewriting the whole process and keeps shared logic in one place.

    Visitor Design Pattern

    The Visitor pattern lets you add new operations to a group of objects without modifying the objects themselves.

    Imagine a zoo. You have animals, and different visitors come: a vet checks health, a photographer takes pictures, a feeder gives food. The animals stay the same, but each visitor performs a different action on them. This pattern helps when you want to change anything in the code without touching the classes.

    C++ Implementation of Behavioural Design Patterns all Together

    We will take a combined example to understand how these behavioural design patterns can work together in one simple C++ program. The idea here is not to make the code complicated, but to show how each pattern plays its own role, the same way different people in a team handle their own duties. This example mixes the Strategy Pattern for choosing behaviours, the Observer Pattern for sending updates to interested objects, and the Template Method Pattern for defining a common workflow that different classes can follow.

    In this example, imagine we are building a small game-like setup. We have a character that can use different attack styles, such as a quick attack or a strong attack. This is where the Strategy Pattern helps, because we can swap attack behaviour without changing the character class itself. The character also has fans or followers who want to know whenever the character attacks. This is where the Observer Pattern comes in. The followers get a notification each time an attack happens. Finally, the Template Method Pattern is used to control the general flow of performing an action, like preparing, attacking, and finishing, while still allowing different steps to be customized depending on the type of attack.

    Example image of behavioural design pattern

    By combining these three patterns, we can see how behavioural patterns make communication inside a program clear and flexible. Each pattern solves a different communication problem, and when they are used together, the code becomes cleaner and easier to expand later.

    #include <iostream>#include <vector>#include <string>usingnamespace std;//======= Strategy Pattern ====classAttackStrategy{public:virtualvoidattack()=0;virtual~AttackStrategy(){}};classQuickAttack:public AttackStrategy{public:voidattack()override{
          cout <<"Character performs a quick attack!"<< endl;}};classStrongAttack:public AttackStrategy{public:voidattack()override{
          cout <<"Character performs a strong attack!"<< endl;}};// ====== Observer Pattern =====classObserver{public:virtualvoidupdate(const string& msg)=0;virtual~Observer(){}};classFollower:public Observer{private:
       string name;public:Follower(string n):name(n){}voidupdate(const string& msg)override{
          cout << name <<" received update: "<< msg << endl;}};classSubject{private:
       vector<Observer*> observers;public:voidaddObserver(Observer* obs){
          observers.push_back(obs);}voidnotify(const string& msg){for(Observer* obs : observers){
             obs-<update(msg);}}};// ======= Template Method Pattern ======classActionTemplate{public:voidperformAction(){prepare();mainAction();finish();}protected:virtualvoidprepare(){
          cout <<"Character prepares for action..."<< endl;}virtualvoidmainAction()=0;virtualvoidfinish(){
          cout <<"Character finishes the action."<< endl;}};classAttackAction:public ActionTemplate{private:
       AttackStrategy* strategy;public:AttackAction(AttackStrategy* s):strategy(s){}protected:voidmainAction()override{
          strategy-<attack();}};// ====Putting Everything Together ======classGameCharacter:public Subject{private:
       AttackStrategy* strategy;public:GameCharacter(AttackStrategy* s):strategy(s){}voidsetStrategy(AttackStrategy* s){
          strategy = s;}voidperformAttack(){
          AttackAction action(strategy);
          action.performAction();notify("Character performed an attack!");}};intmain(){// Strategies
       AttackStrategy* quick =newQuickAttack();
       AttackStrategy* strong =newStrongAttack();// Character with default attack
       GameCharacter hero(quick);// Observers
       Follower f1("Follower 1");
       Follower f2("Follower 2");
    
       hero.addObserver(&f1);
       hero.addObserver(&f2);// Perform attacks
       cout <<"\n=== Quick Attack ==="<< endl;
       hero.performAttack();
    
       cout <<"\n=== Switching to Strong Attack ==="<< endl;
       hero.setStrategy(strong);
       hero.performAttack();delete quick;delete strong;return0;}

    Followng is the output of the above code −

    === Quick Attack ===
    Character prepares for action...
    Character performs a quick attack!
    Character finishes the action.
    Follower 1 received update: Character performed an attack!
    Follower 2 received update: Character performed an attack!
    === Switching to Strong Attack ===
    Character prepares for action...
    Character performs a strong attack!
    Character finishes the action.
    Follower 1 received update: Character performed an attack!
    Follower 2 received update: Character performed an attack!
    

    Applications of Behavioural Design Patterns

    Following are the applications of the behavioral design patterns −

    • User Interface Frameworks − In many apps, whenever you click a button or move something, some part of the app needs to react. This is where the Observer pattern helps. For example, when you click a button, all the functions that are waiting for that click get a message. It’s like saying, “Hey, the button was pressed,” and everyone who cares will act. The button doesn’t need to know who is listening, which keeps everything simple.
    • Game Development − In games, characters need to change behaviour quickly. The Strategy pattern makes this easy. For example, an enemy can attack fast when the player is close or switch to a strong attack when the player is far. The enemy stays the same, only the attack style changes. This helps the game feel smarter without writing complicated code.
    • Workflow Systems − Many office or company systems follow fixed steps. But some steps may differ based on what is being processed. The Template Method pattern fits perfectly here. For example, a document approval process always follows the same main flow, but the actions may change based on whether it’s a salary request, a leave request or a project approval. The structure stays the same, only details change.
    • Command Pattern in GUI Apps − Apps like editors or drawing tools use the Command pattern a lot. Every action like copy, paste, cut, undo or redo is stored as a command. This makes undo and redo super easy because the app knows exactly what action happened last. It’s like keeping small notes of everything you did so you can reverse it anytime.
    • Logging Systems − In logging, messages can have different importance levels. For example, some messages are simple, some are warnings and some are errors. With the Chain of Responsibility pattern, each logger checks if it should handle the message. If not, it passes it to the next logger. It works just like passing a complaint to the right person in an office.
    • State Management − Some apps behave differently based on what state they are in. A media player is the best example. When it is in play state, the button plays the song. In pause state, the same button pauses the song. The behaviour changes based on the state, not the button.
    • Data Processing Pipelines − When systems need to understand complex search text or expressions, the Interpreter pattern helps. Think of how a search bar reads your text and understands what you want. It breaks the text, understands the meaning and gives results. This pattern is perfect for situations like this one.
    • Visitor Pattern in Compilers − Compilers need to check code, analyse it and then generate output. The Visitor pattern makes this easier by allowing different operations to run on the same code structure. It’s like different people checking the same file: one checks spelling, another checks grammar, another checks formatting without changing the file itself.
    Use cases of behavioural design pattern

    Conclusion

    In this chapter, we learned about behavioural design patterns and how they make communication inside a program simple and clear. We looked at patterns like StrategyObserver, and Template Method, and also saw how they can all work together in one simple C++ example. These patterns make sure objects talk to each other in a proper way without creating confusion or messy connections. When developers use behavioural patterns, the whole program becomes easier to understand, easier to change later, and easier to grow as new features are added.

  • Visitor Design Pattern in C++

    The visitor design pattern is a way of writing code that helps you in adding new features or new types of work to your classes without changing those classes again and again.

    In programming, we often create classes that represent some real things like shapes, items, files, animals, or anything else. These classes usually have some basic data in them and maybe one or two simple functions. But as the project grows, we want to do more and more operations with these classes. If we keep adding all the new operations directly inside these classes, the classes become very big and hard to read. The visitor pattern helps us avoid making our classes messy.

    Imagine a school building. The school admin cannot repair wires, fix water pipes, clean the classrooms, or check the furniture. Instead, different people come to the school to do these jobs. An electrician comes to fix wires. A plumber comes to fix water pipes. A cleaner comes to clean the rooms. A carpenter comes to fix furniture. The school admin allows different workers to come inside and do their job.

    Visitor Design Pattern Illustration

    This is the exact same idea in the visitor pattern. Your object is like the school building, and the visitor is like the worker who comes to do the job. The building has a door, and the objects have an accept method. The visitor enters through the accept method and then does the required work.

    This pattern is used when you have many different objects and want to keep adding new tasks for those objects. If you try to put every single task inside the object classes, then those classes will become too large. The visitor pattern keeps things neat by moving the work into separate visitor classes.

    Components of the Visitor Pattern

    Following are the main components of the visitor design pattern −

    • Visitor Interface − This is like a plan that tells which types of objects the visitor can work with. It has one visit function for each element type. For example, visitCircle(), visitSquare(), visitRectangle().
    • Concrete Visitor − These are actual classes that do real work. For example, an AreaCalculator visitor will calculate area. A PerimeterCalculator visitor will calculate perimeter. A DrawingVisitor might draw the shapes on screen.
    • Element Interface − This is the main interface that all elements must follow. It usually contains only one function: accept(visitor). Every concrete element must implement this.
    • Concrete Element − These are your real objects. For example, Circle, Square, and Rectangle. They store simple data like radius or side length and implement the accept method.
    • Object Structure − This is usually a list or collection of elements. The visitor will go through this structure and visit each element one by one.
    • Client − The client sets everything up. It creates shapes, creates visitors, and asks the elements to accept the visitors.

    Implementation of the Visitor Pattern in C++

    Let’s implement the visitor design pattern in C++ using the shape example mentioned earlier. We’ll create a visitor interface for calculating area and perimeter, and concrete visitor classes for each operation.

    Steps to Implement Visitor Design Pattern

    Following image shows the steps to implement the visitor design pattern.

    Steps to Implement Visitor Design Pattern
    • First, make a Visitor interface . This interface will have one visit function for every type of element you have. For example, visitCircle, visitSquare, visitRectangle. This tells the visitor what kinds of objects it can work with.
    • Then create Concrete Visitor classes . These are the real workers. Each visitor class does one type of job, like calculating area, perimeter, printing details, drawing shapes, or anything else you need. Inside each visitor class, you write what happens when it visits each element type.
    • After that, make an Element interface . This interface has only one important function: accept . Every element (like Circle, Square, Rectangle) must use this interface. This accept function is the “door” through which the visitor enters.
    • Next, create the Concrete Element classes . These are your actual objects. For example, Circle has radius, Square has side, Rectangle has width and height. Each one must implement the accept function. Inside accept, the element simply calls the visitor’s matching visit method and passes itself.
    • Make an Object Structure . This is just a collection (like a vector, list, or array) that holds all your elements. The visitor will go through this structure and visit each element one by one. This makes it easy to run a visitor on many elements at the same time.
    • Finally, write the Client code . The client creates the objects, puts them into the structure, and creates visitors. Then the client calls accept on each element and passes the visitor. This starts the whole process and makes the visitor run its work on each element.

    C++ Code for Visitor Design Pattern

    In this example, we have an abstract class Shape that defines the interface for shapes like Circle Square , and Rectangle . The Visitor interface declares visit methods for each shape type. The concrete visitor classes AreaCalculator and PerimeterCalculator implement the visit methods to calculate area and perimeter, respectively.

    #include <iostream>#include <vector>#include <cmath>usingnamespace std;// Forward declarationsclassCircle;classSquare;classRectangle;// Visitor InterfaceclassVisitor{public:virtualvoidvisit(Circle* c)=0;virtualvoidvisit(Square* s)=0;virtualvoidvisit(Rectangle* r)=0;};// Element InterfaceclassShape{public:virtualvoidaccept(Visitor* v)=0;};// Concrete Element: CircleclassCircle:public Shape{private:double radius;public:Circle(double r):radius(r){}doublegetRadius(){return radius;}voidaccept(Visitor* v)override{
             v->visit(this);}};// Concrete Element: SquareclassSquare:public Shape{private:double side;public:Square(double s):side(s){}doublegetSide(){return side;}voidaccept(Visitor* v)override{
             v->visit(this);}};// Concrete Element: RectangleclassRectangle:public Shape{private:double width, height;public:Rectangle(double w,double h):width(w),height(h){}doublegetWidth(){return width;}doublegetHeight(){return height;}voidaccept(Visitor* v)override{
             v->visit(this);}};// Concrete Visitor: AreaCalculatorclassAreaCalculator:public Visitor{public:voidvisit(Circle* c)override{double area = M_PI * c->getRadius()* c->getRadius();
             cout <<"Area of Circle: "<< area << endl;}voidvisit(Square* s)override{double area = s->getSide()* s->getSide();
             cout <<"Area of Square: "<< area << endl;}voidvisit(Rectangle* r)override{double area = r->getWidth()* r->getHeight();
             cout <<"Area of Rectangle: "<< area << endl;}};// Concrete Visitor: PerimeterCalculatorclassPerimeterCalculator:public Visitor{public:voidvisit(Circle* c)override{double perimeter =2* M_PI * c->getRadius();
             cout <<"Perimeter of Circle: "<< perimeter << endl;}voidvisit(Square* s)override{double perimeter =4* s->getSide();
             cout <<"Perimeter of Square: "<< perimeter << endl;}voidvisit(Rectangle* r)override{double perimeter =2*(r->getWidth()+ r->getHeight());
             cout <<"Perimeter of Rectangle: "<< perimeter << endl;}};// Client Codeintmain(){
       vector<Shape*> shapes;
       shapes.push_back(newCircle(5));
       shapes.push_back(newSquare(4));
       shapes.push_back(newRectangle(3,6));
    
       AreaCalculator areaCalc;
       PerimeterCalculator perimeterCalc;for(Shape* shape : shapes){
          shape->accept(&areaCalc);
          shape->accept(&perimeterCalc);}// Clean upfor(Shape* shape : shapes){delete shape;}return0;}

    Following is the output of the above code −

    Area of Circle: 78.5398
    Perimeter of Circle: 31.4159
    Area of Square: 16
    Perimeter of Square: 16
    Area of Rectangle: 18
    Perimeter of Rectangle: 18
    

    The output prints the area and perimeter of each shape. Important thing here is that the shapes did not calculate these values. The visitors did all the work and shapes only allowed the visitors to come in.

    Pros and Cons of Visitor Design Pattern

    Following are the advantages and disadvantages of using the visitor design pattern −

    ProsCons
    Easy to add new work later. You can make a new visitor anytime without touching the old classes.If you add a new element type , you must update every visitor, which can be annoying.
    Keeps element classes small . They only hold data and one accept function.Takes time to understand at first, because the work is not inside the element but inside the visitor.
    Good when you need to do many different tasks on the same set of objects. Each task stays in its own visitor.Creates many visitor classes , which can make the project look larger if not kept organized.
    Makes the project easier to maintain because the main classes rarely change. This reduces mistakes.If the shape or structure of elements changes often, then visitors break easily.

    Real-World Applications of Visitor Design Pattern

    Following are the real-world software use-cases of the visitor design pattern −

    • Compilers − Compilers use visitor pattern all the time because they need to walk through many different types of nodes in the syntax tree. These nodes represent things like numbers, variables, loops, conditions, functions, and more. Instead of putting checking, printing, optimization, and code generation inside every node class, they use visitors. This makes it easy to add new passes to the compiler without touching the original tree structure.
    • Document Processing − In document editors, you may have text blocks, images, tables, links, shapes, and other items. You may want to print the document, export it as PDF, count words, analyze styles, highlight mistakes, or convert it into another format. Instead of putting all these tasks into the document elements, each task becomes a visitor. This keeps the document classes simple and allows adding new features later.
    • Graphics and Game Development − Games have many objects like players, enemies, bullets, walls, items, and environment objects. You might want to render them differently, check collisions, update physics, or debug their state. Each of these actions can be a visitor. This makes the game code cleaner because you avoid stuffing every game object with too many functions. The visitor approach also helps when you want to run different “passes,” like updating health, checking triggers, or drawing outlines for debugging.
    • Data Structures − Trees, graphs, and file systems are perfect places to use visitor pattern. These structures often contain many node types, and you need to perform many operations like searching, sorting, printing, exporting, computing size, checking rules, or validating data. Visitors make it easy to run all these operations without rewriting the structure code.
    • Financial Systems − In finance, you might have many types of financial instruments like loans, bonds, stocks, insurance plans, or transactions. You may want to calculate interest, total value, tax, risk score, or generate reports. Using visitors allows each of these operations to be written separately. This also helps financial companies update formulas or add new types of calculations without editing the core classes.
    • Analytics and Reporting Tools − Many dashboards and analytics tools deal with objects like charts, graphs, metrics, logs, and events. Visitors help perform tasks like generating weekly reports, exporting data, summarizing usage, cleaning logs, or transforming data into new formats.
    • IDE Tools and Code Editors − When an editor analyses your code to show errors, warnings, auto-suggestions, refactoring options, it often uses visitors to walk through your program structure. Each feature becomes a visitor.
    Real-world Software Use-cases of Visitor Design Pattern

    Conclusion

    In this chapter, we explored the visitor design pattern, a powerful behavioral design pattern that allows for the separation of algorithms from the objects on which they operate. We discussed the key components of the pattern, including the visitor interface, concrete visitors, element interface, and concrete elements. We also implemented the visitor pattern in C++ using a shape example, demonstrating how to calculate area and perimeter using separate visitor classes. Finally, we examined the pros and cons of the visitor pattern and highlighted its real-world applications in various domains. By using the visitor design pattern, developers can enhance code maintainability, promote separation of concerns, and easily add new operations to existing object structures.

  • Template Method Design Pattern in C++

    The Template Method Design Pattern is a way to set up a common process that can be shared by different classes. It gives a main method called the template method that explains the steps to complete a task. Other classes can then fill in the details for some of those steps in their own way, without changing the main process. This helps in reusing code and keeping things simple as well as consistent.

    This pattern is helpful when you have a task that follows the same steps every time, but a few steps might need to be done differently. You can keep the main steps in one place and let other classes change only the parts they need. This makes the program easy to read and simple to manage.

    For example, think of a program that shows how to prepare a meal. The template method might describe the main steps : gathering ingredients, cooking, and serving. Now, other classes can change how these steps are done to make different meals like breakfast, lunch, or dinner. The main idea stays the same, but each meal can have its own special details.

    Template Method Design Pattern Illustration

    Key Parts of the Template Method Design Pattern

    The Template Method Design Pattern has following components that work together −

    • The Abstract Class is the main class that defines the overall process. It includes the template method, which lists all the steps in order. Some steps may already have code, while others are left empty so other classes can fill them in later.
    • The Template Method is the main method that shows how the task should be done from start to finish. It calls smaller methods for each step. Some of those smaller methods might be complete, and some might be waiting for other classes to finish them.
    • The Concrete Subclasses are the classes that come from the abstract class. They complete the unfinished steps by adding their own code. Each subclass can do things a little differently, but they all still follow the main process written in the template method.
    • The Hook Methods are optional steps that can be changed if needed. They let you add or skip small actions without touching the main process. Think of them like little switches you can turn on or off to change small parts of how things work.

    C++ Implementation of the Template Method Design Pattern

    Let’s learn how to use the Template Method pattern in C++ with a simple example. We’ll make a program that shows how to prepare different kinds of meals by following the same main steps.

    Steps to use the Template Method pattern in C++

    Following are the steps to implement the Template Method Design Pattern in C++

    • First, make an abstract class that has one main method called the template method. This method lists all the steps of the process, like a recipe. Some steps will already have code, and others will be left empty so that other classes can fill them in later.
    • Next, create subclasses that come from the abstract class. These classes will fill in the missing steps with their own code. For example, one class can show how to make breakfast, another one can show how to make lunch, and another one can show how to make dinner.
    • Finally, use these subclasses to run the template method. The main steps stay the same, but each subclass adds its own little changes to make the meal special in its own way.
    Steps to Implement Template Method Design Pattern

    This way, you can keep the main process in one place and still make it easy to add new meal types later without changing the whole program.

    C++ Code to Implement Template Method Design Pattern

    Below is a simple C++ code example demonstrating the Template Method Design Pattern for preparing different types of meals.

    #include <iostream>usingnamespace std;// Abstract class defining the template methodclassMeal{public:// Template methodvoidprepareMeal(){gatherIngredients();cook();serve();}// Abstract methods to be implemented by subclassesvirtualvoidgatherIngredients()=0;virtualvoidcook()=0;// Concrete methodvoidserve(){
          cout <<"Serving the meal!"<< endl;}};// Concrete subclass for preparing a breakfast meal classBreakfast:public Meal{public:voidgatherIngredients()override{
          cout <<"Gathering ingredients for breakfast: eggs, bread, and coffee."<< endl;}voidcook()override{
          cout <<"Cooking breakfast: frying eggs and toasting bread."<< endl;}};// Concrete subclass for preparing a lunch mealclassLunch:public Meal{public:voidgatherIngredients()override{
          cout <<"Gathering ingredients for lunch: chicken, rice, and vegetables."<< endl;}voidcook()override{
          cout <<"Cooking lunch: grilling chicken and steaming vegetables."<< endl;}};intmain(){
       Meal* breakfast =newBreakfast();
       breakfast->prepareMeal();
    
       cout << endl;
    
       Meal* lunch =newLunch();
       lunch->prepareMeal();// Clean updelete breakfast;delete lunch;return0;}

    Following is the output of the above code −

    Gathering ingredients for breakfast: eggs, bread, and coffee.
    Cooking breakfast: frying eggs and toasting bread.
    Gathering ingredients for lunch: chicken, rice, and vegetables.
    Cooking lunch: grilling chicken and steaming vegetables.
    Serving the meal!
    

    In this example, we have an abstract class called Meal. It has a main method named prepareMeal() that shows the full process of making a meal. The method includes three main steps — gathering ingredientscooking, and serving.

    The subclasses Breakfast and Lunch each add their own way of doing the steps. They give their own details for how to gather the ingredients and how to cook the food.

    When we run the prepareMeal() method for each subclass, it follows the same main steps but changes the small details depending on the type of meal. This lets us keep the main process the same while still making each meal a little different.

    Pros and Cons of the Template Method Design Pattern

    Like any design pattern, the Template Method Design Pattern has its advantages and disadvantages. Here are some of the main pros and cons −

    ProsCons
    It helps reuse code by keeping a common process in one place, so you don’t have to write the same steps again and again.It can create a strict class structure, which might make it harder to change the process later.
    It keeps the process consistent across different parts of the program, so everything follows the same steps.Subclasses don’t have much freedom to change the main process, since the overall structure stays fixed.
    It makes maintenance easier because the main process logic is all written in one place.You might end up with too many subclasses if you need lots of small changes for different versions of the process.
    It makes it easy to see and understand how the whole process works from start to finish.Sometimes it can cause code duplication if different subclasses write the same steps in slightly different ways.

    Real-World Applications of the Template Method Design Pattern

    The Template Method Design Pattern is widely used in various real-world applications. Here are some common scenarios where this pattern might be useful −

    • Data Processing Pipelines − In data processing applications, a common sequence of steps such as data extraction, transformation, and loading (ETL) can be defined using the template method pattern. Different data sources or formats can be handled by subclasses that implement specific extraction and transformation logic.
    • Game Development − In game development, the template method pattern can be used to define the overall game loop structure, while allowing subclasses to implement specific behaviors for different game states, such as playing, paused, or game over.
    • Document Generation − In applications that generate documents (like reports or invoices), the template method pattern can define the overall structure of the document, while subclasses can implement specific formatting and content generation for different document types.
    • User Interface Frameworks − UI frameworks often use the template method pattern to define the lifecycle of UI components, such as initialization, rendering, and event handling, while allowing subclasses to customize specific behaviors for different types of components.
    • Testing Frameworks − Testing frameworks can use the template method pattern to define the overall structure of test cases, while allowing subclasses to implement specific setup, execution, and teardown logic for different types of tests.
    Real-World Use Cases of Template Method Design Pattern

    Conclusion

    The Template Method Design Pattern is a simple and practical way to keep one common process while letting different parts change only when it is needed. It helps you in reusing code, keeping your program organized, and make complex tasks easier to handle without repeating the same logic everywhere.

  • Strategy Design Pattern in C++

    The Strategy Design Pattern is a simple and powerful way to organize your code when you have different ways to perform the same task. It defines a family of algorithms, places each one in its own separate class, and lets you switch between them easily. This means you can change the algorithm’s behavior without touching the main code that uses it.

    For example, imagine you have a navigation app that can show routes based on different preferences: the fastest route, the shortest route, or the most scenic route. With the Strategy Design Pattern, you can create a separate class for each type of route and simply switch between them whenever needed, without changing how the main app works.

    Strategy Design Pattern Illustration

    Key Components of the Strategy Design Pattern

    The Strategy Design Pattern is built around a few main parts that make the code more flexibleorganized, and easy to maintain. Let’s look at them one by one −

    • Strategy Interface − This defines a common method that every strategy (or algorithm) must follow. It ensures that all the different strategies can be used in the same way, no matter which one you choose.
    • Concrete Strategies − These are the actual classes that implement the Strategy Interface. Each one represents a different algorithm or way of doing a task. For example, one strategy might calculate the fastest route, while another finds the most scenic one.
    • Context − This is the main class that uses one of the strategies. It keeps a reference to a Strategy object and asks it to perform the task. The Context doesn’t care which strategy it’s using, it just knows that it can call the same method on any of them.

    In short, the Strategy Design Pattern helps you write code that’s easier to updatecleaner to read, and simpler to extend. When a new way of doing something comes along, you can just add a new strategy class instead of rewriting your existing code.

    C++ Implementation of the Strategy Design Pattern

    In this section, we will see how to implement the Strategy Design Pattern in C++ with a simple and easy-to-understand example. We’ll create a Context class that can use different strategies to perform a calculation. Each strategy will be written in its own class, making the program flexible enough to switch between different strategies whenever needed it without changing the rest of the code.

    Steps to Implement the Strategy Design Pattern in C++

    • Define the Strategy Interface − Start by creating an abstract class that defines a common method for the algorithm. This interface acts like a blueprint that every strategy class will follow this same structure.
    • Implement Concrete Strategies − Create separate classes that inherit from the Strategy Interface and provide their own version of the algorithm. Each class will represent a different way of performing the same task.
    • Create the Context Class − This is the main class that will use one of the strategies. It holds a reference to a Strategy object and uses it to perform the calculation. The Context doesn’t care which strategy it’s using and it just calls the same method.
    • Use the Strategy Pattern − In the main function, create objects for the Context and the different Strategy classes. Show how the Context can switch between strategies dynamically for example, changing from addition to multiplication — without rewriting any logic in the Context itself.

    By following these steps, you’ll learn how the Strategy Design Pattern helps make your code cleanereasier to extend, and more flexible when you need to change or add new behaviors.

    C++ Example Code of the Strategy Design Pattern

    Below is a simple C++ implementation of the Strategy Design Pattern. In this example, we have a context class that can use different strategies for performing calculations (addition and subtraction).

    #include <iostream>usingnamespace std;// Strategy InterfaceclassStrategy{public:virtualintdoOperation(int a,int b)=0;virtual~Strategy(){}};// Concrete Strategy for AdditionclassAddition:public Strategy{public:intdoOperation(int a,int b)override{return a + b;}};// Concrete Strategy for SubtractionclassSubtraction:public Strategy{public:intdoOperation(int a,int b)override{return a -b;}};// Context ClassclassContext{private:
       Strategy* strategy;public:Context(Strategy* strategy):strategy(strategy){}voidsetStrategy(Strategy* strategy){this->strategy = strategy;}intexecuteStrategy(int a,int b){return strategy->doOperation(a, b);}};intmain(){
       Context* context =newContext(newAddition());
       cout <<"10 + 5 = "<< context->executeStrategy(10,5)<< endl;
    
       context->setStrategy(newSubtraction());
       cout <<"10 -5 = "<< context->executeStrategy(10,5)<< endl;delete context;return0;}

    Following is the output of the above code −

    10 + 5 = 15
    10 -5 = 5
    

    Pros and Cons of the Strategy Design Pattern

    Like most design patterns, the Strategy Design Pattern has both advantages and disadvantages. Understanding both sides helps you decide when it’s actually worth using in a project.

    ProsCons
    This pattern gives you the freedom to change algorithms while the program is running. You don’t need to edit the main class; you can just switch one strategy for another, which keeps the code flexible and easy to adapt.Each strategy needs its own class, which can increase the number of files in your project. This might make the codebase feel more cluttered and harder to navigate in larger applications.
    Since every algorithm is placed in its own class, it’s much easier to update or fix without affecting other parts of the code. This separation makes the program cleaner and easier to maintain.For small or simple programs, using this pattern can feel like too much work. Creating multiple classes for something straightforward might make the code more complex than necessary.
    Strategies can be reused in different parts of your program or even in other projects. This helps you avoid repeating the same logic and keeps your code more organized.Since the program has to go through an extra layer to reach the strategy object, there can be a small amount of performance overhead. It’s usually minor, but worth noting in performance-critical applications.

    Overall, the Strategy Design Pattern is a practical and clean way to keep your code flexible and easy to manage. It’s especially useful when your program needs to switch between different algorithms or behaviors, but for very simple projects, it might be better to stick with a straightforward approach.

    Real-World Examples of the Strategy Design Pattern

    The Strategy Design Pattern is used in many software programs to make it easy to change the way something works. Here are some simple examples of where it can be used −

    • In payment systems, such as online shopping apps, different payment methods like credit card, PayPal, or cryptocurrency can each be written in a separate class. The program can then choose the right payment method based on what the user wants.
    • In programs that need to sort data, different sorting methods like quicksort, mergesort, or bubblesort can be used as separate strategies. The program can decide which one to use depending on how big or small the data is.
    • In file compression software, different compression types such as ZIP, RAR, or TAR can each be written separately. The user can choose which one to use without changing the main program.
    • In video games, different character behaviors like attacking, defending, or staying still can each be made as their own strategy. The game can switch between them based on what is happening during the game.
    Strategy Design Pattern Applications Illustration

    Conclusion

    In this chapter, we explored the Strategy Design Pattern, its key components, and how it helps in making your code more flexible and easier to manage. We also saw some real-world examples where this pattern can be effectively applied.

  • State Design Pattern in C++

    The State Design Pattern is a way to let an object change how it behaves when its state changes. Instead of using lots of if-else or switch statements, you put the different behaviors into separate state classes. This makes your code cleaner and easier to understand.

    In this pattern, you have a main class (called the context) that keeps track of its current state. When something happens, the context asks its current state what to do. If the state changes, the context just switches to a different state object. This way, the object can change its behavior at any time, just by changing its state.

    For example, think about a simple vending machine. It can be in different states like Idle (waiting for money), HasMoney (money inserted), or Dispensing (giving out a product). Each state knows what to do when you press a button or insert money. By using the State Design Pattern, the vending machine can easily switch between states and always do the right thing, without complicated code.

    State Design Pattern Illustration

    Key Components of the State Design Pattern

    The State Design Pattern is made up of a few important parts that work together to make your code easier to manage and understand. Here’s what each part does:

    • Context − This is the main object you work with. It keeps track of what state it is in right now. When something happens, the context asks its current state what to do next. The context is also in charge of switching to a different state when needed.
    • State Interface − This is like a blueprint that says what actions every state should be able to do. All the different states must follow this blueprint and provide their own versions of these actions.
    • Concrete State Classes − These are the actual states your object can be in. Each state class has its own way of handling things. For example, the “Idle” state will do something different than the “Dispensing” state when you press a button.
    • State Transition: This is how the context changes from one state to another. When something happens (like inserting money), the context will switch to a new state so it can behave differently.

    C++ Implementation of the State Design Pattern

    In this C++ program, we will make a simple vending machine step by step. The vending machine will work in three main states Idle (waiting for money), HasMoney (money inserted), and Dispensing (item being given to the user). Each state will handle how the machine reacts when a user does something,like inserting money or selecting an item.

    Steps to Build the Vending Machine using the State Design Pattern in C++

    Following are the steps we will follow to create our vending machine using the State Design Pattern −

    Steps to State Design Pattern Illustration
    • First, define a State interface that includes methods for actions like inserting money, selecting an item, and dispensing it.
    • Next, create separate classes for each state IdleHasMoney, and Dispensing. Each class will describe how the vending machine behaves in that particular state.
    • Then, make a Context class that represents the vending machine itself. This class will keep track of the current state and will pass user actions to the state object to handle them.
    • Finally, add state transitions inside the Context class so that the machine can smoothly move from one state to another for example, from Idle to HasMoney when money is inserted, or from HasMoney to Dispensing after an item is selected.

    C++ Code Example of the State Design Pattern

    #include <iostream>usingnamespace std;// State InterfaceclassState{public:virtualvoidinsertMoney()=0;virtualvoidselectProduct()=0;virtualvoiddispenseProduct()=0;virtual~State(){}};// Forward declarationclassVendingMachine;// Concrete State: IdleclassIdleState:public State{private:
        VendingMachine* vendingMachine;public:IdleState(VendingMachine* vm):vendingMachine(vm){}voidinsertMoney()override;voidselectProduct()override{
            cout <<"Please insert money first."<< endl;}voiddispenseProduct()override{
            cout <<"Please insert money and select a product first."<< endl;}};// Concrete State: HasMoneyclassHasMoneyState:public State{private:
        VendingMachine* vendingMachine;public:HasMoneyState(VendingMachine* vm):vendingMachine(vm){}voidinsertMoney()override{
            cout <<"Money already inserted."<< endl;}voidselectProduct()override;voiddispenseProduct()override{
            cout <<"Please select a product first."<< endl;}};// Concrete State: DispensingclassDispensingState:public State{private:
        VendingMachine* vendingMachine;public:DispensingState(VendingMachine* vm):vendingMachine(vm){}voidinsertMoney()override{
            cout <<"Please wait, dispensing product."<< endl;}voidselectProduct()override{
            cout <<"Please wait, dispensing product."<< endl;}voiddispenseProduct()override;};// Context: Vending MachineclassVendingMachine{private:
        State* currentState;
        IdleState idleState;
        HasMoneyState hasMoneyState;
        DispensingState dispensingState;public:VendingMachine():idleState(this),hasMoneyState(this),dispensingState(this){
            currentState =&idleState;}voidsetState(State* state){
            currentState = state;}voidinsertMoney(){ currentState->insertMoney();}voidselectProduct(){ currentState->selectProduct();}voiddispenseProduct(){ currentState->dispenseProduct();}
    
        State*getIdleState(){return&idleState;}
        State*getHasMoneyState(){return&hasMoneyState;}
        State*getDispensingState(){return&dispensingState;}};// ImplementationsvoidIdleState::insertMoney(){
        cout <<"Money inserted."<< endl;
        vendingMachine->setState(vendingMachine->getHasMoneyState());}voidHasMoneyState::selectProduct(){
        cout <<"Product selected."<< endl;
        vendingMachine->setState(vendingMachine->getDispensingState());}voidDispensingState::dispenseProduct(){
        cout <<"Dispensing product."<< endl;
        vendingMachine->setState(vendingMachine->getIdleState());}intmain(){
        VendingMachine vm;
    
        vm.insertMoney();
        vm.selectProduct();
        vm.dispenseProduct();return0;}

    Following is the output of the above code −

    Money inserted.
    Product selected.
    Dispensing product.
    

    Pros and Cons of State Design Pattern

    Following are some advantages and disadvantages of using the State Design Pattern −

    The State Design Pattern helps you write cleaner and more organized code. It does this by putting state-specific behavior inside separate classes, which removes the need for long and confusing conditional statements.However, using the State Design Pattern can also increase the number of classes in your project, which might make the codebase harder to understand and maintain at first.
    It improves maintainability and scalability because you can add new states easily without changing the existing code.On the other hand, the growing number of classes may complicate navigation in the project if not organized properly.
    The pattern allows dynamic behavior changes at runtime, which means the object can switch between different states smoothly.But for developers who are new to design patterns, understanding and implementing the State Design Pattern can take some time and practice.
    It makes your code more organized by separating the logic of each state from the main class. This creates a better separation of concerns and makes the program easier to update later.Still, it might feel complex in the beginning and could slow down development until developers get used to the structure.

    Real-World Examples of the State Design Pattern

    The State Design Pattern is commonly used in many everyday software applications. Here are some practical examples −

    • User Interface Components − Buttons, sliders, and menus often behave differently based on their state (for example, enabled, disabled, or hovered). This pattern helps manage how these components react in each state.
    • Game Development − In video games, characters and objects have multiple states such as idle, running, jumping, or attacking. The State Design Pattern helps switch between these states and control their actions cleanly.
    • Network Protocols − A network connection can be in different states like connected, disconnected, or reconnecting. This pattern helps handle each state’s behavior separately, making network management easier.
    • Workflow Management − In workflow systems, tasks may have states like pending, in progress, or completed. The pattern helps define how each state behaves and transitions to the next one.

    Conclusion

    In this chapter, we explored the State Design Pattern, its key components, and how it helps in managing state-specific behavior in a clean and organized way. We also saw a practical C++ implementation of a vending machine using this pattern, along with its advantages, disadvantages, and real-world applications.

  • Observer Design Pattern in C++

    Observer Design Pattern is a way to make sure that when something important changes in one part of your program, all the other parts that care about it get updated right away. It’s called a one-to-many relationship because one main object (the subject) can have many other objects (the observers) watching it. When the subject changes, it tells all its observers so they can update themselves. This is super helpful when you want different parts of your program to always show the latest information, but you don’t want them to be tightly connected or mixed together.

    For example, imagine you have a weather app with several display screens showing the current weather. The weather data is the subject, and the display screens are the observers. Whenever the weather changes, the weather data tells all the screens to update, so everyone always sees the newest weather. This way, you don’t have to update each screen by hand because they all get the news automatically.

    Sometimes people mix up the Observer Design Pattern with the Mediator Design Pattern. The difference is important: in the Observer Pattern, the subject keeps a list of observers and tells them when something changes. In the Mediator Pattern, there’s a special mediator object in the middle that helps different objects talk to each other, so they don’t talk directly. The Observer Pattern is all about keeping things in sync, while the Mediator Pattern is about organizing communication.

    Observer Design Pattern Illustration

    Components of Observer Design Pattern

    The Observer Design Pattern consists of the following main components −

    • Subject − This is the main object that has some important information or state. When something changes inside the subject, it lets others know about it. The subject keeps a list of all the people (observers) who want to know when something changes. For example, in a weather app, the weather data is the subject because it knows the latest weather and tells others when it changes.
    • Observer − An observer is anyone who wants to know when the subject changes. Observers sign up with the subject, and whenever there is an update, the subject tells all its observers. In our weather app example, the display screens are observers because they show the latest weather whenever the weather data changes.
    • Concrete Subject − This is a real, working version of the subject. It actually stores the data and knows how to tell the observers when something changes. In the weather app, the WeatherData class is the concrete subject because it keeps the weather info and notifies the displays.
    • Concrete Observer − This is a real, working version of an observer. It knows how to react when the subject tells it about a change. In the weather app, the WeatherDisplay class is a concrete observer because it updates what it shows whenever the weather changes.

    C++ Implementation of Observer Design Pattern

    In this section, we will implement the Observer Design Pattern in C++. We will create a simple weather monitoring application to demonstrate how the pattern works.

    Steps to Implement Observer Design Pattern in C++

    Steps to Implement Observer Design Pattern

    Follow these steps to implement the Observer Design Pattern in C++:

    • First, create an Observer interface. This is like a contract that says every observer must have an update function. This function will be called whenever there is a change.
    • Next, make a class for the actual observers (for example, a display screen). This class should use the Observer interface and define what happens when it gets updated (like showing the new weather).
    • Now, create a Subject interface. This is a contract for the main object (like the weather data) and says it must have ways to add, remove, and notify observers.
    • Then, make a class for the real subject (for example, the weather data). This class should use the Subject interface and keep a list of all observers. When the weather changes, it should tell all observers by calling their update function.
    • In your main program, make objects for the subject (weather data) and the observers (display screens).
    • Add the observers to the subject’s list, then change the weather data to see how all the observers get updated automatically.

    Example Code for Observer Design Pattern in C++

    Here is a simple implementation of the Observer Design Pattern in C++

    #include <algorithm>#include <iostream>#include <vector>usingnamespace std;// Observer interfaceclassObserver{public:virtualvoidupdate(float temperature,float humidity,float pressure)=0;};// Concrete Observer classclassWeatherDisplay:public Observer{private:float temperature;float humidity;float pressure;public:voidupdate(float temp,float hum,float pres)override{
          temperature = temp;
          humidity = hum;
          pressure = pres;display();}voiddisplay(){
          cout <<"Weather Update - Temperature: "<< temperature
               <<", Humidity: "<< humidity
               <<", Pressure: "<< pressure << endl;}};// Subject interfaceclassSubject{public:virtualvoidattach(Observer* observer)=0;virtualvoiddetach(Observer* observer)=0;virtualvoidnotify()=0;};// Concrete Subject classclassWeatherData:public Subject{private:
       vector<Observer*> observers;float temperature;float humidity;float pressure;public:voidattach(Observer* observer)override{
          observers.push_back(observer);}voiddetach(Observer* observer)override{
          observers.erase(remove(observers.begin(), observers.end(), observer), observers.end());}voidnotify()override{for(Observer* observer : observers){
             observer->update(temperature, humidity, pressure);}}voidsetMeasurements(float temp,float hum,float pres){
          temperature = temp;
          humidity = hum;
          pressure = pres;notify();}};intmain(){
       WeatherData weatherData;
    
       WeatherDisplay display1;
       WeatherDisplay display2;
    
       weatherData.attach(&display1);
       weatherData.attach(&display2);
    
       weatherData.setMeasurements(30.5,65,1013.1);
       weatherData.setMeasurements(28.3,70,1012.5);
    
       weatherData.detach(&display1);
    
       weatherData.setMeasurements(25.0,80,1011.8);return0;}

    Following is the output of the above code −

    Weather Update - Temperature: 30.5, Humidity: 65, Pressure: 1013.1
    Weather Update - Temperature: 30.5, Humidity: 65, Pressure: 1013.1
    Weather Update - Temperature: 28.3, Humidity: 70, Pressure: 1012.5
    Weather Update - Temperature: 25.0, Humidity: 80, Pressure: 1011.8
    

    Pros and Cons of Observer Design Pattern

    The Observer Design Pattern offers several advantages and disadvantages −

    ProsCons
    The Observer Design Pattern makes it easy to add new observers without changing the existing code. This means your program can grow and change over time without breaking things that already work.If you forget to remove observers when they are no longer needed, your program might use more memory than necessary. This can cause memory leaks, especially if the subject is destroyed but the observers are still around.
    The subject and the observers do not need to know much about each other. This makes your code easier to change and maintain because you can update one part without affecting the other.If the subject changes its state very often, it will notify all observers each time. This can slow down your program if there are many observers or updates.
    You can add or remove observers while the program is running. This means your program can react to changes and new requirements without stopping or restarting.Managing the list of observers and making sure everyone gets the right updates can make your code more complicated, especially in big programs.
    You can use the same observer with different subjects. This helps you avoid writing the same code again and again.Observers are not always notified in a specific order. If your program depends on the order of updates, this can sometimes cause problems.

    When to use Observer Design Pattern

    The Observer Design Pattern is particularly useful in the following scenarios −

    • Use the Observer Design Pattern when you have one object that changes, and you want many other objects to know about this change automatically. For example, if you have a weather station and several display screens, you want all screens to show the new weather as soon as it changes.
    • This pattern is helpful when you don’t know in advance how many things need to be updated. You can add or remove observers (like display screens) at any time, and they will always get the latest information.
    • It’s also great when you want to keep your code simple and not have the main object (the subject) worry about who needs updates. The subject just sends out the update, and all observers get it automatically.
    • If you want to build a system where different parts react to changes or events, like in event-driven programs or notification systems, the Observer Design Pattern makes this easy and keeps everything organized.

    Real-World Examples of Observer Design Pattern

    Here are some real-world examples where the Observer Design Pattern is used −

    • GUI frameworks use this pattern so that when the data model changes, all the UI components (like buttonslabels, or charts) update automatically to show the latest information.
    • Event-driven systems let different parts of a program react to things that happen, like a button click or a new message. When the event source changes, all the listeners (observers) get notified and can respond right away.
    • On social media platforms, when someone you follow (the subject) posts something new, you (the observer) get an update instantly. This keeps you connected and always up to date with your favorite accounts.
    • Stock market apps use this pattern so that whenever a stock price changes, all the investors who are watching that stock get the latest price right away. This helps investors make quick decisions based on real-time data.
    • Messaging systems let you subscribe to topics or channels. When a publisher sends a new message, all the subscribers (observers) who are interested in that topic get the message automatically, so nobody misses important updates.
    Real-World Use Cases of Observer Design Pattern

    Conclusion

    In this chapter, you learned about the Observer Design Pattern, how it works, its good and bad sides, and where it is used in real life. This pattern is very helpful for making programs where changes in one part need to be shared with many other parts, that keeps everything up to date and easy to manage.

  • Memento Design Pattern in C++

    Memento Design Pattern is a behavioral design pattern that allows an object to capture its internal state and save it externally so that it can be restored later without violating encapsulation. This pattern is particularly useful when you want to implement features like undo/redo functionality in applications.

    For example, take an application where users can edit documents. By using the Memento Design Pattern, the application can save the state of the document at various points in time. If the user wants to undo their last action, the application can restore the document to its previous state using the saved memento. This way, the internal state of the document is preserved without exposing its details to other parts of the application.

    Memento Design Pattern Illustration

    Components of Memento Design Pattern

    The Memento Design Pattern consists of three main components −

    • Originator − The main object you want to save and restore. It can make a memento (a snapshot of its current state) and later use that memento to go back to how it was before. For example, in a text editor, the Originator is the editor itself that holds your text.
    • Memento − A special object that remembers the state of the Originator at a certain time. Once made, its contents cannot be changed, so you can always trust it to bring things back exactly as they were. Think of it like a bookmark or a save point.
    • Caretaker − The helper that keeps track of all the mementos (saved states). It stores them safely and can ask the Originator to go back to a previous state when needed. The Caretaker never looks inside the mementos or changes them; it just holds onto them and gives them back when you want to undo or redo something.

    C++ Implementation of Memento Design Pattern

    We will use all three components of the Memento Design Pattern to implement a simple text editor that allows users to type text and undo their last action.

    In this editor, the Originator will be the TextEditor class, which maintains the current text and creates mementos to save its state. The Memento will be the TextMemento class, which stores the text state. The Caretaker will be the EditorHistory class, which manages the mementos and allows undo functionality.

    Steps to Implement Memento Design Pattern in C++

    Follow these steps to implement the Memento Design Pattern in C++

    Steps to Implement Memento Design Pattern
    • Create a Memento class ( TextMemento ) that will save the from the editor. This class just keeps a copy of the text so you can get it back later.
    • Make an Originator class ( TextEditor ). This is your main editor where you type and change text. It can create a memento to save its current text, and it can restore its text from a memento if you want to go back.
    • Add a Caretaker class ( EditorHistory ). This class remembers all the saved versions (mementos) of your text. It lets you undo by giving you back the last saved version.
    • Write a main function to show how it works. Here, you will type some text, save it, and then use undo to go back to earlier versions.

    C++ Code of Memento Design Pattern

    Below is the C++ code that implements the Memento Design Pattern for a simple text editor with undo functionality −

    #include <iostream>#include <string>#include <vector>usingnamespace std;// Memento classclassTextMemento{private:
       string textState;public:TextMemento(const string &state):textState(state){}
       string getState()const{return textState;}};// Originator classclassTextEditor{private:
       string text;public:voidtype(const string &newText){
           text += newText;}
       string getText()const{return text;}
       TextMemento save(){returnTextMemento(text);}voidrestore(const TextMemento &memento){
           text = memento.getState();}};// Caretaker classclassEditorHistory{private:
       vector<TextMemento> history;public:voidpush(const TextMemento &memento){
          history.push_back(memento);}
       TextMemento pop(){if(!history.empty()){
             TextMemento memento = history.back();
             history.pop_back();return memento;}returnTextMemento("");}};// Main function to demonstrate Memento Design Patternintmain(){
       TextEditor editor;
       EditorHistory history;
    
       editor.type("Hello, ");
       history.push(editor.save());
       editor.type("World!");
       history.push(editor.save());
    
       cout <<"Current Text: "<< editor.getText()<< endl;
    
       editor.restore(history.pop());
       cout <<"After Undo: "<< editor.getText()<< endl;
    
       editor.restore(history.pop());
       cout <<"After Undo: "<< editor.getText()<< endl;return0;}

    In this code, we have defined the TextMemento class to store the text state, the TextEditor class to manage the text and create/restore mementos, and the EditorHistory class to manage the history of mementos for undo functionality. The main function demonstrates how to use these classes to type text and undo actions.

    Current Text: Hello, World!
    After Undo: Hello, 
    After Undo: 
    

    Pros and Cons of Memento Design Pattern

    Following are the advantages and disadvantages of using the Memento Design Pattern −

    ProsCons
    Undo is easy and helpful. You can quickly go back to an earlier version if you make a mistake or want to change something.It can use a lot of memory if you keep saving many versions. This might make your program slower or take up more space.
    Your object’s details stay safe. Other parts of your program cannot change or see the inside details by mistake, so your data is protected.You need to make extra classes to use this pattern. This can make your code a little more complicated and harder to manage.
    Undo and redo features are simple to add. This pattern makes it easy for users to fix mistakes or try different things without worry.Saving big or many states can slow things down. If your program saves a lot of information often, it might not run as fast.

    When to Use Memento Design Pattern

    The Memento Design Pattern is very useful in everyday programs where you want to let people fix mistakes or go back to something they did before. It is especially helpful for adding undo and redo features, which make programs much easier and safer to use.

    For example, if someone is writing in a text editor or drawing in a paint app, they might make a mistake. With this pattern, the program can save the state of their work at different times. If they want to fix a mistake, they can restore an earlier version without anyone seeing or changing the private details inside the program.

    This pattern is also great for keeping a history of changes. People can easily go back to an earlier version of their work if they change their mind or want to try something different. It helps make programs more friendly and less stressful to use.

    Real-World Examples of Memento Design Pattern

    Here are some real-world examples where the Memento Design Pattern is used in simple, everyday language −

    Real-World Use Cases of Memento Design Pattern
    • Text editors like Notepad or Word let you undo and redo what you type. If you make a mistake, you can easily go back to how it was before.
    • Drawing or graphic design apps let you revert to an earlier version of your picture. If you don’t like your last change, you can bring back the old version.
    • Video games often let you save your progress. If you lose or want to try again, you can load your saved game and start from there.
    • Version control systems (like Git) help you track changes to your files. If you want to go back to an older version, you can restore it easily.
    • Databases use this pattern to roll back to a safe state if something goes wrong, so your data stays safe.
    • Settings or configuration managers let you save your system settings. If you change something and it doesn’t work, you can restore the old settings.

    Conclusion

    In this chapter, you learned about the Memento Design Pattern, its three main parts, and how to use it in C++. You also saw the good and bad sides, when to use it, and some real-life examples. The Memento Pattern is a great way to let users undo and redo actions, keep their data safe, and make your programs easier to use.

  • Mediator Design Pattern in C++

    Mediator Design Pattern is a way to make communication between different objects or classes much simpler. Instead of having every object talk directly to every other object, which can get very confusing, we use a special class called the mediator. The mediator acts like a middleman and handles all the messages between objects. This makes the code easier to manage and change later because the objects don’t need to know about each other.

    Let’s make this even clearer with a simple example from real life. Imagine an airport. There are many airplanes, and they all need to communicate about when to take off or land. If every airplane tried to talk to every other airplane, it would be chaos! Instead, there is a control tower. The control tower is the mediator. All airplanes talk only to the control tower, and the tower tells each airplane what to do. This keeps everything organized and safe.

    So, in programming, the mediator pattern works just like the control tower at the airport. It helps different parts of a program communicate in an organized way, making the whole system easier to understand and maintain.

    Mediator Design Pattern Illustration

    Components of Mediator Design Pattern

    Following are the main components of the Mediator Design Pattern −

    • Mediator − Think of this as the main organizer or the middleman. It’s a special class that helps different parts of the program talk to each other. Instead of everyone talking to everyone, they all talk to the mediator.
    • ConcreteMediator − This is the real middleman in action. It knows about all the different parts (objects) and helps them send messages to each other. If one part wants to talk to another, it tells the mediator, and the mediator passes the message along.
    • Colleague − These are the different parts or objects in your program that need to communicate. Each one knows about the mediator, but they don’t know about each other. If they want to send a message, they go through the mediator.
    • ConcreteColleague − These are the actual objects doing the work in your program. They use the mediator to talk to other objects. For example, in a chat room, each user is a ConcreteColleague, and they send messages through the chat room (the mediator).

    C++ Implementation of Mediator Design Pattern

    In this section, we will implement a simple mediator pattern example where we have a chat room that acts as a mediator between different users.

    Steps to Implement Mediator Design Pattern in C++

    Step 1: Create the Mediator Interface − This is like making a set of rules for how the middleman (mediator) will help others talk to each other. It just says what the mediator should be able to do, but not how.

    Step 2: Make the Real Mediator Class − Here, you actually build the middleman. This class knows about everyone who needs to talk and helps them send messages to each other.

    Step 3: Create the Colleague Interface − This is a simple plan for all the people (objects) who want to talk to each other. It says what each one should be able to do, like send a message.

    Step 4: Build the Real Colleague Classes − Now you make the actual people (objects) who will use the mediator to talk. Each one uses the middleman instead of talking directly to others.

    Step 5: See How It Works Together − Put everything together and show how the objects use the mediator to send messages. This is where you see the pattern in action, just like people using a group chat to talk instead of calling each other one by one.

    C++ Code Example of Mediator Design Pattern

    Following is a simple C++ code example demonstrating the Mediator Design Pattern −

    #include <iostream>#include <string>#include <vector>usingnamespace std;// Mediator InterfaceclassChatMediator{public:virtualvoidshowMessage(const string &user,const string &message)=0;};// Concrete MediatorclassChatRoom:public ChatMediator{private:
       vector<string> users;public:voidaddUser(const string &user){
          users.push_back(user);}voidshowMessage(const string &user,const string &message)override{
          cout << user <<": "<< message << endl;}};// Colleague InterfaceclassUser{protected:
       ChatMediator *mediator;
       string name;public:User(ChatMediator *med,const string &n):mediator(med),name(n){}virtualvoidsendMessage(const string &message)=0;};// Concrete ColleagueclassChatUser:public User{public:ChatUser(ChatMediator *med,const string &n):User(med, n){}voidsendMessage(const string &message)override{
          mediator->showMessage(name, message);}};intmain(){
       ChatRoom chatRoom;
    
       ChatUser user1(&chatRoom,"Alice");
       ChatUser user2(&chatRoom,"Bob");
       ChatUser user3(&chatRoom,"Charlie");
       chatRoom.addUser("Alice");
       chatRoom.addUser("Bob");
       chatRoom.addUser("Charlie");
       user1.sendMessage("Hello, everyone!");
       user2.sendMessage("Hi Alice!");
       user3.sendMessage("Hey folks, what's up?");return0;}

    Following is the output of the above code −

    Alice: Hello, everyone!
    Bob: Hi Alice!
    Charlie: Hey folks, what's up?
    

    In this example, we have a ChatMediator interface, which is just a set of rules for how messages should be shown. The ChatRoom class follows these rules and acts as the main helper, or “middleman,” for all the users. The User class is like a basic plan for anyone who wants to join the chat, and the ChatUser class is a real person in the chat who sends messages using the chat room.

    Here’s how it works: When a user wants to send a message, they don’t talk directly to other users. Instead, they tell the chat room (the mediator), and the chat room takes care of showing the message. This keeps things simple and organized, because users don’t need to know about each other-they just use the chat room to communicate.

    When you run the code above, you’ll see that all the users send their messages through the chat room. This is a clear example of how the Mediator Design Pattern helps different parts of a program talk to each other in a simple and tidy way, without getting mixed up or confused.

    Pros and Cons of Mediator Design Pattern

    Like any design pattern, the Mediator Design Pattern has its good sides and its not-so-good sides.

    ProsCons
    Makes it easier for different parts of your program to work together without being directly connected. This means if you change one part, you don’t have to change all the others.If too many things depend on the mediator, it can become overloaded and slow things down.
    Puts all the rules for how things talk to each other in one place, so it’s simpler to see and fix how communication works.Adds an extra step (the mediator) between objects, which can make the program a bit more complicated.
    Helps different parts of your program talk to each other, even if they don’t know about each other at all.If you’re not careful, the mediator can become too big and hard to manage.
    Makes your code easier to read and understand because everything goes through the mediator.Because messages go through the mediator, it can be harder to figure out where a problem is if something goes wrong.
    If you want to change how things communicate, you only need to update the mediator, not every single part.Sometimes, using a mediator too much can make the other parts less independent and flexible.

    When to Use Mediator Design Pattern

    The Mediator Design Pattern is particularly useful in the following scenarios −

    • If your program has many different parts that all need to talk to each other, things can quickly get confusing. For example, imagine you have lots of buttonswindows, or users, and they all need to send messages or updates to each other. The Mediator pattern helps keep everything organized by letting each part talk only to a central helper, instead of directly to every other part.
    • It’s much easier to change your code later if each part only talks to the mediator (the middleman). If you ever want to change how things communicate, you just update the mediator, and you don’t have to rewrite everything else. This saves time and makes your program easier to maintain.
    • eeping all the rules for how things talk to each other in one place makes your program simpler to understand and fix. Instead of searching through lots of different files or classes to figure out how communication works, you just look at the mediator.
    • Different parts of your program don’t need to know about each other at all. This means you can addremove, or change parts without worrying about breaking the rest of your program.
    • Your code becomes much easier to read and understand. By using a mediator, you avoid a tangled mess of connections, and it’s clear how everything communicates. This makes it easier for you or anyone else to work with your code in the future.

    Real-World Examples of Mediator Design Pattern

    Some real-world examples of the Mediator Design Pattern include −

    • When you look at how airplanes work at an airport, you can see the mediator pattern in action. All the airplanes do not talk to each other directly. Instead, they all talk to the control tower. The control tower tells each airplane when it is safe to land or take off. This keeps everything safe and organized. The control tower is like a helpful friend who makes sure everyone knows what to do.
    • In a group chat, people do not send messages straight to each other. Everyone sends their message to the chat room. The chat room then shares the message with everyone else. This means people do not need to know who is in the chat or how to reach them. The chat room helps everyone stay connected easily.
    • When you use an app with buttons and windows, the buttons do not talk to each other or to the windows directly. There is a central part of the program that listens to all the buttons and windows. This central part decides what should happen when you click a button or open a window. It helps everything work together smoothly, just like a helpful guide.
    • If you think about a big event like a wedding, the guests do not talk to every vendor, such as the caterer, photographer, or band, by themselves. There is an event organizer who talks to everyone and makes sure things happen at the right time. The event organizer helps everyone work together and keeps things running smoothly.
    • In some offices, there is a manager who gives out tasks to different workers and makes sure everyone knows what to do. The workers do not have to talk to each other about who does what. The manager handles all the communication and helps everyone stay on track.
    Real World Use Cases of Mediator Design Pattern

    Conclusion

    In this chapter, we have learned about the Mediator Design Pattern, its components, implementation in C++, pros and cons, and real-world examples. The Mediator Design Pattern is a powerful tool for managing complex communication between objects while promoting loose coupling and maintainability. By using this pattern, developers can create more flexible and scalable systems that are easier to understand and maintain.

  • Iterator Design Pattern in C++

    Iterator Design Pattern is a behavioral design pattern that helps you move through a collection of items-like a liststack, or tree-without needing to know how that collection is built on the inside. Imagine you have a box full of different objects, and you want to look at each one, one by one, without having to open the box and figure out how everything is arranged. The Iterator pattern gives you a simple way to do this, making it easier to work with all kinds of collections in a consistent way.

    This pattern is especially useful when your application uses many different types of collections. Instead of writing separate code to loop through each type, you can use the Iterator pattern to create a common approach for all of them. This not only saves time but also makes your code cleaner and easier to update in the future. If you ever change how a collection is stored, you won’t have to rewrite the code that goes through its elements.

    Iterator Design Pattern Illustration

    For example, think about a music playlist app. You might have playlists stored as arrayslinked lists, or even trees. With the Iterator pattern, you can play songs from any playlist in the same way, without worrying about how the playlist is organized behind the scenes. This makes your program more flexible and much easier to maintain.

    Key Components of the Iterator Pattern

    • Iterator − Think of this as a guide that helps you move through a collection, one item at a time. The Iterator lays out the basic steps you need, like checking if there are more items to see (hasNext()) and getting the next item in line (next()). It doesn’t care what’s inside the collection or how it’s organized—it just gives you a simple way to look at each item, one after another.
    • Concrete Iterator − This is the actual helper that knows how to walk through a specific collection, like a list of books or a playlist of songs. It remembers where you are in the collection and knows how to get to the next item. For example, if you’re flipping through a stack of cards, the Concrete Iterator keeps track of which card you’re on and helps you move to the next one.
    • Aggregate − This is just a fancy word for any group or collection of items—like a bookshelf full of books or a playlist full of songs. The Aggregate sets the rule that says, “If you want to look through my items, you need to use an iterator.” It provides a way to get an iterator so you can start exploring the collection.
    • Concrete Aggregate − This is the actual collection itself, like your bookshelf or playlist. It holds all the items and knows how to give you an iterator that can walk through them. For example, your Library class might store a bunch of book titles and provide a way to get an iterator so you can read each title one by one.

    Implementation of Iterator Pattern in C++

    In this example, we will implement the Iterator Design Pattern in C++ to traverse a collection of books in a library.

    We will take example of a simple library system where we have a collection of books and we want to iterate through them using the Iterator pattern.

    Steps to Implement the Iterator Pattern in C++

    Following are the steps to implement the Iterator Design Pattern in C++

    Steps to Implement Iterator Design Pattern
    • Start by outlining what it means to move through a collection, and define an Iterator interface. This interface should include methods such as next() to get the next item, and hasNext() to check if there are more items left to visit.
    • Next, create a class that actually implements this Iterator interface for your specific collection. For example, if you have a list of books, this class will know how to go from one book to the next and keep track of where you are in the list.
    • Then, define an Aggregate interface. This is just a way to say that any collection (like a library of books) should be able to give you an iterator so you can look through its items.
    • After that, make a concrete class for your collection-like a Library class for books-that implements the Aggregate interface. This class will store your items and provide a way to create an iterator for them.
    • Finally, use the iterator in your main code to go through the collection. The beauty here is that you don’t need to know how the collection is organized inside; you just use the iterator to access each item one by one, making your code much simpler and easier to manage.

    C++ Code to Implement Iterator Pattern

    Following is the C++ code that demonstrates the Iterator Design Pattern −

    #include <iostream>#include <vector>usingnamespace std;// Iterator InterfaceclassIterator{public:virtualboolhasNext()=0;virtual string next()=0;};// Concrete IteratorclassBookIterator:public Iterator{private:
       vector<string> books;int position;public:BookIterator(vector<string> b):books(b),position(0){}boolhasNext()override{return position < books.size();}
       string next()override{return books[position++];}};// Aggregate InterfaceclassAggregate{public:virtual Iterator*createIterator()=0;};// Concrete AggregateclassLibrary:public Aggregate{private:
       vector<string> books;public:voidaddBook(string book){
          books.push_back(book);}
       Iterator*createIterator()override{returnnewBookIterator(books);}};// Client Codeintmain(){
       Library library;
       library.addBook("The Great Gatsby");
       library.addBook("1984");
       library.addBook("To Kill a Mockingbird");
    
       Iterator* iterator = library.createIterator();
    
       cout <<"Books in the Library:"<< endl;while(iterator->hasNext()){
          cout << iterator->next()<< endl;}delete iterator;return0;}

    Following is the output of the above code −

    Books in the Library:
    The Great Gatsby
    1984
    To Kill a Mockingbird
    

    In this example, we start by defining an Iterator interface, which lays out the basic methods needed to move through a collection: one to check if there are more items, and another to get the next item. The BookIterator class is a concrete implementation of this interface, specifically designed to work with a collection of book titles. It keeps track of its current position in the collection and knows how to move from one book to the next.

    The Library class acts as our collection of books. It provides a way to add new books and, importantly, a method to create an iterator that can be used to go through its books. This means that the details of how the books are stored—whether in a vector, list, or any other structure—are hidden from the code that uses the library.

    In the main part of the program, we create a Library object, add a few book titles to it, and then use the iterator to print out each book. Notice how the code that prints the books doesn’t need to know anything about how the books are stored inside the library. It simply asks the iterator if there are more books, and if so, gets the next one. This separation makes the code much easier to read, maintain, and extend in the future.

    Pros and Cons of Iterator Pattern

    ProsCons
    Makes it much easier to go through complex data structures, like trees or graphs, without having to understand their internal details.Sometimes, having many different iterator classes can make the codebase more complicated than necessary.
    Encourages code reuse by letting you use the same approach to loop through different types of collections.The extra layer of abstraction can slow things down a bit, especially if you only need to work with simple collections.
    Keeps the way collections are stored private, so you can change the internal structure later without affecting the rest of your code.For very simple collections, using an iterator might be overkill and less efficient than direct access.

    When to Use the Iterator Pattern

    The Iterator pattern is especially helpful in situations like these −

    • If you’re working with several different types of collections-like arrayslinked lists, or trees-and you want to loop through all of them using the same simple approach, the Iterator pattern is a great fit. It saves you from having to write separate, complicated code for each collection type.
    • When you want to keep the inner workings of your collections private, so that the rest of your program doesn’t need to know or care about how the data is actually stored. This means you can change the way your collection is built later, without breaking any code that uses it.
    • If you need to offer multiple ways to go through your collection-like moving forwardbackward, or skipping certain items-the Iterator pattern lets you create different iterators for each scenario, making your code more flexible and user-friendly.
    • When your collections are complicated, such as trees or graphs, and you want to make it as easy as possible for someone else (or even yourself in the future) to use them. The Iterator pattern hides the complexity and lets you focus on what you want to do with each item, not how to get to it.

    Real-World Examples of Iterator Pattern

    Following are some real-world examples where the Iterator Design Pattern is commonly used −

    Real-World Use Cases of Iterator Design Pattern
    • In Java, the java.util.Iterator interface lets you loop through lists, sets, and other collections in a consistent way.
    • In Python, the iterator protocol (using __iter__() and __next__() methods) allows you to use loops with any object that supports iteration.
    • C++’s Standard Template Library (STL) uses iterators to let you move through containers like vectors, lists, and maps, making it easy to write generic code.
    • Database cursors work like iterators, letting you go through query results one row at a time without worrying about how the data is stored.
    • Java’s Stream API uses iterators behind the scenes to process sequences of data in a functional style.
    • Tools that let you browse files and folders on your computer often use iterators to move through directories and files.

    Conclusion

    The Iterator Design Pattern is a practical and widely used solution for working with collections of data. By separating the way you access items from the way they are stored, it makes your code more flexible, easier to maintain, and ready for future changes. Whether you’re building a playlist app, managing a library of books, or working with any kind of collection, the Iterator pattern helps you keep your code clean and adaptable.

  • Facade Design Pattern in C++

    Facade Design Pattern is a structural design pattern that provides a single and simplified interface to a complex system of classes, library or framework. It orginizes a complicated system by adding a simple interface to it.

    Instead of having multiple objects to interact with, the client can interact with a single facade object which internally manages the interactions with the complex system.

    Imagine the following big “Facade” building is like a magic “Play” button for a whole toy factory. You just press that one button, and inside, all the machines start working together automatically to make toys, without you needing to know how each one works.

    Facade Design Pattern Example

    Components of Facade Design Pattern

    The Facade Design Pattern consists of the following three parts −

    • Facade − This is the main part the user talks to. It provides simplified interface to bunch of subsystems. It act as a middleman between client and complex system.
    • Complex System − Many classes that do the real work. These classes or we also call them subsystems are the ones who actually do the tasks. They can be hard to use directly without the facade.
    • Client − The user. Talks only to the facade, not the complex system. Means, the client doesn’t need to know about the complex system, it just uses the facade to get things done.
    Components of Facade Pattern

    Implementation of Facade Design Pattern in C++

    Now, let’s see how we can implement the Facade Design Pattern in C++.

    In this implementation, we will create a simple Home Theater system where we have multiple components like TVSound System, and DVD Player. We will then create a Facade class that provides a simplified interface to control these components.

    Steps to Implement Facade Design Pattern

    Let’s see how we can implement the Facade Design Pattern in C++:

    For this implementation, we follow 5 steps. First we identify the components of complex system. Then we create classes for each component. After that, we create a facade class that provides a simple interface to interact with the complex system. Next, we implement the methods in the facade class to control the components. Finally, we create a client class to use the facade. Final step is to Keep subsystems independent which is totally optional.

    Steps to Implement Facade Design Pattern

    C++ Code for Facade Design Pattern

    Let’s look at the C++ code for the Facade Design Pattern implementation of a Home Theater system.

    Here we will use all the components of the Facade Design Pattern that we discussed earlier. We will create classes for each component of the complex system, a facade class that provides a simple interface to interact with the complex system, and a client class to use the facade.

    #include <iostream>usingnamespace std;// Complex System ComponentsclassTV{public:voidon(){
          cout <<"TV is ON"<< endl;}voidoff(){
          cout <<"TV is OFF"<< endl;}};classSoundSystem{public:voidon(){
          cout <<"Sound System is ON"<< endl;}voidoff(){
          cout <<"Sound System is OFF"<< endl;}};classDVDPlayer{public:voidon(){
          cout <<"DVD Player is ON"<< endl;}voidoff(){
          cout <<"DVD Player is OFF"<< endl;}voidplay(string movie){
          cout <<"Playing movie: "<< movie << endl;}};// FacadeclassHomeTheaterFacade{private:
       TV* tv;
       SoundSystem* soundSystem;
       DVDPlayer* dvdPlayer;public:HomeTheaterFacade(TV* t, SoundSystem* s, DVDPlayer* d
    ):tv(t),soundSystem(s),dvdPlayer(d){}voidwatchMovie(string movie){
          cout <<"Get ready to watch a movie..."<< endl;
          tv->on();
          soundSystem->on();
          dvdPlayer->on();
          dvdPlayer->play(movie);}voidendMovie(){
          cout <<"Shutting down the home theater..."<< endl;
          dvdPlayer->off();
          soundSystem->off();
          tv->off();}};// Clientintmain(){
       TV* tv =newTV();
       SoundSystem* soundSystem =newSoundSystem();
       DVDPlayer* dvdPlayer =newDVDPlayer();
       HomeTheaterFacade* homeTheater =newHomeTheaterFacade(tv, soundSystem, dvdPlayer);
       homeTheater->watchMovie("Inception");
       homeTheater->endMovie();delete homeTheater;delete tv;delete soundSystem;delete dvdPlayer;return0;}

    Following is the output of the above code:

    Get ready to watch a movie...
    TV is ON
    Sound System is ON
    DVD Player is ON
    Playing movie: Inception
    Shutting down the home theater...
    DVD Player is OFF
    Sound System is OFF
    TV is OFF
    

    Pros and Cons of Facade Design Pattern

    The following table highlights the pros and cons of using the Facade Design Pattern −

    ProsCons
    Gives a simple way to use a complex system.Can become too big if it does too much.
    Reduces direct links between client and system.May hide useful features from the client.
    Makes code easier to read and manage by hiding complexity.Can make it hard to use advanced features because they are hidden.
    Helps in organizing code better.Adds another layer to the system, which may slow things down.
    Keeps client and system loosely connected.Can make finding errors harder.

    When to Use Facade Design Pattern?

    Following are some scenarios where you should consider using the Facade Design Pattern −

    • To make a complex system easier to use.
    • For reducing direct connections between client and system.
    • To organize code better.
    • Keeping client and system loosely connected.
    • To hide system details from the client.
    • Making a library or framework simpler to use.
    • Offer a simple interface for common tasks.

    Real-world Applications of Facade Design Pattern

    Following are some real-world applications of the Facade Design Pattern −

    Real Life Applications Facade Design Pattern

    Conclusion

    In this chapter, we learned what the Facade Design Pattern is, its parts, and how to use it effectively. We looked at its good and bad sides, when to use it, and some real uses.