0% found this document useful (0 votes)
14 views

Singleton Pattern C++

The document discusses the Singleton Design Pattern in C++, emphasizing its purpose of ensuring a single instance of a class with global access. It covers both basic and thread-safe implementations, highlighting the use of `std::mutex` and static local variables for thread safety. Additionally, it briefly introduces the Factory and Abstract Factory patterns with Dependency Injection, and the Observer pattern for market data dissemination to TCP clients.

Uploaded by

Gamindu Udayanga
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
14 views

Singleton Pattern C++

The document discusses the Singleton Design Pattern in C++, emphasizing its purpose of ensuring a single instance of a class with global access. It covers both basic and thread-safe implementations, highlighting the use of `std::mutex` and static local variables for thread safety. Additionally, it briefly introduces the Factory and Abstract Factory patterns with Dependency Injection, and the Observer pattern for market data dissemination to TCP clients.

Uploaded by

Gamindu Udayanga
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 31

Singleton Pattern C++

singleton design pattern C++ usage

The Singleton Design Pattern ensures that a class has only one instance and provides a global point of
access to that instance. It is commonly used in C++ for scenarios such as logging, database connections,
configuration management, etc.

Key Features of Singleton Pattern

1. Single Instance: Only one object of the class exists.


2. Global Access: Provides a single, globally accessible point to the instance.
3. Lazy Initialization (Optional): Instance is created only when it is first accessed.

Basic Implementation of Singleton in C++

cpp

#include <iostream>

// Singleton Class
class Singleton {
private:
static Singleton* instance; // Static instance of class

// Private Constructor to prevent object creation


Singleton() {
std::cout << "Singleton instance created.\n";
}

public:
// Delete copy constructor and assignment operator to prevent copying
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;

// Public static method to get the instance


static Singleton* getInstance() {
if (instance == nullptr) { // Lazy initialization
instance = new Singleton();
}
return instance;
}

void showMessage() {
std::cout << "Hello from Singleton!\n";
}
};

// Define static instance


Singleton* Singleton::instance = nullptr;

// Main function
int main() {
Singleton* s1 = Singleton::getInstance();
s1->showMessage();

Singleton* s2 = Singleton::getInstance();

Printed using ChatGPT to PDF, powered by PDFCrowd HTML to PDF API. 1/31
if (s1 == s2) {
std::cout << "Both instances are the same.\n";
}

return 0;
}

Output:

sql

Singleton instance created.


Hello from Singleton!
Both instances are the same.

Modern C++ Thread-Safe Singleton (C++11)

With C++11, we can use `std::mutex` or `static local variable` to ensure thread safety.

Using `std::mutex` (Thread-safe but with locking overhead)

cpp

#include <iostream>
#include <mutex>

class Singleton {
private:
static Singleton* instance;
static std::mutex mutex_;

Singleton() {
std::cout << "Singleton instance created.\n";
}

public:
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;

static Singleton* getInstance() {


std::lock_guard<std::mutex> lock(mutex_); // Thread-safe access
if (instance == nullptr) {
instance = new Singleton();
}
return instance;
}

void showMessage() {
std::cout << "Hello from Singleton!\n";
}
};

// Define static members


Singleton* Singleton::instance = nullptr;
std::mutex Singleton::mutex_;

int main() {
Singleton* s1 = Singleton::getInstance();
s1->showMessage();
return 0;
}

🔹 Drawback: Locking overhead can impact performance.


Printed using ChatGPT to PDF, powered by PDFCrowd HTML to PDF API. 2/31
Using `static local variable` (Thread-safe and efficient)

C++11 guarantees that static local variables are initialized only once in a thread-safe manner.

cpp

#include <iostream>

class Singleton {
private:
Singleton() {
std::cout << "Singleton instance created.\n";
}

public:
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;

static Singleton& getInstance() {


static Singleton instance; // Thread-safe in C++11+
return instance;
}

void showMessage() {
std::cout << "Hello from Singleton!\n";
}
};

int main() {
Singleton& s1 = Singleton::getInstance();
s1.showMessage();

Singleton& s2 = Singleton::getInstance();
if (&s1 == &s2) {
std::cout << "Both instances are the same.\n";
}

return 0;
}

Output:

sql

Singleton instance created.


Hello from Singleton!
Both instances are the same.

🔹 Advantage: No need for explicit locking, faster and more efficient.


When to Use Singleton?

✅ Use Singleton when:


You need one instance of a class globally.
Managing shared resources (e.g., database connections, logging).

🚫 Avoid Singleton when:


It introduces global state, which makes code hard to test and maintain.
It violates the Single Responsibility Principle (SRP).

Printed using ChatGPT to PDF, powered by PDFCrowd HTML to PDF API. 3/31
Summary

Implementation Thread-Safe Performance Complexity


Basic Singleton ❌ No ✅ Fast ✅ Simple
`std::mutex` ✅ Yes ❌ Slower due to locking ✅ Moderate
Static Local Variable ✅ Yes (C++11+) ✅ Fast ✅ Simple
For modern C++, static local variable Singleton is recommended for its simplicity and efficiency.
Would you like an example with smart pointers or dependency injection to avoid Singleton
drawbacks? 🚀

factory & abstract factory dipendency injection

Factory Pattern & Abstract Factory Pattern with Dependency Injection in C++

The Factory Pattern and Abstract Factory Pattern are key creational design patterns that help in
object creation while keeping the creation logic separate from the client code. They are often used in
Dependency Injection (DI) to provide flexibility and scalability.

1. Factory Pattern with Dependency Injection


The Factory Pattern is used when we need to create multiple related objects without exposing the
instantiation logic.

Example: Factory Pattern for Dependency Injection

Consider a scenario where we create different types of databases (`MySQL`, `PostgreSQL`) and inject the
appropriate dependency into a client class.

Step 1: Define an Interface

