Federico Mengozzi

Design Pattern - Creational

Singleton (object level)

  • Intent
    • Guarantee a single instance of a class
    • Provide global point of access to it
  • Motivation
    • One connection to db, instance of window manager
// Extensible singleton
class CExtensibleSingleton;
using *(*TExtensibleSingletonFunction)() = CExtensibleSingleton;

class CExtensibleSingleton {
protected:
    CExtensibleSingleton() {};

    static void Register(const std::string &instanceType, TExtensibleSingletonFunction func);
    static std::map<std::string, TExtensibleSingletonFunction> &Registry() {
        static std::map<std::string, TExtensibleSingletonFunction> StaticRegistry;
        return StaticRegistry;
    }
    static CExtensibleSingleton *DUniqueInstance;

    void Register(const std::string &instanceType, TExtensibleSingletonFunction func) {
        Registry()[instanceType] = func;
    }

public:
    static CExtensibleSingleton *Instance(const std::string &instanceType) {
        if (nullptr == DUniqueInstance) {
            if(Registry().end() != Registry().find(instanceType)) {
                DUniqueInstance = Registry()[instanceType]();
            }
        }
        return DUniqueInstance;
    }
    virtual void Operation() = 0;
}

CExtensibleSingleton *CExtensibleSingleton::DUniqueInstance = nullptr;

// Extended singleton
class CExtendedSingleton : public CExtensibleSingleton {
protected:
    CExtendedSingleton() : CExtensibleSingleton() {}

    static CExtensibleSingleton *ExtendedSingletonInstance() {
        return new CExtendedSingleton();
    }

    class CRegistrant {
    public:
        CRegistrant() {
            CExtensibleSingleton::Register("Extended", CExtendedSingleton:ExtendedSingletonInstance);
        }
    };

    static CRegistrant DRegistrant;
public:
    void Operation() {
        // operation
    }
}
// Thread safe lazy singleton
public class SingletonLazyTS {

    // inner static class are initialized at FIRST use only
    private static class LazyHolder {
        private static final SingletonLazy SINGLETON = new SingletonLazyTS(); 
    }

    private SingletonLazyTS(){};

    public static SingletonLazyTS GetInstance() {
        return LazyHolder.SINGLETON;
    }
}

Factory Method (class level)

  • Intent
    • Have an interface to create object
  • Motivation
    • Reduce redundancy in creating objects
  • Benefits
    • Connect parallel class hierarchies
  • Limitations
    • Refactoring class to use Factory Method breaks existing clients
// Creator
class CCreator {
public:
    void Operation() {
        CProduct *Product = CreateProduct();
        Product->Operation();
        delete Product;
    }
    virtual CProduct *CreateProduct() = 0;
}

// Concrete creator
class CConcreteCreator : public CCreator {
public:
    CProduct *CreateProduct() {
        return new CConcreteProduct();
    }
}

Builder (object level)

  • Intent
    • Separate object construction from its representation
    • Allow same construction process to create different representation
  • Motivation
    • Documents that may require many type conversion
  • Benefits
    • Modify internal representation
    • Gives finer control over construction process
// Director
class CDirector {
protected:
    CBuilder *DBuilder;
public:
    CDirector(CBuilder *builder) {
        *DBuilder = builder;
    }

    void Construct() {
        for (int i=0; i<N; ++i) {
            DBuilder->BuildPart();
        }
    }
}

// Builder
class CBuilder {
public:
    virtual void BuildPart() = 0;
}

class CConcreteBuilder : Public CBuilder {
protected:
    std::vector<CProduct *> DProducts;
public:
    CConcreteBuilder() : CBuilder {}

    void BuildPart() {
        DProducts.push_back(new CProduct);
    } 
}
public class Product {
    private String name;
    private int ID;
    //...

    Product(String name, int id, ...) {
        this.name = name;
        this.ID = id;
        /...
    }
}

public static class Builder {
    private String name;
    private int ID = -1;
    //...

    public Builder name(String s) {
        this.name = s;
        return this;
    }

    public Builder id(int id) {
        this.ID = id;
        return this;
    }

    //...

    public Product build() throws IllegalStateException {
        if (this.name == null || this.ID = -1 || / ...) {
            throw new IllegalStateException("");
        }
        return new Product(name, ID, ...);
    }
}

Abstract Factory (object level)

  • Intent
    • Create families of objects without specifying concrete classes
  • Motivation
    • Support multiple look-and-feel widgets
    • Support multiple database implementation
  • Benefits
    • Isolate concrete classes
    • Make exchanging product family easy
  • Limitations
    • Supporting new product types is difficult
// Abstract Factory
class CAbstractFactory {
public:
    CAbstractProductA *CreateProductA() = 0;
    CAbstractProductB *CreateProductB() = 0;
}

// Abstract Products
class CAbstractProductA {
public:
    virtual void OperationA() = 0;
}

class CAbstractProductB {
public:
    virtual void OperationB() = 0;
}

class CConcreteFactory1 : public CAbstractFactory {
public:
    CAbstractProductA *CreateProductA() {
        return new CConcreteProductA1();
    }
    
    CAbstractProductB *CreateProductB() {
        return new CConcreteProductB1();
    }
}
Go to top