Monday, March 17, 2025

Abstract Factory Pattern in C#

Below is a C# implementation of the Abstract Factory design pattern, a Creational pattern, following the Gang of Four (GoF) structure. Each class is placed in its own file and created in an order that avoids dependency issues.


Class Creation Order

To avoid dependency issues, create the classes in this order:

  1. AbstractProductA & AbstractProductB (Abstract Products)
  2. ConcreteProductA1, ConcreteProductA2, ConcreteProductB1, ConcreteProductB2 (Concrete Products)
  3. AbstractFactory (Factory Interface)
  4. ConcreteFactory1 & ConcreteFactory2 (Factory Implementations)
  5. Client Code (Program.cs)

1. Abstract Products (IAbstractProductA.cs & IAbstractProductB.cs)

IAbstractProductA.cs

namespace AbstractFactoryPattern
{
    // Abstract Product A
    public interface IAbstractProductA
    {
        void Use();
    }
}

IAbstractProductB.cs

namespace AbstractFactoryPattern
{
    // Abstract Product B
    public interface IAbstractProductB
    {
        void Use();
    }
}

Explanation

IAbstractProductA and IAbstractProductB define the interfaces for two types of products.
Each product type has a Use() method, which will be implemented by concrete products.


2. Concrete Products

ConcreteProductA1.cs

using System;

namespace AbstractFactoryPattern
{
    // Concrete Product A1
    public class ConcreteProductA1 : IAbstractProductA
    {
        public void Use()
        {
            Console.WriteLine("Using ConcreteProductA1");
        }
    }
}

ConcreteProductA2.cs

using System;

namespace AbstractFactoryPattern
{
    // Concrete Product A2
    public class ConcreteProductA2 : IAbstractProductA
    {
        public void Use()
        {
            Console.WriteLine("Using ConcreteProductA2");
        }
    }
}

ConcreteProductB1.cs

using System;

namespace AbstractFactoryPattern
{
    // Concrete Product B1
    public class ConcreteProductB1 : IAbstractProductB
    {
        public void Use()
        {
            Console.WriteLine("Using ConcreteProductB1");
        }
    }
}

ConcreteProductB2.cs

using System;

namespace AbstractFactoryPattern
{
    // Concrete Product B2
    public class ConcreteProductB2 : IAbstractProductB
    {
        public void Use()
        {
            Console.WriteLine("Using ConcreteProductB2");
        }
    }
}

Explanation

ConcreteProductA1, ConcreteProductA2 implement IAbstractProductA.
ConcreteProductB1, ConcreteProductB2 implement IAbstractProductB.
These represent different product variations.


3. Abstract Factory (IAbstractFactory.cs)

namespace AbstractFactoryPattern
{
    // Abstract Factory Interface
    public interface IAbstractFactory
    {
        IAbstractProductA CreateProductA();
        IAbstractProductB CreateProductB();
    }
}

Explanation:
Defines CreateProductA() and CreateProductB(), which will be implemented by concrete factories.


4. Concrete Factories

ConcreteFactory1.cs

namespace AbstractFactoryPattern
{
    // Concrete Factory 1
    public class ConcreteFactory1 : IAbstractFactory
    {
        public IAbstractProductA CreateProductA()
        {
            return new ConcreteProductA1();
        }

        public IAbstractProductB CreateProductB()
        {
            return new ConcreteProductB1();
        }
    }
}

ConcreteFactory2.cs

namespace AbstractFactoryPattern
{
    // Concrete Factory 2
    public class ConcreteFactory2 : IAbstractFactory
    {
        public IAbstractProductA CreateProductA()
        {
            return new ConcreteProductA2();
        }

        public IAbstractProductB CreateProductB()
        {
            return new ConcreteProductB2();
        }
    }
}

Explanation:
ConcreteFactory1 creates ConcreteProductA1 and ConcreteProductB1.
ConcreteFactory2 creates ConcreteProductA2 and ConcreteProductB2.