cpp

#include <iostream>
#include <memory>

// Database Interface
class Database {
public:
virtual void connect() = 0;
virtual ~Database() = default;
};

Step 2: Implement Concrete Classes

cpp

class MySQL : public Database {


public:
Printed using ChatGPT to PDF, powered by PDFCrowd HTML to PDF API. 4/31
void connect() override {
std::cout << "Connected to MySQL database.\n";
}
};

class PostgreSQL : public Database {


public:
void connect() override {
std::cout << "Connected to PostgreSQL database.\n";
}
};

Step 3: Create a Factory to Generate Objects

cpp

class DatabaseFactory {
public:
static std::unique_ptr<Database> createDatabase(const std::string& type) {
if (type == "MySQL") {
return std::make_unique<MySQL>();
} else if (type == "PostgreSQL") {
return std::make_unique<PostgreSQL>();
}
return nullptr;
}
};

Step 4: Inject Dependency in Client Code

cpp

class Application {
private:
std::unique_ptr<Database> db;

public:
// Dependency Injection via Constructor
Application(std::unique_ptr<Database> database) : db(std::move(database)) {}

void run() {
db->connect();
}
};

Step 5: Main Function

cpp

int main() {
// Create a database using Factory
std::unique_ptr<Database> myDatabase = DatabaseFactory::createDatabase("MySQL");

// Inject dependency into Application


Application app(std::move(myDatabase));
app.run();

return 0;
}

Key Points

Printed using ChatGPT to PDF, powered by PDFCrowd HTML to PDF API. 5/31
✅ Loose Coupling: The application doesn't depend on specific database implementations.
✅ Flexible: We can easily switch between MySQL, PostgreSQL, or any other database.
✅ Extensible: Adding new databases doesn't require modifying existing client code.
2. Abstract Factory Pattern with Dependency Injection
The Abstract Factory Pattern is used when we need to create families of related objects without
specifying their concrete classes.

Example: Abstract Factory for Dependency Injection

Let's extend the previous example to include a QueryExecutor along with a Database, ensuring that
both are related.

Step 1: Define Interfaces

cpp

#include <iostream>
#include <memory>

// Abstract Product: Database


class Database {
public:
virtual void connect() = 0;
virtual ~Database() = default;
};

// Abstract Product: Query Executor


class QueryExecutor {
public:
virtual void executeQuery() = 0;
virtual ~QueryExecutor() = default;
};

Step 2: Implement Concrete Products

cpp

// Concrete Database: MySQL


class MySQL : public Database {
public:
void connect() override {
std::cout << "Connected to MySQL database.\n";
}
};

// Concrete Database: PostgreSQL


class PostgreSQL : public Database {
public:
void connect() override {
std::cout << "Connected to PostgreSQL database.\n";
}
};

// Concrete Query Executor for MySQL


class MySQLQueryExecutor : public QueryExecutor {
public:
void executeQuery() override {
std::cout << "Executing MySQL Query...\n";
}

Printed using ChatGPT to PDF, powered by PDFCrowd HTML to PDF API. 6/31
};

// Concrete Query Executor for PostgreSQL


class PostgreSQLQueryExecutor : public QueryExecutor {
public:
void executeQuery() override {
std::cout << "Executing PostgreSQL Query...\n";
}
};

Step 3: Define an Abstract Factory

cpp

class DatabaseFactory {
public:
virtual std::unique_ptr<Database> createDatabase() = 0;
virtual std::unique_ptr<QueryExecutor> createQueryExecutor() = 0;
virtual ~DatabaseFactory() = default;
};

Step 4: Implement Concrete Factories

cpp

class MySQLFactory : public DatabaseFactory {


public:
std::unique_ptr<Database> createDatabase() override {
return std::make_unique<MySQL>();
}
std::unique_ptr<QueryExecutor> createQueryExecutor() override {
return std::make_unique<MySQLQueryExecutor>();
}
};

class PostgreSQLFactory : public DatabaseFactory {


public:
std::unique_ptr<Database> createDatabase() override {
return std::make_unique<PostgreSQL>();
}
std::unique_ptr<QueryExecutor> createQueryExecutor() override {
return std::make_unique<PostgreSQLQueryExecutor>();
}
};

Step 5: Inject Dependencies into Client Code

cpp

class Application {
private:
std::unique_ptr<Database> db;
std::unique_ptr<QueryExecutor> executor;

public:
// Dependency Injection via Abstract Factory
Application(std::unique_ptr<DatabaseFactory> factory) {
db = factory->createDatabase();
executor = factory->createQueryExecutor();
}

void run() {
db->connect();
executor->executeQuery();

Printed using ChatGPT to PDF, powered by PDFCrowd HTML to PDF API. 7/31
}
};

Step 6: Main Function

cpp

int main() {
std::unique_ptr<DatabaseFactory> factory = std::make_unique<MySQLFactory>(); // Change to Postg

// Inject dependency
Application app(std::move(factory));
app.run();

return 0;
}

Key Points

✅ Encapsulation of Object Creation: The client doesn’t need to worry about which database or
executor is used.
✅ Loose Coupling: We can switch the database family just by changing to
`MySQLFactory`
.
✅ Scalability: If we need to add a new database type, we just implement a new factory without
`PostgreSQLFactory`

modifying existing code.

Comparison: Factory vs Abstract Factory

Feature Factory Pattern Abstract Factory Pattern

Usage Used to create one type of object Used to create families of related objects

Example Creating Database objects (MySQL, PostgreSQL) Creating Database + QueryExecutor together
Flexibility Moderate High

Scalability Requires modification for new types Easily extendable with new factories

Conclusion
✅ Factory Pattern is great for single object creation with dependency injection.
✅ Abstract Factory Pattern is useful when multiple related objects need to be created together.
✅ Dependency Injection (DI) ensures loose coupling and flexibility.
✅ Use smart pointers ( ) to manage memory automatically.
`std::unique_ptr`

