#ifndef SINGLETON_H_
#define SINGLETON_H_
classSingletonfinal{public:staticSingleton&getInstance(){staticSingletontheInstance{};returntheInstance;}intdoSomething(){return42;}// ...more member functions doing more or less useful things here...
private:Singleton()=default;Singleton(constSingleton&)=delete;Singleton(Singleton&&)=delete;Singleton&operator=(constSingleton&)=delete;Singleton&operator=(Singleton&&)=delete;// ...
};#endif
/**
* The Subject owns some important state and notifies observers when the state
* changes.
*/classSubject:publicISubject{public:virtual~Subject(){std::cout<<"Goodbye, I was the Subject.\n";}/**
* The subscription management methods.
*/voidAttach(IObserver*observer)override{list_observer_.push_back(observer);}voidDetach(IObserver*observer)override{list_observer_.remove(observer);}voidNotify()override{std::list<IObserver*>::iteratoriterator=list_observer_.begin();HowManyObserver();while(iterator!=list_observer_.end()){(*iterator)->Update(message_);++iterator;}}voidCreateMessage(std::stringmessage="Empty"){this->message_=message;Notify();}voidHowManyObserver(){std::cout<<"There are "<<list_observer_.size()<<" observers in the list.\n";}/**
* Usually, the subscription logic is only a fraction of what a Subject can
* really do. Subjects commonly hold some important business logic, that
* triggers a notification method whenever something important is about to
* happen (or after it).
*/voidSomeBusinessLogic(){this->message_="change message message";Notify();std::cout<<"I'm about to do some thing important\n";}private:std::list<IObserver*>list_observer_;std::stringmessage_;};
classObserver:publicIObserver{public:Observer(Subject&subject):subject_(subject){this->subject_.Attach(this);std::cout<<"Hi, I'm the Observer \""<<++Observer::static_number_<<"\".\n";this->number_=Observer::static_number_;}virtual~Observer(){std::cout<<"Goodbye, I was the Observer \""<<this->number_<<"\".\n";}voidUpdate(conststd::string&message_from_subject)override{message_from_subject_=message_from_subject;PrintInfo();}voidRemoveMeFromTheList(){subject_.Detach(this);std::cout<<"Observer \""<<number_<<"\" removed from the list.\n";}voidPrintInfo(){std::cout<<"Observer \""<<this->number_<<"\": a new message is available --> "<<this->message_from_subject_<<"\n";}private:std::stringmessage_from_subject_;Subject&subject_;staticintstatic_number_;intnumber_;};
intObserver::static_number_=0;voidClientCode(){Subject*subject=newSubject;Observer*observer1=newObserver(*subject);Observer*observer2=newObserver(*subject);Observer*observer3=newObserver(*subject);Observer*observer4;Observer*observer5;subject->CreateMessage("Hello World! :D");observer3->RemoveMeFromTheList();subject->CreateMessage("The weather is hot today! :p");observer4=newObserver(*subject);observer2->RemoveMeFromTheList();observer5=newObserver(*subject);subject->CreateMessage("My new car is great! ;)");observer5->RemoveMeFromTheList();observer4->RemoveMeFromTheList();observer1->RemoveMeFromTheList();deleteobserver5;deleteobserver4;deleteobserver3;deleteobserver2;deleteobserver1;deletesubject;}intmain(){ClientCode();return0;}
/**
* The Product interface declares the operations that all concrete products must
* implement.
*/classProduct{public:virtual~Product(){}virtualstd::stringOperation()const=0;};/**
* Concrete Products provide various implementations of the Product interface.
*/classConcreteProduct1:publicProduct{public:std::stringOperation()constoverride{return"{Result of the ConcreteProduct1}";}};classConcreteProduct2:publicProduct{public:std::stringOperation()constoverride{return"{Result of the ConcreteProduct2}";}};
/**
* The Creator class declares the factory method that is supposed to return an
* object of a Product class. The Creator's subclasses usually provide the
* implementation of this method.
*/classCreator{/**
* Note that the Creator may also provide some default implementation of the
* factory method.
*/public:virtual~Creator(){};virtualProduct*FactoryMethod()const=0;/**
* Also note that, despite its name, the Creator's primary responsibility is
* not creating products. Usually, it contains some core business logic that
* relies on Product objects, returned by the factory method. Subclasses can
* indirectly change that business logic by overriding the factory method and
* returning a different type of product from it.
*/std::stringSomeOperation()const{// Call the factory method to create a Product object.
Product*product=this->FactoryMethod();// Now, use the product.
std::stringresult="Creator: The same creator's code has just worked with "+product->Operation();deleteproduct;returnresult;}};/**
* Concrete Creators override the factory method in order to change the
* resulting product's type.
*/classConcreteCreator1:publicCreator{/**
* Note that the signature of the method still uses the abstract product type,
* even though the concrete product is actually returned from the method. This
* way the Creator can stay independent of concrete product classes.
*/public:Product*FactoryMethod()constoverride{returnnewConcreteProduct1();}};classConcreteCreator2:publicCreator{public:Product*FactoryMethod()constoverride{returnnewConcreteProduct2();}};
/**
* The client code works with an instance of a concrete creator, albeit through
* its base interface. As long as the client keeps working with the creator via
* the base interface, you can pass it any creator's subclass.
*/voidClientCode(constCreator&creator){// ...
std::cout<<"Client: I'm not aware of the creator's class, but it still works.\n"<<creator.SomeOperation()<<std::endl;// ...
}/**
* The Application picks a creator's type depending on the configuration or
* environment.
*/intmain(){std::cout<<"App: Launched with the ConcreteCreator1.\n";Creator*creator=newConcreteCreator1();ClientCode(*creator);std::cout<<std::endl;std::cout<<"App: Launched with the ConcreteCreator2.\n";Creator*creator2=newConcreteCreator2();ClientCode(*creator2);deletecreator;deletecreator2;return0;}
/**
* Each distinct product of a product family should have a base interface. All
* variants of the product must implement this interface.
*/classAbstractProductA{public:virtual~AbstractProductA(){};virtualstd::stringUsefulFunctionA()const=0;};/**
* Concrete Products are created by corresponding Concrete Factories.
*/classConcreteProductA1:publicAbstractProductA{public:std::stringUsefulFunctionA()constoverride{return"The result of the product A1.";}};classConcreteProductA2:publicAbstractProductA{std::stringUsefulFunctionA()constoverride{return"The result of the product A2.";}};/**
* Here's the the base interface of another product. All products can interact
* with each other, but proper interaction is possible only between products of
* the same concrete variant.
*/classAbstractProductB{/**
* Product B is able to do its own thing...
*/public:virtual~AbstractProductB(){};virtualstd::stringUsefulFunctionB()const=0;/**
* ...but it also can collaborate with the ProductA.
*
* The Abstract Factory makes sure that all products it creates are of the
* same variant and thus, compatible.
*/virtualstd::stringAnotherUsefulFunctionB(constAbstractProductA&collaborator)const=0;};/**
* Concrete Products are created by corresponding Concrete Factories.
*/classConcreteProductB1:publicAbstractProductB{public:std::stringUsefulFunctionB()constoverride{return"The result of the product B1.";}/**
* The variant, Product B1, is only able to work correctly with the variant,
* Product A1. Nevertheless, it accepts any instance of AbstractProductA as an
* argument.
*/std::stringAnotherUsefulFunctionB(constAbstractProductA&collaborator)constoverride{conststd::stringresult=collaborator.UsefulFunctionA();return"The result of the B1 collaborating with ( "+result+" )";}};classConcreteProductB2:publicAbstractProductB{public:std::stringUsefulFunctionB()constoverride{return"The result of the product B2.";}/**
* The variant, Product B2, is only able to work correctly with the variant,
* Product A2. Nevertheless, it accepts any instance of AbstractProductA as an
* argument.
*/std::stringAnotherUsefulFunctionB(constAbstractProductA&collaborator)constoverride{conststd::stringresult=collaborator.UsefulFunctionA();return"The result of the B2 collaborating with ( "+result+" )";}};/**
* The Abstract Factory interface declares a set of methods that return
* different abstract products. These products are called a family and are
* related by a high-level theme or concept. Products of one family are usually
* able to collaborate among themselves. A family of products may have several
* variants, but the products of one variant are incompatible with products of
* another.
*/classAbstractFactory{public:virtualAbstractProductA*CreateProductA()const=0;virtualAbstractProductB*CreateProductB()const=0;};/**
* Concrete Factories produce a family of products that belong to a single
* variant. The factory guarantees that resulting products are compatible. Note
* that signatures of the Concrete Factory's methods return an abstract product,
* while inside the method a concrete product is instantiated.
*/classConcreteFactory1:publicAbstractFactory{public:AbstractProductA*CreateProductA()constoverride{returnnewConcreteProductA1();}AbstractProductB*CreateProductB()constoverride{returnnewConcreteProductB1();}};/**
* Each Concrete Factory has a corresponding product variant.
*/classConcreteFactory2:publicAbstractFactory{public:AbstractProductA*CreateProductA()constoverride{returnnewConcreteProductA2();}AbstractProductB*CreateProductB()constoverride{returnnewConcreteProductB2();}};/**
* The client code works with factories and products only through abstract
* types: AbstractFactory and AbstractProduct. This lets you pass any factory or
* product subclass to the client code without breaking it.
*/voidClientCode(constAbstractFactory&factory){constAbstractProductA*product_a=factory.CreateProductA();constAbstractProductB*product_b=factory.CreateProductB();std::cout<<product_b->UsefulFunctionB()<<"\n";std::cout<<product_b->AnotherUsefulFunctionB(*product_a)<<"\n";deleteproduct_a;deleteproduct_b;}intmain(){std::cout<<"Client: Testing client code with the first factory type:\n";ConcreteFactory1*f1=newConcreteFactory1();ClientCode(*f1);deletef1;std::cout<<std::endl;std::cout<<"Client: Testing the same client code with the second factory type:\n";ConcreteFactory2*f2=newConcreteFactory2();ClientCode(*f2);deletef2;return0;}