5. Client Code (Program.cs)

using System;

namespace AbstractFactoryPattern
{
    class Program
    {
        static void Main(string[] args)
        {
            // Create a factory of type 1
            IAbstractFactory factory1 = new ConcreteFactory1();
            IAbstractProductA productA1 = factory1.CreateProductA();
            IAbstractProductB productB1 = factory1.CreateProductB();

            productA1.Use(); // Output: Using ConcreteProductA1
            productB1.Use(); // Output: Using ConcreteProductB1

            // Create a factory of type 2
            IAbstractFactory factory2 = new ConcreteFactory2();
            IAbstractProductA productA2 = factory2.CreateProductA();
            IAbstractProductB productB2 = factory2.CreateProductB();

            productA2.Use(); // Output: Using ConcreteProductA2
            productB2.Use(); // Output: Using ConcreteProductB2
        }
    }
}

Final Explanation

  1. Abstract Products (IAbstractProductA, IAbstractProductB): Define interfaces for different types of products.
  2. Concrete Products: Implement the abstract product interfaces.
  3. Abstract Factory: Declares factory methods for creating products.
  4. Concrete Factories: Implement factory methods to produce different products.
  5. Client Code: Uses the abstract factory to create product families.

Key Takeaways

  • Encapsulation: The client is independent of concrete product classes.
  • Scalability: Easily add new product families without modifying existing code.
  • Consistency: Ensures related products are created together.
Would you like a downloadable version of this file or to have it combined with the C++/PHP HTML examples into a single learning package?

Tuesday, March 11, 2025

Below is a C++ implementation of the Abstract Factory design pattern, which is a Creational pattern, following the Gang of Four (GoF) structure. Each class is placed in its own file and created in an order that avoids dependency issues.


Class Creation Order

To avoid dependency errors, create the classes in this order:

  1. AbstractProductA & AbstractProductB (Abstract Products)
  2. ConcreteProductA1, ConcreteProductA2, ConcreteProductB1, ConcreteProductB2 (Concrete Products)
  3. AbstractFactory (Factory Interface)
  4. ConcreteFactory1 & ConcreteFactory2 (Factory Implementations)
  5. Client Code (main.cpp)

1. AbstractProductA.h & AbstractProductB.h (Abstract Products)

AbstractProductA.h

#ifndef ABSTRACTPRODUCTA_H
#define ABSTRACTPRODUCTA_H

// Abstract Product A
class AbstractProductA {
public:
    virtual void use() = 0; // Pure virtual function
    virtual ~AbstractProductA() {} // Virtual destructor
};

#endif // ABSTRACTPRODUCTA_H

AbstractProductB.h

#ifndef ABSTRACTPRODUCTB_H
#define ABSTRACTPRODUCTB_H

// Abstract Product B
class AbstractProductB {
public:
    virtual void use() = 0;
    virtual ~AbstractProductB() {} // Virtual destructor
};

#endif // ABSTRACTPRODUCTB_H

Explanation

AbstractProductA and AbstractProductB define the interfaces for the two types of products. Each abstract product contains a use() method, which will be implemented by concrete products.


2. Concrete Products

ConcreteProductA1.h

#ifndef CONCRETEPRODUCTA1_H
#define CONCRETEPRODUCTA1_H

#include "AbstractProductA.h"
#include <iostream>

// Concrete Product A1
class ConcreteProductA1 : public AbstractProductA {
public:
    void use() override {
        std::cout << "Using ConcreteProductA1" << std::endl;
    }
};

#endif // CONCRETEPRODUCTA1_H

ConcreteProductA2.h

#ifndef CONCRETEPRODUCTA2_H
#define CONCRETEPRODUCTA2_H

#include "AbstractProductA.h"
#include <iostream>

// Concrete Product A2
class ConcreteProductA2 : public AbstractProductA {
public:
    void use() override {
        std::cout << "Using ConcreteProductA2" << std::endl;
    }
};