Would you like an example using shared pointers or a more advanced implementation using
Dependency Injection frameworks like Google’s Guice or Boost.DI? 🚀

observer market data dissmination to tcp clients

Observer Pattern for Market Data Dissemination to TCP Clients in C++

Printed using ChatGPT to PDF, powered by PDFCrowd HTML to PDF API. 8/31
The Observer Pattern is useful when you need to broadcast real-time updates to multiple clients,
making it ideal for market data dissemination. In this example, we will implement a Market Data
Publisher that sends updates to multiple TCP clients using C++.

1. Design Overview
MarketDataPublisher (Subject): Maintains a list of connected clients and notifies them of new
market data.
MarketDataClient (Observer): Listens for updates from the publisher.
TCP Communication: Uses Boost.Asio for handling TCP connections.

2. Implementing the Observer Pattern


Step 1: Define the Observer Interface

cpp

#include <iostream>
#include <string>

// Observer Interface
class MarketDataObserver {
public:
virtual void update(const std::string& data) = 0; // Called when new data is available
virtual ~MarketDataObserver() = default;
};

Step 2: Implement the Subject (Market Data Publisher)

cpp

#include <vector>
#include <algorithm>

// Subject (Market Data Publisher)


class MarketDataPublisher {
private:
std::vector<MarketDataObserver*> observers;

public:
void addObserver(MarketDataObserver* observer) {
observers.push_back(observer);
}

void removeObserver(MarketDataObserver* observer) {


observers.erase(std::remove(observers.begin(), observers.end(), observer), observers.end())
}

void notifyObservers(const std::string& marketData) {


for (auto* observer : observers) {
observer->update(marketData);
}
}

// Simulate receiving new market data


void publishData(const std::string& data) {
std::cout << "Publishing market data: " << data << std::endl;
notifyObservers(data);

Printed using ChatGPT to PDF, powered by PDFCrowd HTML to PDF API. 9/31
}
};

3. TCP Client Implementation (Observer)


We'll use Boost.Asio for TCP communication.

Step 3: Implement a TCP Client (Observer)

cpp

#include <boost/asio.hpp>
#include <thread>

using namespace boost::asio;


using namespace boost::asio::ip;

class MarketDataClient : public MarketDataObserver {


private:
std::string name;
io_service io;
tcp::socket socket;

public:
MarketDataClient(const std::string& clientName, const std::string& host, int port)
: name(clientName), socket(io) {
try {
tcp::resolver resolver(io);
tcp::resolver::query query(host, std::to_string(port));
tcp::resolver::iterator endpoint = resolver.resolve(query);

connect(socket, endpoint);
std::cout << name << " connected to market data server.\n";

// Start a thread to listen for server messages


std::thread(&MarketDataClient::listenForData, this).detach();
} catch (std::exception& e) {
std::cerr << "Error: " << e.what() << "\n";
}
}

void update(const std::string& data) override {


// Send market data to the TCP server
try {
write(socket, buffer(data + "\n"));
} catch (std::exception& e) {
std::cerr << name << " failed to send data: " << e.what() << "\n";
}
}

void listenForData() {
try {
char buf[1024];
while (true) {
size_t len = socket.read_some(buffer(buf));
if (len > 0) {
std::cout << name << " received: " << std::string(buf, len) << std::endl;
}
}
} catch (std::exception& e) {
std::cerr << name << " error receiving data: " << e.what() << "\n";
}
}
};

Printed using ChatGPT to PDF, powered by PDFCrowd HTML to PDF API. 10/31
4. TCP Server for Market Data Publisher
We'll implement a TCP server that listens for client connections and forwards market data.

Step 4: Implement a TCP Server (Subject)

cpp

#include <boost/asio.hpp>
#include <thread>

using namespace boost::asio;


using namespace boost::asio::ip;

class MarketDataServer : public MarketDataPublisher {


private:
io_service io;
tcp::acceptor acceptor;
std::vector<std::shared_ptr<tcp::socket>> clients;

public:
MarketDataServer(int port)
: acceptor(io, tcp::endpoint(tcp::v4(), port)) {
std::cout << "Market Data Server started on port " << port << std::endl;
acceptClients();
}

void acceptClients() {
std::thread([this]() {
while (true) {
auto client = std::make_shared<tcp::socket>(io);
acceptor.accept(*client);
clients.push_back(client);
std::cout << "New client connected\n";
}
}).detach();
}

void notifyObservers(const std::string& marketData) override {


for (auto& client : clients) {
try {
write(*client, buffer(marketData + "\n"));
} catch (std::exception& e) {
std::cerr << "Error sending data to client: " << e.what() << "\n";
}
}
}

void run() {
io.run();
}
};

5. Bringing Everything Together


Step 5: Main Function

cpp

int main() {
// Start the market data server
MarketDataServer server(8080);

// Create market data clients

Printed using ChatGPT to PDF, powered by PDFCrowd HTML to PDF API. 11/31
MarketDataClient client1("Client1", "127.0.0.1", 8080);
MarketDataClient client2("Client2", "127.0.0.1", 8080);

// Register clients as observers


server.addObserver(&client1);
server.addObserver(&client2);

// Simulate market data updates


for (int i = 1; i <= 5; ++i) {
server.publishData("Price Update: " + std::to_string(100 + i));
std::this_thread::sleep_for(std::chrono::seconds(1));
}

return 0;
}

6. Explanation of the Implementation


✅ Observer Pattern for Market Data
keeps track of observers (clients).
`MarketDataPublisher`
When new market data arrives, it notifies all observers (clients).

✅ TCP Server for Market Data


Listens on port 8080 for incoming clients.
Broadcasts market data updates to all connected clients.

✅ TCP Clients Receive Market Data