#endif // CONCRETEPRODUCTA2_H

ConcreteProductB1.h

#ifndef CONCRETEPRODUCTB1_H
#define CONCRETEPRODUCTB1_H

#include "AbstractProductB.h"
#include <iostream>

// Concrete Product B1
class ConcreteProductB1 : public AbstractProductB {
public:
    void use() override {
        std::cout << "Using ConcreteProductB1" << std::endl;
    }
};

#endif // CONCRETEPRODUCTB1_H

ConcreteProductB2.h

#ifndef CONCRETEPRODUCTB2_H
#define CONCRETEPRODUCTB2_H

#include "AbstractProductB.h"
#include <iostream>

// Concrete Product B2
class ConcreteProductB2 : public AbstractProductB {
public:
    void use() override {
        std::cout << "Using ConcreteProductB2" << std::endl;
    }
};

#endif // CONCRETEPRODUCTB2_H

Explanation

ConcreteProductA1, ConcreteProductA2 implement AbstractProductA.
ConcreteProductB1, ConcreteProductB2 implement AbstractProductB.
These represent different product variations.


3. AbstractFactory.h (Abstract Factory Interface)

#ifndef ABSTRACTFACTORY_H
#define ABSTRACTFACTORY_H

#include "AbstractProductA.h"
#include "AbstractProductB.h"

// Abstract Factory Interface
class AbstractFactory {
public:
    virtual AbstractProductA* createProductA() = 0;
    virtual AbstractProductB* createProductB() = 0;
    virtual ~AbstractFactory() {} // Virtual destructor
};

#endif // ABSTRACTFACTORY_H

Explanation:
Defines createProductA() and createProductB(), which will be implemented by concrete factories.


4. Concrete Factories

ConcreteFactory1.h

#ifndef CONCRETEFACTORY1_H
#define CONCRETEFACTORY1_H

#include "AbstractFactory.h"
#include "ConcreteProductA1.h"
#include "ConcreteProductB1.h"

// Concrete Factory 1
class ConcreteFactory1 : public AbstractFactory {
public:
    AbstractProductA* createProductA() override {
        return new ConcreteProductA1();
    }

    AbstractProductB* createProductB() override {
        return new ConcreteProductB1();
    }
};

#endif // CONCRETEFACTORY1_H

ConcreteFactory2.h

#ifndef CONCRETEFACTORY2_H
#define CONCRETEFACTORY2_H

#include "AbstractFactory.h"
#include "ConcreteProductA2.h"
#include "ConcreteProductB2.h"

// Concrete Factory 2
class ConcreteFactory2 : public AbstractFactory {
public:
    AbstractProductA* createProductA() override {
        return new ConcreteProductA2();
    }

    AbstractProductB* createProductB() override {
        return new ConcreteProductB2();
    }
};

#endif // CONCRETEFACTORY2_H

Explanation:
ConcreteFactory1 creates ConcreteProductA1 and ConcreteProductB1.
ConcreteFactory2 creates ConcreteProductA2 and ConcreteProductB2.


5. main.cpp (Client Code)

#include <iostream>
#include "ConcreteFactory1.h"
#include "ConcreteFactory2.h"

int main() {
    // Create a factory of type 1
    AbstractFactory* factory1 = new ConcreteFactory1();
    AbstractProductA* productA1 = factory1->createProductA();
    AbstractProductB* productB1 = factory1->createProductB();

    productA1->use(); // Output: Using ConcreteProductA1
    productB1->use(); // Output: Using ConcreteProductB1

    // Create a factory of type 2
    AbstractFactory* factory2 = new ConcreteFactory2();
    AbstractProductA* productA2 = factory2->createProductA();
    AbstractProductB* productB2 = factory2->createProductB();

    productA2->use(); // Output: Using ConcreteProductA2
    productB2->use(); // Output: Using ConcreteProductB2

    // Cleanup
    delete productA1;
    delete productB1;
    delete factory1;

    delete productA2;
    delete productB2;
    delete factory2;

    return 0;
}

Final Explanation

  1. Abstract Products (AbstractProductA & AbstractProductB): Define interfaces for different types of products.
  2. Concrete Products: Implement the abstract products.
  3. Abstract Factory: Declares factory methods for creating products.
  4. Concrete Factories: Implement factory methods to produce different products.
  5. Client Code: Uses the abstract factory to create product families.

Key Takeaways

  • Encapsulation: The client is independent of concrete product classes.
  • Scalability: Easily add new product families without modifying existing code.
  • Consistency: Ensures related products are created together.

Monday, March 03, 2025

Factory Design Pattern in PHP

Here's the detailed breakdown and implementation of the Factory Design Pattern in PHP following the Gang of Four's approach.


Order of Class Creation

  1. Product Interface (Product.php) – Defines the interface that all concrete products must implement.
  2. Concrete Products (ConcreteProductA.php and ConcreteProductB.php) – Implement the product interface.
  3. Creator (Factory) Interface (Creator.php) – Declares the factory method.
  4. Concrete Factories (ConcreteCreatorA.php and ConcreteCreatorB.php) – Implement the factory method to create specific product instances.
  5. Client Code (index.php) – Uses the factory to create objects.

Factory Design Pattern in PHP

I'll generate the code in individual files, following the correct sequence.

1. Product Interface (Product.php)

<?php
// Product.php
// The Product interface declares the operations that all concrete products must implement.

interface Product {
    public function operation(): string;
}
?>
  

Explanation:
This interface ensures that all products created by the factory implement a common method operation().


2. Concrete Products (ConcreteProductA.php and ConcreteProductB.php)

Concrete Product A (ConcreteProductA.php)

<?php
// ConcreteProductA.php
// Implements the Product interface.

require_once "Product.php";

class ConcreteProductA implements Product {
    public function operation(): string {
        return "Result from ConcreteProductA";
    }
}
?>
  

Concrete Product B (ConcreteProductB.php)

<?php
// ConcreteProductB.php
// Implements the Product interface.

require_once "Product.php";

class ConcreteProductB implements Product {
    public function operation(): string {
        return "Result from ConcreteProductB";
    }
}
?>
  

Explanation:
Both ConcreteProductA and ConcreteProductB implement the Product interface.
Each class defines the operation() method, returning a string to identify itself.


3. Factory Interface (Creator.php)

<?php
// Creator.php
// The Creator class declares the factory method.

interface Creator {
    public function factoryMethod(): Product;
}
?>
  

Explanation:
This interface defines a method factoryMethod() that must be implemented by all concrete factories to produce a Product.


4. Concrete Factories (ConcreteCreatorA.php and ConcreteCreatorB.php)

Concrete Factory A (ConcreteCreatorA.php)

<?php
// ConcreteCreatorA.php
// Implements the Creator interface and produces ConcreteProductA.

require_once "Creator.php";
require_once "ConcreteProductA.php";

class ConcreteCreatorA implements Creator {
    public function factoryMethod(): Product {
        return new ConcreteProductA();
    }
}
?>
  

Concrete Factory B (ConcreteCreatorB.php)

<?php
// ConcreteCreatorB.php
// Implements the Creator interface and produces ConcreteProductB.

require_once "Creator.php";
require_once "ConcreteProductB.php";

class ConcreteCreatorB implements Creator {
    public function factoryMethod(): Product {
        return new ConcreteProductB();
    }
}
?>
  

Explanation:
ConcreteCreatorA and ConcreteCreatorB each implement Creator.
They override factoryMethod() to return an instance of a specific Product (ConcreteProductA or ConcreteProductB).


5. Client Code (index.php)

<?php
// index.php
// The client code calls the factory method to create objects.

require_once "ConcreteCreatorA.php";
require_once "ConcreteCreatorB.php";

/**
 * Function to test the factory pattern
 */