Connect to the server and listen for data.
`update()` method sends received data over TCP.

7. Sample Output
sql

Market Data Server started on port 8080


Client1 connected to market data server.
Client2 connected to market data server.
New client connected
New client connected
Publishing market data: Price Update: 101
Client1 received: Price Update: 101
Client2 received: Price Update: 101
Publishing market data: Price Update: 102
Client1 received: Price Update: 102
Client2 received: Price Update: 102
...

8. Summary
Feature Implementation
Observer Pattern Market Data Publisher notifies all clients

Printed using ChatGPT to PDF, powered by PDFCrowd HTML to PDF API. 12/31
Feature Implementation
TCP Server Handles client connections and broadcasts updates
TCP Clients Listen for updates and display received data

Boost.Asio Used for efficient TCP networking

This solution scales well and allows multiple clients to receive real-time market data updates.
Would you like me to extend this with WebSockets, ZeroMQ, or Redis pub/sub for even more efficient
market data broadcasting? 🚀

adaptor usage

Adapter Pattern in C++: Usage and Examples

The Adapter Pattern is a structural design pattern that allows incompatible interfaces to work
together by acting as a bridge between them. It is commonly used in legacy system integration, third-
party API adaptation, and interface unification.

1. When to Use the Adapter Pattern?


✅ You have incompatible interfaces that need to work together.
✅ You want to use an existing class but its interface doesn’t match your requirements.
✅ You want to reuse legacy code without modifying its source.
2. Types of Adapter Patterns
Class Adapter (Multiple Inheritance) → Uses private inheritance.
Object Adapter (Composition-based) → Uses composition.

3. Example 1: Class Adapter (Multiple Inheritance)


Let's assume we have an old API for an electric socket that provides 110V power, but we need 220V
power for a modern device.

Step 1: Define the Legacy Interface

cpp

#include <iostream>

// Legacy Interface (Old API)


class OldElectricSocket {
public:
virtual void supply110V() {
std::cout << "Supplying 110V power.\n";
}
};

Printed using ChatGPT to PDF, powered by PDFCrowd HTML to PDF API. 13/31
Step 2: Define the Target Interface

cpp

// Target Interface (New API)


class NewElectricSocket {
public:
virtual void supply220V() = 0;
};

Step 3: Implement the Class Adapter

cpp

// Adapter (inherits from both)


class SocketAdapter : public NewElectricSocket, private OldElectricSocket {
public:
void supply220V() override {
std::cout << "Adapter converting 110V to 220V...\n";
supply110V(); // Call old method
}
};

Step 4: Client Code

cpp

int main() {
NewElectricSocket* socket = new SocketAdapter();
socket->supply220V(); // Uses adapter to convert 110V -> 220V

delete socket;
return 0;
}

Output

css

Adapter converting 110V to 220V...


Supplying 110V power.

✅ Class Adapter uses multiple inheritance to adapt the interface.


✅ Downside: C++ does not support multiple inheritance from two concrete classes.
4. Example 2: Object Adapter (Composition)
Preferred approach in modern C++ (Composition-based design).

Step 1: Define the Legacy Interface

cpp

class OldMediaPlayer {
public:

Printed using ChatGPT to PDF, powered by PDFCrowd HTML to PDF API. 14/31
void playMP3() {
std::cout << "Playing MP3 audio.\n";
}
};

Step 2: Define the Target Interface

cpp

class NewMediaPlayer {
public:
virtual void playAudio() = 0;
virtual ~NewMediaPlayer() = default;
};

Step 3: Implement the Object Adapter

cpp

class MediaAdapter : public NewMediaPlayer {


private:
OldMediaPlayer* oldPlayer; // Using Composition

public:
MediaAdapter(OldMediaPlayer* player) : oldPlayer(player) {}

void playAudio() override {


std::cout << "Adapter converting audio format...\n";
oldPlayer->playMP3(); // Call old API method
}
};

Step 4: Client Code

cpp

int main() {
OldMediaPlayer oldPlayer;
NewMediaPlayer* adapter = new MediaAdapter(&oldPlayer);

adapter->playAudio(); // Converts old MP3 to new audio format

delete adapter;
return 0;
}

Output

css

Adapter converting audio format...


Playing MP3 audio.

✅ Object Adapter uses composition instead of multiple inheritance.


✅ More flexible and reusable than the class adapter approach.
5. Real-World Use Cases
Printed using ChatGPT to PDF, powered by PDFCrowd HTML to PDF API. 15/31
Use Case Example
Third-party Library Integration Wrapping an old C API into a modern C++ class
Database Driver Compatibility Adapting an old database connection class to a new interface

Cross-Platform Development Adapting Windows API calls for Linux compatibility


Hardware Abstraction Adapting different sensor interfaces to a standard interface

6. Summary: Class Adapter vs Object Adapter


Feature Class Adapter (Inheritance) Object Adapter (Composition)
Implementation Uses multiple inheritance Uses composition

Flexibility Less flexible (tightly coupled) More flexible (loosely coupled)


Reusability Limited (cannot adapt multiple classes easily) High (can work with multiple existing classes)
Complexity Higher (inherits from two classes) Lower (uses delegation)

7. Conclusion
🔹 Use Class Adapter when modifying an existing class using inheritance is feasible.
🔹 Use Object Adapter when composition is preferred to increase reusability and flexibility.
🔹 Adapters help modernize legacy code, integrate third-party libraries, and standardize
interfaces.

Would you like an example using Boost, STL, or a real-world library integration scenario? 🚀

statergy in fsm with event queue to mobile attendance system

Strategy Pattern in FSM with Event Queue for a Mobile Attendance System (C++)

This implementation will use:

Strategy Pattern: Different attendance processing strategies (e.g., GPS-based, QR-code-based).


Finite State Machine (FSM): Manages attendance states (e.g., `CHECK_IN`, `CHECK_OUT`).
Event Queue: Processes incoming events asynchronously.
Multithreading (optional): Simulates event processing in a real-time system.

1. Design Overview
Key Components

Component Description
FSM (Finite State Controls different states like `IDLE`, `CHECKING_IN`, `CHECKED_IN`,
Machine) `CHECKED_OUT`.
Strategy Pattern Defines different ways to mark attendance (GPS, QR, NFC).

Printed using ChatGPT to PDF, powered by PDFCrowd HTML to PDF API. 16/31
Component Description
Event Queue Buffers and processes incoming attendance events.
Multithreading Simulates real-time event handling.

2. Implementing the Strategy Pattern


Step 1: Define Attendance Strategies

Different ways to mark attendance (GPS-based, QR-code-based, etc.).

cpp

#include <iostream>
#include <memory>

// Strategy Interface
class AttendanceStrategy {
public:
virtual void markAttendance() = 0;
virtual ~AttendanceStrategy() = default;
};

// Concrete Strategy: GPS-based Attendance


class GPSAttendance : public AttendanceStrategy {
public:
void markAttendance() override {
std::cout << "Marking attendance using GPS.\n";
}
};

// Concrete Strategy: QR Code-based Attendance


class QRCodeAttendance : public AttendanceStrategy {
public:
void markAttendance() override {
std::cout << "Marking attendance using QR Code.\n";
}
};

// Concrete Strategy: NFC-based Attendance


class NFCAttendance : public AttendanceStrategy {
public:
void markAttendance() override {
std::cout << "Marking attendance using NFC.\n";
}
};

3. Implementing the Finite State Machine (FSM)


Step 2: Define FSM States

cpp

enum class AttendanceState {


IDLE, // Waiting for check-in
CHECKING_IN, // Processing attendance
CHECKED_IN, // Successfully checked in
CHECKED_OUT // Successfully checked out
};

Printed using ChatGPT to PDF, powered by PDFCrowd HTML to PDF API. 17/31
Step 3: Implement FSM Class

cpp

#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>

class AttendanceFSM {
private:
AttendanceState state;
std::unique_ptr<AttendanceStrategy> strategy;
std::queue<std::string> eventQueue;
std::mutex queueMutex;
std::condition_variable queueCV;

public:
AttendanceFSM() : state(AttendanceState::IDLE), strategy(nullptr) {}

void setStrategy(std::unique_ptr<AttendanceStrategy> newStrategy) {


strategy = std::move(newStrategy);
}

void processEvent(const std::string& event) {


std::lock_guard<std::mutex> lock(queueMutex);
eventQueue.push(event);
queueCV.notify_one();
}

void run() {
while (true) {
std::unique_lock<std::mutex> lock(queueMutex);
queueCV.wait(lock, [this] { return !eventQueue.empty(); });

std::string event = eventQueue.front();


eventQueue.pop();
lock.unlock();

handleEvent(event);
}
}

private:
void handleEvent(const std::string& event) {
if (event == "CHECK_IN") {
if (state == AttendanceState::IDLE) {
std::cout << "Processing CHECK-IN...\n";
state = AttendanceState::CHECKING_IN;
if (strategy) strategy->markAttendance();
state = AttendanceState::CHECKED_IN;
std::cout << "User checked in successfully.\n";
} else {
std::cout << "Invalid state for CHECK-IN.\n";
}
} else if (event == "CHECK_OUT") {
if (state == AttendanceState::CHECKED_IN) {
std::cout << "Processing CHECK-OUT...\n";
state = AttendanceState::CHECKED_OUT;
std::cout << "User checked out successfully.\n";
} else {
std::cout << "Invalid state for CHECK-OUT.\n";
}
}
}
};

4. Bringing Everything Together

Printed using ChatGPT to PDF, powered by PDFCrowd HTML to PDF API. 18/31
Step 4: Simulating a Mobile Attendance System

cpp

#include <chrono>

int main() {
AttendanceFSM fsm;

// Set an initial strategy (GPS-based)


fsm.setStrategy(std::make_unique<GPSAttendance>());

// Start the FSM in a separate thread


std::thread fsmThread(&AttendanceFSM::run, &fsm);

// Simulate attendance events


std::this_thread::sleep_for(std::chrono::seconds(1));
fsm.processEvent("CHECK_IN");

std::this_thread::sleep_for(std::chrono::seconds(3));
fsm.setStrategy(std::make_unique<QRCodeAttendance>());
fsm.processEvent("CHECK_OUT");

// Join FSM thread (not recommended in real-world usage; used for simulation)
fsmThread.join();

return 0;
}

5. Expected Output
sql

Processing CHECK-IN...
Marking attendance using GPS.
User checked in successfully.
Processing CHECK-OUT...
User checked out successfully.

6. Key Takeaways
Feature Implementation

Strategy Pattern Used for different attendance marking methods (GPS, QR, NFC).
FSM Manages states (`IDLE`, `CHECKING_IN`, `CHECKED_IN`, `CHECKED_OUT`).
Event Queue Handles asynchronous event processing.
Multithreading Allows real-time event handling.

7. Enhancements
WebSocket Integration 📡 : Connect to a mobile app for live updates.
Database Logging 🗄️
: Store attendance history in MySQL/PostgreSQL.
REST API 🌐
: Expose attendance actions via a web API.

Would you like an extension with WebSocket, MySQL, or REST API integration? 🚀
Printed using ChatGPT to PDF, powered by PDFCrowd HTML to PDF API. 19/31
visitor using templates & usage

Visitor Pattern Using Templates in C++

The Visitor Pattern is a behavioral design pattern that allows you to separate an algorithm from the
objects it operates on. When combined with C++ templates, it enables generic visitor
implementations that work with multiple types without modifying the objects.

1. Why Use the Visitor Pattern with Templates?