function clientCode(Creator $creator) {
    echo "Client: I'm working with " . get_class($creator) . "<br>";
    $product = $creator->factoryMethod();
    echo "Product says: " . $product->operation() . "<br><br>";
}

// Testing both factories
echo "<h2>Factory Method Pattern in PHP</h2>";

echo "<h3>Using ConcreteCreatorA:</h3>";
clientCode(new ConcreteCreatorA());

echo "<h3>Using ConcreteCreatorB:</h3>";
clientCode(new ConcreteCreatorB());

?>
  

Explanation:
The clientCode() function expects an object that implements Creator.
It calls the factoryMethod() to create a product and prints the result.
The index.php script tests both ConcreteCreatorA and ConcreteCreatorB, demonstrating the Factory Pattern in action.


Final Thoughts

This structured approach ensures:

  • Clear separation of concerns (each class has a single responsibility).
  • Encapsulation of object creation in the factory classes.
  • Scalability (new products can be introduced without altering existing code).

Tuesday, February 25, 2025

Java Creational Factory

📁 File Structure

/FactoryMethodPattern
│── Product.java
│── ConcreteProductA.java
│── ConcreteProductB.java
│── Creator.java
│── ConcreteCreatorA.java
│── ConcreteCreatorB.java
│── Main.java
    

1. Product.java (Abstract Product Interface)

// Abstract Product interface
public interface Product {
    void use();
}
    

2. ConcreteProductA.java & ConcreteProductB.java (Concrete Products)

ConcreteProductA.java

// Concrete Product A
public class ConcreteProductA implements Product {
    @Override
    public void use() {
        System.out.println("Using ConcreteProductA");
    }
}
    

ConcreteProductB.java

// Concrete Product B
public class ConcreteProductB implements Product {
    @Override
    public void use() {
        System.out.println("Using ConcreteProductB");
    }
}
    

3. Creator.java (Abstract Factory Class)

// Abstract Creator class
public abstract class Creator {
    // Factory Method: Must be implemented by concrete creators
    public abstract Product factoryMethod();
}
    

4. ConcreteCreatorA.java & ConcreteCreatorB.java (Factory Implementations)

ConcreteCreatorA.java

// Concrete Creator A
public class ConcreteCreatorA extends Creator {
    @Override
    public Product factoryMethod() {
        return new ConcreteProductA();
    }
}
    

ConcreteCreatorB.java

// Concrete Creator B
public class ConcreteCreatorB extends Creator {
    @Override
    public Product factoryMethod() {
        return new ConcreteProductB();
    }
}
    

5. Main.java (Client Code)

public class Main {
    public static void main(String[] args) {
        // Create a factory for ProductA
        Creator creatorA = new ConcreteCreatorA();
        Product productA = creatorA.factoryMethod();
        productA.use(); // Output: Using ConcreteProductA

        // Create a factory for ProductB
        Creator creatorB = new ConcreteCreatorB();
        Product productB = creatorB.factoryMethod();
        productB.use(); // Output: Using ConcreteProductB
    }
}
    

🎯 Key Takeaways

  • Encapsulation: The client does not know which concrete product it gets.
  • Scalability: Easily add new products and factories.
  • Decoupling: The factory method isolates the creation logic.

Monday, February 17, 2025

C# Creational Factory

📁 File Structure

/FactoryMethodPattern
│── IProduct.cs
│── ConcreteProductA.cs
│── ConcreteProductB.cs
│── Creator.cs
│── ConcreteCreatorA.cs
│── ConcreteCreatorB.cs
│── Program.cs
    

1. IProduct.cs (Abstract Product Interface)

namespace FactoryMethodPattern
{
    // Abstract Product Interface
    public interface IProduct
    {
        void Use();
    }
}
    

2. ConcreteProductA.cs & ConcreteProductB.cs (Concrete Products)

ConcreteProductA.cs

using System;

namespace FactoryMethodPattern
{
    // Concrete Product A
    public class ConcreteProductA : IProduct
    {
        public void Use()
        {
            Console.WriteLine("Using ConcreteProductA");
        }
    }
}
    