✅ Type Safety → Allows operations on different types at compile time.
✅ Extensibility → Add new operations without modifying existing classes.
✅ Avoids Type Casting → Uses templates instead of dynamic casting ( ).
✅ Performance → Compile-time polymorphism avoids virtual table lookup overhead.
`dynamic_cast`

2. Template-Based Visitor Implementation


Step 1: Define the Base Element Interface

cpp

#include <iostream>

// Forward declaration of visitor template


template <typename Derived>
class Visitor;

class Element {
public:
virtual ~Element() = default;

// Accept function for visitor


virtual void accept(Visitor<Element>& visitor) = 0;
};

Step 2: Define the Visitor Interface as a Template

cpp

// Visitor base template


template <typename Derived>
class Visitor {
public:
virtual void visit(Derived& element) = 0;
};

🔹 This allows type-specific visit functions at compile time.


Step 3: Define Concrete Elements

Printed using ChatGPT to PDF, powered by PDFCrowd HTML to PDF API. 20/31
cpp

class ConcreteElementA : public Element {


public:
void accept(Visitor<Element>& visitor) override {
visitor.visit(*this);
}

void operationA() {
std::cout << "Operation A on ConcreteElementA\n";
}
};

class ConcreteElementB : public Element {


public:
void accept(Visitor<Element>& visitor) override {
visitor.visit(*this);
}

void operationB() {
std::cout << "Operation B on ConcreteElementB\n";
}
};

🔹 `ConcreteElementA` and `ConcreteElementB` each implement `accept()` to allow visitors to operate on


them.

Step 4: Implement the Template Visitor

cpp

template <typename T>


class ConcreteVisitor : public Visitor<T> {
public:
void visit(T& element) override {
if constexpr (std::is_same_v<T, ConcreteElementA>) {
element.operationA();
} else if constexpr (std::is_same_v<T, ConcreteElementB>) {
element.operationB();
}
}
};

🔹 → Enables compile-time type checking, avoiding dynamic casting.


🔹 Templates ensure strong type checking and avoid unnecessary virtual function calls.
`if constexpr`

Step 5: Using the Visitor Pattern

cpp

int main() {
ConcreteElementA elementA;
ConcreteElementB elementB;

ConcreteVisitor<ConcreteElementA> visitorA;
ConcreteVisitor<ConcreteElementB> visitorB;

elementA.accept(visitorA); // Calls operationA()


elementB.accept(visitorB); // Calls operationB()

return 0;
}

Printed using ChatGPT to PDF, powered by PDFCrowd HTML to PDF API. 21/31
3. Expected Output
nginx

Operation A on ConcreteElementA
Operation B on ConcreteElementB

4. Advantages of Using Templates for Visitor Pattern


Feature Traditional Visitor Template-Based Visitor
Polymorphism Uses virtual functions Uses compile-time dispatch
Performance Virtual function overhead No virtual table lookup

Type Safety Requires dynamic_cast Compile-time type checking


Extensibility Requires modifying base class Can extend via new visitor types

5. Real-World Use Cases


✅ Compilers → AST traversal where different node types (Expressions, Statements) need different
operations.
✅ Game Engines 🎮 → AI characters react differently to different game objects (Walls, Players,
Enemies).
✅ Financial Systems 💰 → Processing different financial instruments (Stocks, Bonds, Futures).
Would you like an example with double dispatch, smart pointers, or multiple visitors? 🚀

visitor class diagram

Visitor Pattern Class Diagram

Here is the UML Class Diagram for the Visitor Pattern:

1. Standard Visitor Pattern (Without Templates)

pgsql

+--------------------+
| Element | (Abstract Base Class)
|--------------------|
| + accept(visitor) | <--- Abstract accept() method
+--------------------+


+-------------+----------------+
| |
| |
+------------------+ +------------------+
| ConcreteElementA | | ConcreteElementB |

Printed using ChatGPT to PDF, powered by PDFCrowd HTML to PDF API. 22/31
|------------------| |------------------|
| + operationA() | | + operationB() |
+------------------+ +------------------+
▲ ▲
| accept(visitor) | accept(visitor)
| |
| |
| +-----------------+
| |
| +--------------------+
| | Visitor | (Abstract Base Visitor)
| |--------------------|
| | + visit(ElementA) | <--- Abstract visit() method
| | + visit(ElementB) |
| +--------------------+
| ▲
| |
+------------------+ +------------------+
| ConcreteVisitorA | | ConcreteVisitorB | (Concrete implementations)
|------------------| |------------------|
| + visit(A) | | + visit(B) |
| + visit(B) | | + visit(A) |
+------------------+ +------------------+

2. Visitor Pattern with C++ Templates

When using C++ Templates, we eliminate the need for multiple `visit()` methods and reduce code
duplication:

pgsql

+----------------------+
| Element | (Abstract Base Class)
|----------------------|
| + accept(visitor) |
+----------------------+


+---------------+----------------+
| |
| |
+------------------+ +------------------+
| ConcreteElementA | | ConcreteElementB |
|------------------| |------------------|
| + operationA() | | + operationB() |
+------------------+ +------------------+
▲ ▲
| accept(visitor) | accept(visitor)
| |
| |
| +-----------------+
| |
| +----------------------+
| | Visitor<T> | (Template Visitor Base)
| |----------------------|
| | + visit(T& element) | <--- Generic visit method
| +----------------------+
| ▲
| |
+--------------------------+
| ConcreteVisitor<T> | (Template Concrete Visitor)
|--------------------------|
| + visit(T& element) |
+--------------------------+

Printed using ChatGPT to PDF, powered by PDFCrowd HTML to PDF API. 23/31
Explanation of the Diagram