ConcreteProductB.cs

using System;

namespace FactoryMethodPattern
{
    // Concrete Product B
    public class ConcreteProductB : IProduct
    {
        public void Use()
        {
            Console.WriteLine("Using ConcreteProductB");
        }
    }
}
    

3. Creator.cs (Abstract Factory Class)

namespace FactoryMethodPattern
{
    // Abstract Creator
    public abstract class Creator
    {
        // Factory Method: Must be implemented by concrete creators
        public abstract IProduct FactoryMethod();
    }
}
    

4. ConcreteCreatorA.cs & ConcreteCreatorB.cs (Factory Implementations)

ConcreteCreatorA.cs

namespace FactoryMethodPattern
{
    // Concrete Creator A
    public class ConcreteCreatorA : Creator
    {
        public override IProduct FactoryMethod()
        {
            return new ConcreteProductA();
        }
    }
}
    

ConcreteCreatorB.cs

namespace FactoryMethodPattern
{
    // Concrete Creator B
    public class ConcreteCreatorB : Creator
    {
        public override IProduct FactoryMethod()
        {
            return new ConcreteProductB();
        }
    }
}
    

5. Program.cs (Client Code)

using System;

namespace FactoryMethodPattern
{
    class Program
    {
        static void Main(string[] args)
        {
            // Create a factory for ProductA
            Creator creatorA = new ConcreteCreatorA();
            IProduct productA = creatorA.FactoryMethod();
            productA.Use(); // Output: Using ConcreteProductA

            // Create a factory for ProductB
            Creator creatorB = new ConcreteCreatorB();
            IProduct productB = creatorB.FactoryMethod();
            productB.Use(); // Output: Using ConcreteProductB
        }
    }
}
    

🎯 Key Takeaways

  • Encapsulation: The client does not know which concrete product it gets.
  • Scalability: Easily add new products and factories.
  • Decoupling: The factory method isolates the creation logic.

Saturday, February 15, 2025

C++ Creational Factory

📁 File Structure

/ProjectFolder
│── Product.h
│── ConcreteProduct.h
│── ConcreteProduct.cpp
│── Creator.h
│── ConcreteCreator.h
│── ConcreteCreator.cpp
│── main.cpp
    

1. Product.h (Abstract Product)

#ifndef PRODUCT_H
#define PRODUCT_H

#include <iostream>

// Abstract Product class
class Product {
public:
    virtual void use() = 0; // Pure virtual function to be implemented by concrete products
    virtual ~Product() {} // Virtual destructor for proper cleanup
};

#endif // PRODUCT_H
    

2. ConcreteProduct.h & ConcreteProduct.cpp (Concrete Implementations)

ConcreteProduct.h

#ifndef CONCRETEPRODUCT_H
#define CONCRETEPRODUCT_H

#include "Product.h"

// Concrete Product class
class ConcreteProductA : public Product {
public:
    void use() override; // Implementation of abstract method
};

class ConcreteProductB : public Product {
public:
    void use() override;
};

#endif // CONCRETEPRODUCT_H
    

ConcreteProduct.cpp

#include "ConcreteProduct.h"

// Implement ConcreteProductA's behavior
void ConcreteProductA::use() {
    std::cout << "Using ConcreteProductA" << std::endl;
}

// Implement ConcreteProductB's behavior
void ConcreteProductB::use() {
    std::cout << "Using ConcreteProductB" << std::endl;
}
    

3. Creator.h (Abstract Factory Class)

#ifndef CREATOR_H
#define CREATOR_H

#include "Product.h"

// Abstract Factory class
class Creator {
public:
    virtual Product* factoryMethod() = 0; // Factory method to create objects
    virtual ~Creator() {} // Virtual destructor
};

#endif // CREATOR_H
    

4. ConcreteCreator.h & ConcreteCreator.cpp (Factory Implementations)

ConcreteCreator.h