Component Description
Declares an `accept()` method that takes a `Visitor` as a
`Element` (Abstract Base Class)
parameter.
`ConcreteElementA, ConcreteElementB` Implements `accept()` and contains specific operations.
`Visitor<T>` (Template Visitor) Defines a templated method `visit(T& element)`.
`ConcreteVisitor<T>` (Template Concrete Implements the visitor logic using `if constexpr` for
Visitor) compile-time dispatch.

Advantages of the Template Approach

✅ Avoids dynamic polymorphism (No virtual functions needed).


✅ More flexible and generic (One visitor class can handle multiple types).
✅ Compile-time optimizations (No need for ).
`dynamic_cast`

Would you like a real-world example such as AST traversal, game entity interactions, or financial
trade processing? 🚀

statergy ,fsm class diagram

Strategy Pattern & Finite State Machine (FSM) Class Diagram

The Strategy Pattern and Finite State Machine (FSM) can be combined to build flexible systems where
behavior changes dynamically based on state transitions. Below are UML class diagrams for both
patterns and a combined design that integrates Strategy with FSM.

1. Strategy Pattern Class Diagram


The Strategy Pattern allows an object to change its behavior dynamically by switching algorithms
(strategies) at runtime.

pgsql

+----------------------+
| Context | (Holds a reference to Strategy)
|----------------------|
| - strategy: Strategy*|
|----------------------|
| + setStrategy() | <---- Allows changing strategy dynamically
| + executeStrategy() |
+----------------------+


+---------------+----------------+
| |
+------------------+ +------------------+
| Strategy | | ConcreteStrategy | (Abstract Strategy)
|------------------| |------------------|
| + execute() | | + execute() |

Printed using ChatGPT to PDF, powered by PDFCrowd HTML to PDF API. 24/31
+------------------+ +------------------+

Explanation

Component Description
Context Maintains a reference to a `Strategy` object and allows changing strategies dynamically.
Strategy (Interface) Defines a common interface for all strategies.

ConcreteStrategy Implements a specific algorithm (e.g., GPS-based, QR Code-based).

2. FSM (Finite State Machine) Class Diagram


The FSM allows an object to transition between different states while maintaining well-defined
behaviors.

lua

+----------------------+
| FSMContext | (Manages State Transitions)
|----------------------|
| - state: State* |
|----------------------|
| + setState(State*) | <---- Switches between states
| + handleEvent() |
+----------------------+


+---------------+----------------+
| |
+------------------+ +------------------+
| State | | ConcreteState | (Abstract State)
|------------------| |------------------|
| + handle() | | + handle() |
+------------------+ +------------------+

Explanation

Component Description
FSMContext Manages state transitions and holds the current state.
State (Interface) Defines a common interface for all states.
ConcreteState Implements a specific state behavior (e.g., `CHECK_IN`, `CHECK_OUT`).

3. Combined Strategy + FSM Class Diagram


This approach integrates Strategy Pattern into FSM, allowing different states to use different strategies
dynamically.

lua

+----------------------+
| FSMContext | (Manages State Transitions & Strategy)
|----------------------|
| - state: State* |

Printed using ChatGPT to PDF, powered by PDFCrowd HTML to PDF API. 25/31
| - strategy: Strategy*|
|----------------------|
| + setState(State*) |
| + setStrategy() | <---- Allows dynamic strategy change
| + handleEvent() |
+----------------------+


+---------------+----------------+
| |
+------------------+ +------------------+
| State | | ConcreteState | (Abstract State)
|------------------| |------------------|
| + handle() | | + handle() |
+------------------+ +------------------+


+---------------+----------------+
| |
+------------------+ +------------------+
| Strategy | | ConcreteStrategy | (Abstract Strategy)
|------------------| |------------------|
| + execute() | | + execute() |
+------------------+ +------------------+

Key Features of the Combined Model

✅ FSM manages state transitions dynamically based on events.


✅ Each state can apply a different strategy to define behavior.
✅ Strategy can be changed dynamically inside any state transition.
✅ Extensible → New states and strategies can be added without modifying existing code.
4. Example Use Case: Mobile Attendance System
FSM States

`IDLE` → Waiting for user action.


`CHECK_IN` → Verifies attendance.
`CHECKED_IN` → User is marked present.
`CHECK_OUT` → User exits.

Attendance Strategies

GPS-based (Location tracking).


QR Code-based (Scanning QR codes).
NFC-based (Near Field Communication).

Would you like a C++ implementation of the combined FSM + Strategy pattern for a real-world
example? 🚀

observer class diagram

Observer Pattern Class Diagram (UML)

Printed using ChatGPT to PDF, powered by PDFCrowd HTML to PDF API. 26/31
The Observer Pattern is a behavioral design pattern that establishes a one-to-many relationship
between objects, ensuring that when one object (Subject) changes state, all dependent objects
(Observers) are notified automatically.

1. Standard Observer Pattern Class Diagram


sql

+----------------------+
| Subject | (Observable)
|----------------------|
| - observers: List<> | <--- Maintains a list of observers
|----------------------|
| + addObserver() | <--- Registers an observer
| + removeObserver() | <--- Unregisters an observer
| + notifyObservers() | <--- Notifies all observers
+----------------------+


+---------------+----------------+
| |
+------------------+ +------------------+
| ConcreteSubject | | Observer | (Abstract Observer)
|------------------| |------------------|
| - state: int | | + update() | <--- Observer Interface
| + setState() | +------------------+
| + getState() | ▲
+------------------+ │
+---------------+----------------+
| |
+------------------+ +------------------+
| ConcreteObserverA | | ConcreteObserverB | (Concrete Implementations)
|------------------| |------------------|
| + update() | | + update() |
+------------------+ +------------------+

2. Explanation of Components
Component Description

Subject (Observable) Maintains a list of observers and notifies them on state changes.
ConcreteSubject Holds the actual state and triggers updates when it changes.
Declares an `update()` method to be implemented by concrete
Observer (Interface)
observers.
ConcreteObserverA,
Implements `update()` to react to subject state changes.
ConcreteObserverB

3. Real-World Example Use Cases


✅ Market Data Broadcasting 📈 → Stock market price updates to multiple traders.
✅ Event Notification System 🔔 → Notifying users about app notifications.
✅ Multithreading Sync 🧵 → Thread-safe update mechanisms.
✅ UI Design 🎨 → Reacting to button clicks or form inputs dynamically.
Would you like a C++ implementation for one of these use cases? 🚀

Printed using ChatGPT to PDF, powered by PDFCrowd HTML to PDF API. 27/31
adaptor class diagram

Adapter Pattern Class Diagram (UML)

The Adapter Pattern is a structural design pattern that enables objects with incompatible interfaces
to work together. It acts as a bridge between two interfaces by converting one interface into another
expected by the client.

1. Standard Adapter Pattern Class Diagram


lua

+----------------------+
| Client | (Uses Target Interface)
|----------------------|
| + request() |
+----------------------+


+----------------------+
| Target | (Expected Interface)
|----------------------|
| + request() |
+----------------------+


+----------------------+
| Adapter | (Bridges Target & Adaptee)
|----------------------|
| - adaptee: Adaptee* | <--- Uses composition
| + request() | <--- Converts Target calls to Adaptee calls
+----------------------+


+----------------------+
| Adaptee | (Incompatible Interface)
|----------------------|
| + specificRequest() | <--- Has a different interface
+----------------------+

2. Explanation of Components
Component Description
Client Uses the Target interface but is unaware of the Adaptee.

Target (Interface) Defines the expected interface for the Client.


Adapter Implements Target, holds a reference to Adaptee, and translates requests.
Adaptee Has an existing incompatible interface that needs adaptation.

3. Real-World Example Use Cases

Printed using ChatGPT to PDF, powered by PDFCrowd HTML to PDF API. 28/31
✅ Legacy System Integration 🔄 → Adapting an old API to a new system.
✅ Hardware Drivers 🔌 → Making different devices work with a common interface.
✅ Database Wrappers 🗄️ → Allowing multiple databases to work with a single query API.
✅ Third-party API Integration 🌍 → Wrapping a third-party API to match internal interfaces.
Would you like a C++ implementation for one of these use cases? 🚀

factory & abstract factory class diagram

Factory Pattern & Abstract Factory Pattern Class Diagram (UML)

The Factory Pattern and Abstract Factory Pattern are creational design patterns used for object
creation while encapsulating instantiation logic.

1. Factory Method Pattern Class Diagram


lua

+----------------------+
| Product (Interface) | (Abstract Product)
|----------------------|
| + operation() |
+----------------------+


+---------------+----------------+
| |
+------------------+ +------------------+
| ConcreteProductA | | ConcreteProductB | (Concrete Implementations)
|------------------| |------------------|
| + operation() | | + operation() |
+------------------+ +------------------+


+----------------------+
| Factory (Interface) | (Abstract Factory)
|----------------------|
| + createProduct() | <--- Factory Method
+----------------------+


+---------------+----------------+
| |
+------------------+ +------------------+
| FactoryA | | FactoryB | (Concrete Factories)
|------------------| |------------------|
| + createProduct() | | + createProduct() |
+------------------+ +------------------+

Explanation of Components

Component Description
Product (Interface) Defines the common interface for all products.
ConcreteProductA, ConcreteProductB Implements the product interface.
Factory (Abstract Class) Defines the factory method `createProduct()`.

Printed using ChatGPT to PDF, powered by PDFCrowd HTML to PDF API. 29/31
Component Description
Concrete Factories (FactoryA, FactoryB) Implements `createProduct()` to create specific products.

2. Abstract Factory Pattern Class Diagram


lua

+----------------------+
| AbstractFactory | (Abstract Factory)
|----------------------|
| + createProductA() | <--- Factory Methods
| + createProductB() |
+----------------------+


+---------------+----------------+
| |
+------------------+ +------------------+
| FactoryA | | FactoryB | (Concrete Factories)
|------------------| |------------------|
| + createProductA() | | + createProductA() |
| + createProductB() | | + createProductB() |
+------------------+ +------------------+
▲ ▲
│ │
+---------------+----------------+ +---------------+----------------+
| | | |
+------------------+ +------------------+ +------------------+ +--------------
| ProductA1 | | ProductA2 | | ProductB1 | | ProductB2
|------------------| |------------------| |------------------| |--------------
| + operation() | | + operation() | | + operation() | | + operation()
+------------------+ +------------------+ +------------------+ +--------------

Explanation of Components

Component Description
AbstractFactory Declares factory methods for different product families.
FactoryA, FactoryB Concrete factories creating different product families.

ProductA1, ProductA2, ProductB1, ProductB2 Concrete products that belong to different families.

3. Factory vs Abstract Factory Comparison


Feature Factory Method Pattern Abstract Factory Pattern
Number of Products
Creates a single type of product Creates a family of related products
Created

Can add new products by extending a


Flexibility Can add new product families easily
single factory
When a single product needs a When multiple related products must be
Use Case
controlled instantiation created together

4. Real-World Use Cases

Printed using ChatGPT to PDF, powered by PDFCrowd HTML to PDF API. 30/31
✅ Factory Method: Creating different types of UI buttons ( `WindowsButton`, `MacButton`).
✅ Abstract Factory: Creating families of UI components ( `Windows UI Factory`, `Mac UI Factory`).
✅ Database Drivers: Connecting different databases ( `MySQLDriver`, `PostgreSQLDriver`).
✅ Game Development: Generating different enemy types ( `OrcFactory`, `ElfFactory`).

Would you like a C++ implementation for one of these patterns? 🚀

Printed using ChatGPT to PDF, powered by PDFCrowd HTML to PDF API. 31/31

You might also like