#ifndef CONCRETECREATOR_H
#define CONCRETECREATOR_H

#include "Creator.h"
#include "ConcreteProduct.h"

// Concrete Creator for ProductA
class ConcreteCreatorA : public Creator {
public:
    Product* factoryMethod() override;
};

// Concrete Creator for ProductB
class ConcreteCreatorB : public Creator {
public:
    Product* factoryMethod() override;
};

#endif // CONCRETECREATOR_H
    

ConcreteCreator.cpp

#include "ConcreteCreator.h"

// Factory method returns an instance of ConcreteProductA
Product* ConcreteCreatorA::factoryMethod() {
    return new ConcreteProductA();
}

// Factory method returns an instance of ConcreteProductB
Product* ConcreteCreatorB::factoryMethod() {
    return new ConcreteProductB();
}
    

5. main.cpp (Client Code)

#include <iostream>
#include "ConcreteCreator.h"

int main() {
    // Create a factory for ProductA
    Creator* creatorA = new ConcreteCreatorA();
    Product* productA = creatorA->factoryMethod();
    productA->use(); // Output: Using ConcreteProductA

    // Create a factory for ProductB
    Creator* creatorB = new ConcreteCreatorB();
    Product* productB = creatorB->factoryMethod();
    productB->use(); // Output: Using ConcreteProductB

    // Cleanup
    delete productA;
    delete creatorA;
    delete productB;
    delete creatorB;

    return 0;
}
    

🎯 Key Takeaways

  • Encapsulation: The factory method ensures the client only depends on the abstract Product interface, not concrete classes.
  • Scalability: Adding new products only requires adding new concrete products and their corresponding creators.
  • Decoupling: The client does not depend on the actual product classes.

Friday, February 14, 2025

PHP Creational Singelton

📁 File Structure

1. Singleton.php - This file contains the actual Singleton class.
2. index.php - This demonstrates the Singleton pattern in action.
3. SomeClass.php - An additional class to showcase how the Singleton can be used with other classes.
    

1. Singleton.php

<?php

class Singleton {
    private static $instance = null;

    // The constructor is private so that the object can't be instantiated from outside
    private function __construct() { }

    // Cloning is disabled to ensure the uniqueness of the instance
    private function __clone() { }

    // This method returns the singleton instance of this class
    public static function getInstance() {
        if (self::$instance === null) {
            self::$instance = new Singleton();
        }
        return self::$instance;
    }
}

?>
    

2. SomeClass.php

<?php

class SomeClass {
    private $singleton;

    public function __construct() {
        $this->singleton = Singleton::getInstance();
    }

    public function doSomething() {
        echo "Using the Singleton instance within SomeClass!";
    }
}

?>
    

3. index.php

<?php

include 'Singleton.php';
include 'SomeClass.php';

// Trying to get two instances of Singleton
$instance1 = Singleton::getInstance();
$instance2 = Singleton::getInstance();

// Both instances are the same
if ($instance1 === $instance2) {
    echo "Both instances are the same!<br>";
}

// Demonstrating the use of Singleton in another class
$obj = new SomeClass();
$obj->doSomething();

?>
    

🛠 Explanation

  • Singleton Class:
    • Private static variable $instance: This holds the only instance of the class.
    • Private Constructor: To prevent any external instantiations.
    • Private __clone Method: To prevent the object from being cloned.
    • getInstance Method: Ensures only one instance is created.
  • SomeClass:
    • Demonstrates how we might use the Singleton within another class.
  • index.php:
    • Demonstrates that both instances retrieved from Singleton::getInstance() are the same.
    • Shows the usage of the Singleton instance within another class.

⚠️ Important Note

When working with the Singleton pattern, ensure you genuinely need a singleton. Overusing this pattern can lead to design issues and difficulties in testing.

Abstract Factory Pattern in C#

Below is a C# implementation of the Abstract Factory design pattern, a Creational pattern, following the Gang of Four (GoF) structure....