Sei sulla pagina 1di 53

10/14/2015

C++Programming/Code/DesignPatternsWikibooks,openbooksforanopenworld

C++Programming/Code/DesignPatterns
Contents
1ProgrammingPatterns
1.1CreationalPatterns
1.1.1Builder
1.1.2Factory
1.1.2.1AbstractFactory
1.1.3Prototype
1.1.4Singleton
1.2StructuralPatterns
1.2.1Adapter
1.2.2Bridge
1.2.3Composite
1.2.3.1Decorator
1.2.4Facade
1.2.5Flyweight
1.2.6Proxy
1.2.7CuriouslyRecurringTemplate
1.2.8InterfacebasedProgramming(IBP)
1.3BehavioralPatterns
1.3.1ChainofResponsibility
1.3.2Command
1.3.3Interpreter
1.3.4Iterator
1.3.5Mediator
1.3.6Memento
1.3.7Observer
1.3.8State
1.3.9Strategy
1.3.10TemplateMethod
1.3.11Visitor
1.3.12ModelViewController(MVC)

ProgrammingPatterns
Softwaredesignpatternsareabstractionsthathelpstructuresystemdesigns.Whilenotnew,sincethe
conceptwasalreadydescribedbyChristopherAlexanderinitsarchitecturaltheories,itonlygatheredsome
tractioninprogrammingduetothepublicationofDesignPatterns:ElementsofReusableObjectOriented
SoftwarebookinOctober1994byErichGamma,RichardHelm,RalphJohnsonandJohnVlissides,known
astheGangofFour(GoF),thatidentifiesanddescribes23classicsoftwaredesignpatterns.

https://en.wikibooks.org/w/index.php?title=C%2B%2B_Programming/Code/Design_Patterns&printable=yes

1/53

10/14/2015

C++Programming/Code/DesignPatternsWikibooks,openbooksforanopenworld

Adesignpatternisneitherastaticsolution,norisitanalgorithm.Apatternisawaytodescribeand
addressbyname(mostlyasimplisticdescriptionofitsgoal),arepeatablesolutionorapproachtoa
commondesignproblem,thatis,acommonwaytosolveagenericproblem(howgenericorcomplex,
dependsonhowrestrictedthetargetgoalis).Patternscanemergeontheirownorbydesign.Thisiswhy
designpatternsareusefulasanabstractionovertheimplementationandahelpatdesignstage.Withthis
concept,aneasierwaytofacilitatecommunicationoveradesignchoiceasnormalizationtechniqueisgiven
sothateverypersoncansharethedesignconcept.
Dependingonthedesignproblemtheyaddress,designpatternscanbeclassifiedindifferentcategories,of
whichthemaincategoriesare:
CreationalPatterns
StructuralPatterns
BehavioralPatterns.
PatternsarecommonlyfoundinobjectedorientedprogramminglanguageslikeC++orJava.Theycanbe
seenasatemplateforhowtosolveaproblemthatoccursinmanydifferentsituationsorapplications.Itis
notcodereuse,asitusuallydoesnotspecifycode,butcodecanbeeasilycreatedfromadesignpattern.
Objectorienteddesignpatternstypicallyshowrelationshipsandinteractionsbetweenclassesorobjects
withoutspecifyingthefinalapplicationclassesorobjectsthatareinvolved.
Eachdesignpatternconsistsofthefollowingparts:
Problem/requirement
Touseadesignpattern,weneedtogothroughaminianalysisdesignthatmaybecodedtotestout
thesolution.Thissectionstatestherequirementsoftheproblemwewanttosolve.Thisisusuallya
commonproblemthatwilloccurinmorethanoneapplication.
Forces
Thissectionstatesthetechnologicalboundaries,thathelpsandguidesthecreationofthesolution.
Solution
Thissectiondescribeshowtowritethecodetosolvetheaboveproblem.Thisisthedesignpartofthe
designpattern.Itmaycontainclassdiagrams,sequencediagrams,andorwhateverisneededto
describehowtocodethesolution.
Designpatternscanbeconsideredasastandardizationofcommonlyagreedbestpracticestosolvespecific
designproblems.Oneshouldunderstandthemasawaytoimplementgooddesignpatternswithin
applications.Doingsowillreducetheuseofinefficientandobscuresolutions[citationneeded].Usingdesign
patternsspeedsupyourdesignandhelpstocommunicateittootherprogrammers[citationneeded].

CreationalPatterns
Insoftwareengineering,creationaldesignpatternsaredesignpatternsthatdealwithobjectcreation
mechanisms,tryingtocreateobjectsinamannersuitabletothesituation.Thebasicformofobjectcreation
couldresultindesignproblemsoraddedcomplexitytothedesign.Creationaldesignpatternssolvethis
problembysomehowcontrollingthisobjectcreation.

https://en.wikibooks.org/w/index.php?title=C%2B%2B_Programming/Code/Design_Patterns&printable=yes

2/53

10/14/2015

C++Programming/Code/DesignPatternsWikibooks,openbooksforanopenworld

Inthissectionofthebookweassumethatthereaderhasenoughfamiliaritywithfunctions,global
variables,stackvs.heap,classes,pointers,andstaticmemberfunctionsasintroducedbefore.
Aswewillseethereareseveralcreationaldesignpatterns,andallwilldealwithaspecificimplementation
task,thatwillcreateahigherlevelofabstractiontothecodebase,wewillnowcovereachone.
Builder
TheBuilderCreationalPatternisusedtoseparatetheconstructionofacomplexobjectfromits
representationsothatthesameconstructionprocesscancreatedifferentobjectsrepresentations.
Problem
Wewanttoconstructacomplexobject,howeverwedonotwanttohaveacomplexconstructor
memberoronethatwouldneedmanyarguments.
Solution
Defineanintermediateobjectwhosememberfunctionsdefinethedesiredobjectpartbypartbefore
theobjectisavailabletotheclient.BuilderPatternletsusdefertheconstructionoftheobjectuntilall
theoptionsforcreationhavebeenspecified.
#include<string>
#include<iostream>
usingnamespacestd;
//"Product"
classPizza
{

public:

voidsetDough(conststring&dough)

m_dough=dough;

voidsetSauce(conststring&sauce)

m_sauce=sauce;

voidsetTopping(conststring&topping)

m_topping=topping;

voidopen()const

cout<<"Pizzawith"<<m_dough<<"dough,"<<m_sauce<<"sauceand"

<<m_topping<<"topping.Mmm."<<endl;

private:

stringm_dough;

stringm_sauce;

stringm_topping;
};
//"AbstractBuilder"
classPizzaBuilder
{

public:
virtual~PizzaBuilder(){};

Pizza*getPizza()
{

returnm_pizza;

https://en.wikibooks.org/w/index.php?title=C%2B%2B_Programming/Code/Design_Patterns&printable=yes

3/53

10/14/2015

};

C++Programming/Code/DesignPatternsWikibooks,openbooksforanopenworld

voidcreateNewPizzaProduct()

m_pizza=newPizza;

virtualvoidbuildDough()=0;

virtualvoidbuildSauce()=0;

virtualvoidbuildTopping()=0;
protected:

Pizza*m_pizza;

//
classHawaiianPizzaBuilder:publicPizzaBuilder
{

public:
virtual~HawaiianPizzaBuilder(){};

};

virtualvoidbuildDough()
{

m_pizza>setDough("cross");
}
virtualvoidbuildSauce()
{

m_pizza>setSauce("mild");
}
virtualvoidbuildTopping()
{

m_pizza>setTopping("ham+pineapple");
}

classSpicyPizzaBuilder:publicPizzaBuilder
{

public:
virtual~SpicyPizzaBuilder(){};

};

virtualvoidbuildDough()
{

m_pizza>setDough("panbaked");
}
virtualvoidbuildSauce()
{

m_pizza>setSauce("hot");
}
virtualvoidbuildTopping()
{

m_pizza>setTopping("pepperoni+salami");
}

//
classCook
{

public:

voidsetPizzaBuilder(PizzaBuilder*pb)
{

m_pizzaBuilder=pb;
}
Pizza*getPizza()
{

returnm_pizzaBuilder>getPizza();
}
voidconstructPizza()
{

m_pizzaBuilder>createNewPizzaProduct();

m_pizzaBuilder>buildDough();

m_pizzaBuilder>buildSauce();

https://en.wikibooks.org/w/index.php?title=C%2B%2B_Programming/Code/Design_Patterns&printable=yes

4/53

10/14/2015

};

C++Programming/Code/DesignPatternsWikibooks,openbooksforanopenworld

m_pizzaBuilder>buildTopping();

}
private:

PizzaBuilder*m_pizzaBuilder;

intmain()
{

Cookcook;

PizzaBuilder*hawaiianPizzaBuilder=newHawaiianPizzaBuilder;

PizzaBuilder*spicyPizzaBuilder=newSpicyPizzaBuilder;

cook.setPizzaBuilder(hawaiianPizzaBuilder);

cook.constructPizza();

Pizza*hawaiian=cook.getPizza();

hawaiian>open();

cook.setPizzaBuilder(spicyPizzaBuilder);

cook.constructPizza();

Pizza*spicy=cook.getPizza();

spicy>open();

deletehawaiianPizzaBuilder;

deletespicyPizzaBuilder;

deletehawaiian;

deletespicy;
}

Factory
Definition:Autilityclassthatcreatesaninstanceofaclassfromafamilyofderivedclasses
AbstractFactory

Definition:Autilityclassthatcreatesaninstanceofseveralfamiliesofclasses.Itcanalsoreturnafactory
foracertaingroup.
TheFactoryDesignPatternisusefulinasituationthatrequiresthecreationofmanydifferenttypesof
objects,allderivedfromacommonbasetype.TheFactoryMethoddefinesamethodforcreatingthe
objects,whichsubclassescanthenoverridetospecifythederivedtypethatwillbecreated.Thus,atrun
time,theFactoryMethodcanbepassedadescriptionofadesiredobject(e.g.,astringreadfromuserinput)
andreturnabaseclasspointertoanewinstanceofthatobject.Thepatternworksbestwhenawell
designedinterfaceisusedforthebaseclass,sothereisnoneedtocastthereturnedobject.
Problem
Wewanttodecideatruntimewhatobjectistobecreatedbasedonsomeconfigurationorapplication
parameter.Whenwewritethecode,wedonotknowwhatclassshouldbeinstantiated.
Solution
Defineaninterfaceforcreatinganobject,butletsubclassesdecidewhichclasstoinstantiate.Factory
Methodletsaclassdeferinstantiationtosubclasses.
Inthefollowingexample,afactorymethodisusedtocreatelaptopordesktopcomputerobjectsatruntime.
https://en.wikibooks.org/w/index.php?title=C%2B%2B_Programming/Code/Design_Patterns&printable=yes

5/53

10/14/2015

C++Programming/Code/DesignPatternsWikibooks,openbooksforanopenworld

Let'sstartbydefiningComputer,whichisanabstractbaseclass(interface)anditsderivedclasses:Laptop
andDesktop.
classComputer
{
public:
virtualvoidRun()=0;
virtualvoidStop()=0;

virtual~Computer(){};/*withoutthis,youdonotcallLaptoporDesktopdestructorinthisexample!*/
};
classLaptop:publicComputer
{
public:
virtualvoidRun(){mHibernating=false;};
virtualvoidStop(){mHibernating=true;};
virtual~Laptop(){};/*becausewehavevirtualfunctions,weneedvirtualdestructor*/
private:
boolmHibernating;//Whetherornotthemachineishibernating
};
classDesktop:publicComputer
{
public:
virtualvoidRun(){mOn=true;};
virtualvoidStop(){mOn=false;};
virtual~Desktop(){};
private:
boolmOn;//Whetherornotthemachinehasbeenturnedon
};

TheactualComputerFactoryclassreturnsaComputer,givenarealworlddescriptionoftheobject.
classComputerFactory
{
public:
staticComputer*NewComputer(conststd::string&description)
{
if(description=="laptop")
returnnewLaptop;
if(description=="desktop")
returnnewDesktop;
returnNULL;
}
};

Let'sanalyzethebenefitsofthisdesign.First,thereisacompilationbenefit.Ifwemovetheinterface
Computerintoaseparateheaderfilewiththefactory,wecanthenmovetheimplementationofthe
NewComputer()functionintoaseparateimplementationfile.NowtheimplementationfileforNewComputer()
istheonlyonethatrequiresknowledgeofthederivedclasses.Thus,ifachangeismadetoanyderived
classofComputer,oranewComputersubtypeisadded,theimplementationfileforNewComputer()istheonly
filethatneedstoberecompiled.Everyonewhousesthefactorywillonlycareabouttheinterface,which
shouldremainconsistentthroughoutthelifeoftheapplication.
Also,ifthereisaneedtoaddaclass,andtheuserisrequestingobjectsthroughauserinterface,nocode
callingthefactorymayberequiredtochangetosupporttheadditionalcomputertype.Thecodeusingthe
factorywouldsimplypassonthenewstringtothefactory,andallowthefactorytohandlethenewtypes
entirely.
https://en.wikibooks.org/w/index.php?title=C%2B%2B_Programming/Code/Design_Patterns&printable=yes

6/53

10/14/2015

C++Programming/Code/DesignPatternsWikibooks,openbooksforanopenworld

Imagineprogrammingavideogame,whereyouwouldliketoaddnewtypesofenemiesinthefuture,each
ofwhichhasdifferentAIfunctionsandcanupdatedifferently.Byusingafactorymethod,thecontrollerof
theprogramcancalltothefactorytocreatetheenemies,withoutanydependencyorknowledgeofthe
actualtypesofenemies.Now,futuredeveloperscancreatenewenemies,withnewAIcontrolsandnew
drawingmemberfunctions,addittothefactory,andcreatealevelwhichcallsthefactory,askingforthe
enemiesbyname.CombinethismethodwithanXMLdescriptionoflevels,anddeveloperscouldcreate
newlevelswithouthavingtorecompiletheirprogram.Allthis,thankstotheseparationofcreationof
objectsfromtheusageofobjects.
Anotherexample:
#include<stdexcept>
#include<iostream>
#include<memory>
classPizza{
public:
virtualintgetPrice()const=0;
virtual~Pizza(){};/*withoutthis,nodestructorforderivedPizza'swillbecalled.*/
};

classHamAndMushroomPizza:publicPizza{
public:
virtualintgetPrice()const{return850;};
virtual~HamAndMushroomPizza(){};
};

classDeluxePizza:publicPizza{
public:
virtualintgetPrice()const{return1050;};
virtual~DeluxePizza(){};
};

classHawaiianPizza:publicPizza{
public:
virtualintgetPrice()const{return1150;};
virtual~HawaiianPizza(){};
};

classPizzaFactory{
public:
enumPizzaType{
HamMushroom,
Deluxe,
Hawaiian
};

staticPizza*createPizza(PizzaTypepizzaType){
switch(pizzaType){
caseHamMushroom:
returnnewHamAndMushroomPizza();
caseDeluxe:
returnnewDeluxePizza();
caseHawaiian:
returnnewHawaiianPizza();
}
throw"invalidpizzatype.";
}
};

/*
*Createallavailablepizzasandprinttheirprices
*/
voidpizza_information(PizzaFactory::PizzaTypepizzatype)
{
https://en.wikibooks.org/w/index.php?title=C%2B%2B_Programming/Code/Design_Patterns&printable=yes

7/53

10/14/2015

C++Programming/Code/DesignPatternsWikibooks,openbooksforanopenworld

Pizza*pizza=PizzaFactory::createPizza(pizzatype);
std::cout<<"Priceof"<<pizzatype<<"is"<<pizza>getPrice()<<std::endl;
deletepizza;

intmain()
{

pizza_information(PizzaFactory::HamMushroom);

pizza_information(PizzaFactory::Deluxe);

pizza_information(PizzaFactory::Hawaiian);
}

Prototype
Aprototypepatternisusedinsoftwaredevelopmentwhenthetypeofobjectstocreateisdeterminedbya
prototypicalinstance,whichisclonedtoproducenewobjects.Thispatternisused,forexample,whenthe
inherentcostofcreatinganewobjectinthestandardway(e.g.,usingthenewkeyword)isprohibitively
expensiveforagivenapplication.
Implementation:Declareanabstractbaseclassthatspecifiesapurevirtualclone()method.Anyclassthat
needsa"polymorphicconstructor"capabilityderivesitselffromtheabstractbaseclass,andimplementsthe
clone()operation.
Heretheclientcodefirstinvokesthefactorymethod.Thisfactorymethod,dependingontheparameter,
findsouttheconcreteclass.Onthisconcreteclass,theclone()methodiscalledandtheobjectisreturned
bythefactorymethod.
ThisissamplecodewhichisasampleimplementationofPrototypemethod.Wehavethedetailed
descriptionofallthecomponentshere.
Recordclass,whichisapurevirtualclassthathasapurevirtualmethodclone().
CarRecord,BikeRecordandPersonRecordasconcreteimplementationofaRecordclass.
AnenumRECORD_TYPE_enasonetoonemappingofeachconcreteimplementationof
Recordclass.
RecordFactoryclassthathasaFactorymethodCreateRecord().Thismethodrequiresanenum
RECORD_TYPE_enasparameteranddependingonthisparameteritreturnstheconcrete
implementationofRecordclass.
/**
*ImplementationofPrototypeMethod
**/
#include<iostream>
#include<map>
#include<string>

usingnamespacestd;

enumRECORD_TYPE_en
{
CAR,
BIKE,
PERSON
};

/**
*RecordisthebasePrototype
*/

https://en.wikibooks.org/w/index.php?title=C%2B%2B_Programming/Code/Design_Patterns&printable=yes

8/53

10/14/2015

C++Programming/Code/DesignPatternsWikibooks,openbooksforanopenworld

classRecord
{
public:

Record(){}

virtual~Record(){}

virtualRecord*clone()=0;

virtualvoidprint()=0;
};

/**
*CarRecordisaConcretePrototype
*/

classCarRecord:publicRecord
{
private:
stringm_carName;
intm_ID;

public:
CarRecord(stringcarName,intID)
:Record()
,m_carName(carName)
,m_ID(ID)
{
}

CarRecord(constCarRecord&carRecord)
:Record(carRecord)//callthebasedefaultcopyconstructor
{
m_carName=carRecord.m_carName;
m_ID=carRecord.m_ID;
}

~CarRecord(){}

Record*clone()
{
returnnewCarRecord(*this);
}

voidprint()
{
cout<<"CarRecord"<<endl
<<"Name:"<<m_carName<<endl
<<"Number:"<<m_ID<<endl<<endl;
}
};

/**
*BikeRecordistheConcretePrototype
*/

classBikeRecord:publicRecord
{
private:
stringm_bikeName;

intm_ID;

public:
BikeRecord(stringbikeName,intID)
:Record()
,m_bikeName(bikeName)
,m_ID(ID)
https://en.wikibooks.org/w/index.php?title=C%2B%2B_Programming/Code/Design_Patterns&printable=yes

9/53

10/14/2015

C++Programming/Code/DesignPatternsWikibooks,openbooksforanopenworld

{
}

BikeRecord(constBikeRecord&bikeRecord)
:Record(bikeRecord)
{
m_bikeName=bikeRecord.m_bikeName;
m_ID=bikeRecord.m_ID;
}

~BikeRecord(){}

Record*clone()
{
returnnewBikeRecord(*this);
}

voidprint()
{
cout<<"BikeRecord"<<endl
<<"Name:"<<m_bikeName<<endl
<<"Number:"<<m_ID<<endl<<endl;
}
};

/**
*PersonRecordistheConcretePrototype
*/

classPersonRecord:publicRecord
{
private:
stringm_personName;

intm_age;

public:
PersonRecord(stringpersonName,intage)
:Record()
,m_personName(personName)
,m_age(age)
{
}

PersonRecord(constPersonRecord&personRecord)
:Record(personRecord)
{
m_personName=personRecord.m_personName;
m_age=personRecord.m_age;
}

~PersonRecord(){}

Record*clone()
{
returnnewPersonRecord(*this);
}

voidprint()
{
cout<<"PersonRecord"<<endl
<<"Name:"<<m_personName<<endl
<<"Age:"<<m_age<<endl<<endl;
}
};

/**
*RecordFactoryistheclient
https://en.wikibooks.org/w/index.php?title=C%2B%2B_Programming/Code/Design_Patterns&printable=yes

10/53

10/14/2015

C++Programming/Code/DesignPatternsWikibooks,openbooksforanopenworld

*/

classRecordFactory
{
private:
map<RECORD_TYPE_en,Record*>m_recordReference;

public:
RecordFactory()
{
m_recordReference[CAR]=newCarRecord("Ferrari",5050);
m_recordReference[BIKE]=newBikeRecord("Yamaha",2525);
m_recordReference[PERSON]=newPersonRecord("Tom",25);
}

~RecordFactory()
{
deletem_recordReference[CAR];
deletem_recordReference[BIKE];
deletem_recordReference[PERSON];
}

Record*createRecord(RECORD_TYPE_enenType)
{
returnm_recordReference[enType]>clone();
}
};

intmain()
{
RecordFactory*poRecordFactory=newRecordFactory();

Record*poRecord;
poRecord=poRecordFactory>createRecord(CAR);
poRecord>print();
deletepoRecord;

poRecord=poRecordFactory>createRecord(BIKE);
poRecord>print();
deletepoRecord;

poRecord=poRecordFactory>createRecord(PERSON);
poRecord>print();
deletepoRecord;

deletepoRecordFactory;
return0;
}

Anotherexample:
Toimplementthepattern,declareanabstractbaseclassthatspecifiesapurevirtualclone()member
function.Anyclassthatneedsa"polymorphicconstructor"capabilityderivesitselffromtheabstractbase
class,andimplementstheclone()operation.
Theclient,insteadofwritingcodethatinvokesthenewoperatoronahardwiredclassname,callsthe
clone()memberfunctionontheprototype,callsafactorymemberfunctionwithaparameterdesignating
theparticularconcretederivedclassdesired,orinvokestheclone()memberfunctionthroughsome
mechanismprovidedbyanotherdesignpattern.
classCPrototypeMonster
{
protected:
https://en.wikibooks.org/w/index.php?title=C%2B%2B_Programming/Code/Design_Patterns&printable=yes

11/53

10/14/2015

C++Programming/Code/DesignPatternsWikibooks,openbooksforanopenworld

CString_name;
public:
CPrototypeMonster();
CPrototypeMonster(constCPrototypeMonster&copy);
virtual~CPrototypeMonster();

virtualCPrototypeMonster*Clone()const=0;//Thisforceseveryderivedclasstoprovideanoverloadforthisfuncti
voidName(CStringname);
CStringName()const;
};
classCGreenMonster:publicCPrototypeMonster
{
protected:
int_numberOfArms;
double_slimeAvailable;
public:
CGreenMonster();
CGreenMonster(constCGreenMonster&copy);
~CGreenMonster();

virtualCPrototypeMonster*Clone()const;
voidNumberOfArms(intnumberOfArms);
voidSlimeAvailable(doubleslimeAvailable);

intNumberOfArms()const;
doubleSlimeAvailable()const;
};
classCPurpleMonster:publicCPrototypeMonster
{
protected:
int_intensityOfBadBreath;
double_lengthOfWhiplikeAntenna;
public:
CPurpleMonster();
CPurpleMonster(constCPurpleMonster&copy);
~CPurpleMonster();

virtualCPrototypeMonster*Clone()const;

voidIntensityOfBadBreath(intintensityOfBadBreath);
voidLengthOfWhiplikeAntenna(doublelengthOfWhiplikeAntenna);

intIntensityOfBadBreath()const;
doubleLengthOfWhiplikeAntenna()const;
};
classCBellyMonster:publicCPrototypeMonster
{
protected:
double_roomAvailableInBelly;
public:
CBellyMonster();
CBellyMonster(constCBellyMonster&copy);
~CBellyMonster();

virtualCPrototypeMonster*Clone()const;

voidRoomAvailableInBelly(doubleroomAvailableInBelly);
doubleRoomAvailableInBelly()const;
};
CPrototypeMonster*CGreenMonster::Clone()const
{
returnnewCGreenMonster(*this);
}
CPrototypeMonster*CPurpleMonster::Clone()const
{
https://en.wikibooks.org/w/index.php?title=C%2B%2B_Programming/Code/Design_Patterns&printable=yes

12/53

10/14/2015

C++Programming/Code/DesignPatternsWikibooks,openbooksforanopenworld

returnnewCPurpleMonster(*this);
}
CPrototypeMonster*CBellyMonster::Clone()const
{
returnnewCBellyMonster(*this);
}

Aclientofoneoftheconcretemonsterclassesonlyneedsareference(pointer)toaCPrototypeMonster
classobjecttobeabletocalltheClonefunctionandcreatecopiesofthatobject.Thefunctionbelow
demonstratesthisconcept:
voidDoSomeStuffWithAMonster(constCPrototypeMonster*originalMonster)
{
CPrototypeMonster*newMonster=originalMonster>Clone();
ASSERT(newMonster);

newMonster>Name("MyOwnMonster");
//Addcodedoingallsortsofcoolstuffwiththemonster.
deletenewMonster;
}

NoworiginalMonstercanbepassedasapointertoCGreenMonster,CPurpleMonsterorCBellyMonster.
Singleton
TheSingletonpatternensuresthataclasshasonlyoneinstanceandprovidesaglobalpointofaccessto
thatinstance.Itisnamedafterthesingletonset,whichisdefinedtobeasetcontainingoneelement.Thisis
usefulwhenexactlyoneobjectisneededtocoordinateactionsacrossthesystem.
Checklist
Defineaprivatestaticattributeinthe"singleinstance"class.
Defineapublicstaticaccessorfunctionintheclass.
Do"lazyinitialization"(creationonfirstuse)intheaccessorfunction.
Defineallconstructorstobeprotectedorprivate.
ClientsmayonlyusetheaccessorfunctiontomanipulatetheSingleton.
Let'stakealookathowaSingletondiffersfromothervariabletypes.
Likeaglobalvariable,theSingletonexistsoutsideofthescopeofanyfunctions.Traditional
implementationusesastaticmemberfunctionoftheSingletonclass,whichwillcreateasingleinstanceof
theSingletonclassonthefirstcall,andforeverreturnthatinstance.Thefollowingcodeexampleillustrates
theelementsofaC++singletonclass,thatsimplystoresasinglestring.
classStringSingleton
{
public:
//Someaccessorfunctionsfortheclass,itself
std::stringGetString()const
{returnmString;}
voidSetString(conststd::string&newStr)
{mString=newStr;}

https://en.wikibooks.org/w/index.php?title=C%2B%2B_Programming/Code/Design_Patterns&printable=yes

13/53

10/14/2015

C++Programming/Code/DesignPatternsWikibooks,openbooksforanopenworld

//Themagicfunction,whichallowsaccesstotheclassfromanywhere
//Togetthevalueoftheinstanceoftheclass,call:
//StringSingleton::Instance().GetString();
staticStringSingleton&Instance()
{
//Thislineonlyrunsonce,thuscreatingtheonlyinstanceinexistence
staticStringSingleton*instance=newStringSingleton;
//dereferencingthevariablehere,savesthecallerfromhavingtouse
//thearrowoperator,andremovestemptationtotryanddeletethe
//returnedinstance.
return*instance;//alwaysreturnsthesameinstance
}

private:
//Weneedtomakesomegivenfunctionsprivatetofinishthedefinitionofthesingleton
StringSingleton(){}//defaultconstructoravailableonlytomembersorfriendsofthisclass

//Notethatthenexttwofunctionsarenotgivenbodies,thusanyattempt
//tocallthemimplicitlywillreturnascompilererrors.Thisprevents
//accidentalcopyingoftheonlyinstanceoftheclass.
StringSingleton(constStringSingleton&old);//disallowcopyconstructor
constStringSingleton&operator=(constStringSingleton&old);//disallowassignmentoperator

//Notethatalthoughthisshouldbeallowed,
//somecompilersmaynotimplementprivatedestructors
//Thispreventsothersfromdeletingouronesingleinstance,whichwasotherwisecreatedontheheap
~StringSingleton(){}
private://privatedataforaninstanceofthisclass
std::stringmString;
};

VariationsofSingletons:
ApplicationsofSingletonClass:
Onecommonuseofthesingletondesignpatternisforapplicationconfigurations.Configurationsmayneed
tobeaccessibleglobally,andfutureexpansionstotheapplicationconfigurationsmaybeneeded.The
subsetC'sclosestalternativewouldbetocreateasingleglobalstruct.Thishadthelackofclarityasto
wherethisobjectwasinstantiated,aswellasnotguaranteeingtheexistenceoftheobject.
Take,forexample,thesituationofanotherdeveloperusingyoursingletoninsidetheconstructoroftheir
object.Then,yetanotherdeveloperdecidestocreateaninstanceofthesecondclassintheglobalscope.If
youhadsimplyusedaglobalvariable,theorderoflinkingwouldthenmatter.Sinceyourglobalwillbe
accessed,possiblybeforemainbeginsexecuting,thereisnodefinitionastowhethertheglobalis
initialized,ortheconstructorofthesecondclassiscalledfirst.Thisbehaviorcanthenchangewithslight
modificationstootherareasofcode,whichwouldchangeorderofglobalcodeexecution.Suchanerrorcan
beveryhardtodebug.But,withuseofthesingleton,thefirsttimetheobjectisaccessed,theobjectwill
alsobecreated.Younowhaveanobjectwhichwillalwaysexist,inrelationtobeingused,andwillnever
existifneverused.
Asecondcommonuseofthisclassisinupdatingoldcodetoworkinanewarchitecture.Sincedevelopers
mayhaveusedglobalsliberally,movingthemintoasingleclassandmakingitasingleton,canbean
intermediarysteptobringtheprograminlinetostrongerobjectorientedstructure.
Anotherexample:
#include<iostream>
usingnamespacestd;
https://en.wikibooks.org/w/index.php?title=C%2B%2B_Programming/Code/Design_Patterns&printable=yes

14/53

10/14/2015

C++Programming/Code/DesignPatternsWikibooks,openbooksforanopenworld

/*Placeholderforthreadsynchronizationmutex*/
classMutex
{/*placeholderforcodetocreate,use,andfreeamutex*/
};
/*Placeholderforthreadsynchronizationlock*/
classLock
{public:
Lock(Mutex&m):mutex(m){/*placeholdercodetoacquirethemutex*/}
~Lock(){/*placeholdercodetoreleasethemutex*/}
private:
Mutex&mutex;
};
classSingleton
{public:
staticSingleton*GetInstance();
inta;
~Singleton(){cout<<"InDestructor"<<endl;}
private:
Singleton(int_a):a(_a){cout<<"InConstructor"<<endl;}

staticMutexmutex;
//Notdefined,topreventcopying
Singleton(constSingleton&);
Singleton&operator=(constSingleton&other);
};
MutexSingleton::mutex;
Singleton*Singleton::GetInstance()
{
Locklock(mutex);
cout<<"GetInstance"<<endl;
//Initializedduringfirstaccess
staticSingletoninst(1);
return&inst;
}
intmain()
{
Singleton*singleton=Singleton::GetInstance();
cout<<"Thevalueofthesingleton:"<<singleton>a<<endl;
return0;
}

StructuralPatterns
Adapter
Converttheinterfaceofaclassintoanotherinterfacethatclientsexpect.Adapterletsclassesworktogether
thatcouldn'totherwisebecauseofincompatibleinterfaces.
#include<iostream>
classMuslim{//AbstractTarget

virtual~Muslim()=default;
https://en.wikibooks.org/w/index.php?title=C%2B%2B_Programming/Code/Design_Patterns&printable=yes

15/53

10/14/2015

};

C++Programming/Code/DesignPatternsWikibooks,openbooksforanopenworld

virtualvoidperformsMuslimRitual()=0;

classMuslimFemale:publicMuslim{//ConcreteTarget

virtualvoidperformsMuslimRitual()override{std::cout<<"MuslimgirlperformsMuslimritual."<<std::endl;}
};
classHindu{//AbstractAdaptee

virtual~Hindu()=default;

virtualvoidperformsHinduRitual()=0;
};
classHinduFemale:publicHindu{//ConcreteAdaptee

virtualvoidperformsHinduRitual()override{std::cout<<"HindugirlperformsHinduritual."<<std::endl;}
};
classMuslimRitual{

voidcarryOutRitual(Muslim*muslim){

std::cout<<"OnwiththeMuslimrituals!"<<std::endl;

muslim>performsMuslimRitual();

}
};
classMuslimAdapter:publicMuslim{//Adapter

private:

Hindu*hindu;

public:

MuslimAdapter(Hindu*h):hindu(h){}

virtualvoidperformsMuslimRitual()override{hindu>performsHinduRitual();}
};

intmain(){//Clientcode

HinduFemale*hinduGirl=newHinduFemale;

MuslimFemale*muslimGirl=newMuslimFemale;

MuslimRitualmuslimRitual;
//
muslimRitual.carryOutRitual(hinduGirl);//WillnotcompileofcoursesincetheparametermustbeoftypeMuslim*.

MuslimAdapter*adaptedHindu=newMuslimAdapter(hinduGirl);//hinduGirlhasadaptedtobecomeaMuslim!

muslimRitual.carryOutRitual(muslimGirl);

muslimRitual.carryOutRitual(adaptedHindu);//SonowhinduGirl,intheformofadaptedHindu,participatesinthemu
//NotethathinduGirliscarryingoutherowntypeofritualinmuslimRitualthough.

deleteadaptedHindu;//adaptedHinduisnotneededanymore
}

Bridge
TheBridgePatternisusedtoseparateouttheinterfacefromitsimplementation.Doingthisgivesthe
flexibilitysothatbothcanvaryindependently.
Thefollowingexamplewilloutput:
API1.circleat1:27.5
API2.circleat5:727.5

#include<iostream>
usingnamespacestd;
/*Implementor*/
classDrawingAPI{
public:
https://en.wikibooks.org/w/index.php?title=C%2B%2B_Programming/Code/Design_Patterns&printable=yes

16/53

10/14/2015

C++Programming/Code/DesignPatternsWikibooks,openbooksforanopenworld

virtualvoiddrawCircle(doublex,doubley,doubleradius)=0;
virtual~DrawingAPI(){}
};
/*ConcreteImplementorA*/
classDrawingAPI1:publicDrawingAPI{
public:
voiddrawCircle(doublex,doubley,doubleradius){
cout<<"API1.circleat"<<x<<':'<<y<<''<<radius<<endl;
}
};
/*ConcreteImplementorB*/
classDrawingAPI2:publicDrawingAPI{
public:
voiddrawCircle(doublex,doubley,doubleradius){
cout<<"API2.circleat"<<x<<':'<<y<<''<<radius<<endl;
}
};
/*Abstraction*/
classShape{
public:
virtual~Shape(){}
virtualvoiddraw()=0;
virtualvoidresizeByPercentage(doublepct)=0;
};
/*RefinedAbstraction*/
classCircleShape:publicShape{
public:
CircleShape(doublex,doubley,doubleradius,DrawingAPI*drawingAPI):

m_x(x),m_y(y),m_radius(radius),m_drawingAPI(drawingAPI)
{}
voiddraw(){
m_drawingAPI>drawCircle(m_x,m_y,m_radius);
}
voidresizeByPercentage(doublepct){
m_radius*=pct;
}
private:
doublem_x,m_y,m_radius;
DrawingAPI*m_drawingAPI;
};
intmain(void){
CircleShapecircle1(1,2,3,newDrawingAPI1());
CircleShapecircle2(5,7,11,newDrawingAPI2());
circle1.resizeByPercentage(2.5);
circle2.resizeByPercentage(2.5);
circle1.draw();
circle2.draw();
return0;
}

Composite
Compositeletsclientstreatindividualobjectsandcompositionsofobjectsuniformly.TheComposite
patterncanrepresentboththeconditions.Inthispattern,onecandeveloptreestructuresforrepresenting
partwholehierarchies.
#include<vector>
#include<iostream>//std::cout
#include<memory>//std::auto_ptr
#include<algorithm>//std::for_each
https://en.wikibooks.org/w/index.php?title=C%2B%2B_Programming/Code/Design_Patterns&printable=yes

17/53

10/14/2015

C++Programming/Code/DesignPatternsWikibooks,openbooksforanopenworld

#include<functional>//std::mem_fun
usingnamespacestd;

classGraphic
{
public:
virtualvoidprint()const=0;
virtual~Graphic(){}
};

classEllipse:publicGraphic
{
public:
voidprint()const{
cout<<"Ellipse\n";
}
};

classCompositeGraphic:publicGraphic
{
public:
voidprint()const{
//foreachelementingraphicList_,calltheprintmemberfunction
for_each(graphicList_.begin(),graphicList_.end(),mem_fun(&Graphic::print));
}

voidadd(Graphic*aGraphic){
graphicList_.push_back(aGraphic);
}

private:
vector<Graphic*>graphicList_;
};

intmain()
{
//Initializefourellipses
constauto_ptr<Ellipse>ellipse1(newEllipse());
constauto_ptr<Ellipse>ellipse2(newEllipse());
constauto_ptr<Ellipse>ellipse3(newEllipse());
constauto_ptr<Ellipse>ellipse4(newEllipse());

//Initializethreecompositegraphics
constauto_ptr<CompositeGraphic>graphic(newCompositeGraphic());
constauto_ptr<CompositeGraphic>graphic1(newCompositeGraphic());
constauto_ptr<CompositeGraphic>graphic2(newCompositeGraphic());

//Composesthegraphics
graphic1>add(ellipse1.get());
graphic1>add(ellipse2.get());
graphic1>add(ellipse3.get());

graphic2>add(ellipse4.get());

graphic>add(graphic1.get());
graphic>add(graphic2.get());

//Printsthecompletegraphic(fourtimesthestring"Ellipse")
graphic>print();
return0;
}

Decorator

https://en.wikibooks.org/w/index.php?title=C%2B%2B_Programming/Code/Design_Patterns&printable=yes

18/53

10/14/2015

C++Programming/Code/DesignPatternsWikibooks,openbooksforanopenworld

Thedecoratorpatternhelpstoattachadditionalbehaviororresponsibilitiestoanobjectdynamically.
Decoratorsprovideaflexiblealternativetosubclassingforextendingfunctionality.Thisisalsocalled
Wrapper.Ifyourapplicationdoessomekindoffiltering,thenDecoratormightbegoodpatternto
considerforthejob.
#include<string>
#include<iostream>
usingnamespacestd;
classCar//OurAbstractbaseclass
{
protected:
string_str;
public:
Car()
{
_str="UnknownCar";
}

virtualstringgetDescription()
{
return_str;
}

virtualdoublegetCost()=0;

virtual~Car()
{
cout<<"~Car()\n";
}
};

classOptionsDecorator:publicCar//DecoratorBaseclass
{
public:
virtualstringgetDescription()=0;

virtual~OptionsDecorator()
{
cout<<"~OptionsDecorator()\n";
}
};

classCarModel1:publicCar
{
public:
CarModel1()
{
_str="CarModel1";
}
virtualdoublegetCost()
{
return31000.23;
}

~CarModel1()
{
cout<<"~CarModel1()\n";
}
};

classNavigation:publicOptionsDecorator
{
Car*_b;
public:
https://en.wikibooks.org/w/index.php?title=C%2B%2B_Programming/Code/Design_Patterns&printable=yes

19/53

10/14/2015

C++Programming/Code/DesignPatternsWikibooks,openbooksforanopenworld

Navigation(Car*b)
{
_b=b;
}
stringgetDescription()
{
return_b>getDescription()+",Navigation";
}

doublegetCost()
{
return300.56+_b>getCost();
}
~Navigation()
{
cout<<"~Navigation()\n";
}
};

classPremiumSoundSystem:publicOptionsDecorator
{
Car*_b;
public:
PremiumSoundSystem(Car*b)
{
_b=b;
}
stringgetDescription()
{
return_b>getDescription()+",PremiumSoundSystem";
}

doublegetCost()
{
return0.30+_b>getCost();
}
~PremiumSoundSystem()
{
cout<<"~PremiumSoundSystem()\n";
}
};

classManualTransmission:publicOptionsDecorator
{
Car*_b;
public:
ManualTransmission(Car*b)
{
_b=b;
}
stringgetDescription()
{

return_b>getDescription()+",ManualTransmission";
}

doublegetCost()
{
return0.30+_b>getCost();
}
~ManualTransmission()
{
cout<<"~ManualTransmission()\n";
}
};

classCarDecoratorExample{

public:

voidexecute()
{
https://en.wikibooks.org/w/index.php?title=C%2B%2B_Programming/Code/Design_Patterns&printable=yes

20/53

10/14/2015

C++Programming/Code/DesignPatternsWikibooks,openbooksforanopenworld

//CreateourCarthatwewanttobuy
Car*b=newCarModel1();

cout<<"Basemodelof"<<b>getDescription()<<"costs$"<<b>getCost()<<"\n";

//Whowantsbasemodelletsaddsomemorefeatures

b=newNavigation(b);
cout<<b>getDescription()<<"willcostyou$"<<b>getCost()<<"\n";
b=newPremiumSoundSystem(b);
b=newManualTransmission(b);
cout<<b>getDescription()<<"willcostyou$"<<b>getCost()<<"\n";
//WARNING!HereweleaktheCarModel1,NavigationandPremiumSoundSystem
//objects!eitherwedeletethemexplicitlyorrewritetheDecoratorstotake
//ownershipanddeletetheirCarswhendestroyed.
deleteb;
}

};
intmain()
{

CarDecoratorExampleb;

b.execute();

return0;
}

Theoutputoftheprogramaboveis:
BasemodelofCarModel1costs$31000.2
CarModel1,Navigationwillcostyou$31300.8
CarModel1,Navigation,PremiumSoundSystem,ManualTransmissionwillcostyou$31301.4
~ManualTransmission()
~OptionsDecorator()
~Car()

Anotherexample:
#include<iostream>
#include<string>
#include<memory>
classInterface{

public:

virtual~Interface(){}

virtualvoidwrite(std::string&)=0;
};
classCore:publicInterface{

public:

~Core(){std::cout<<"Coredestructorcalled.\n";}

virtualvoidwrite(std::string&text)override{};//Donothing.
};
classDecorator:publicInterface{

private:

std::unique_ptr<Interface>interface;

public:

Decorator(std::unique_ptr<Interface>c){interface=std::move(c);}

virtualvoidwrite(std::string&text)override{interface>write(text);}
};
classMessengerWithSalutation:publicDecorator{
https://en.wikibooks.org/w/index.php?title=C%2B%2B_Programming/Code/Design_Patterns&printable=yes

21/53

10/14/2015

};

C++Programming/Code/DesignPatternsWikibooks,openbooksforanopenworld

private:

std::stringsalutation;
public:

MessengerWithSalutation(std::unique_ptr<Interface>c,conststd::string&str):Decorator(std::move(c)),

~MessengerWithSalutation(){std::cout<<"Messengerdestructorcalled.\n";}

virtualvoidwrite(std::string&text)override{

text=salutation+"\n\n"+text;

Decorator::write(text);

classMessengerWithValediction:publicDecorator{

private:

std::stringvalediction;

public:

MessengerWithValediction(std::unique_ptr<Interface>c,conststd::string&str):Decorator(std::move(c

~MessengerWithValediction(){std::cout<<"MessengerWithValedictiondestructorcalled.\n";}

virtualvoidwrite(std::string&text)override{

Decorator::write(text);

text+="\n\n"+valediction;

}
};

intmain(){

conststd::stringsalutation="Greetings,",valediction="Sincerly,Andy";

std::stringmessage1="Thismessageisnotdecorated.",

message2="Thismessageisdecoratedwithasalutation.",

message3="Thismessageisdecoratedwithavalediction.",

message4="Thismessageisdecoratedwithasalutationandavalediction.";

std::unique_ptr<Interface>messenger1=std::make_unique<Core>();

std::unique_ptr<Interface>messenger2=std::make_unique<MessengerWithSalutation>(std::make_unique<Core

std::unique_ptr<Interface>messenger3=std::make_unique<MessengerWithValediction>(std::make_unique<Core

std::unique_ptr<Interface>messenger4=std::make_unique<MessengerWithValediction>(std::make_unique<Messenge
(std::make_unique<Core>(),salutation),valediction);

messenger1>write(message1);

std::cout<<message1<<'\n';

std::cout<<"\n\n\n";

messenger2>write(message2);

std::cout<<message2<<'\n';

std::cout<<"\n\n\n";

messenger3>write(message3);

std::cout<<message3<<'\n';

std::cout<<"\n\n\n";

messenger4>write(message4);

std::cout<<message4<<'\n';

std::cout<<"\n\n\n";

}
}

Theoutputoftheprogramaboveis:
Thismessageisnotdecorated.

Greetings,
Thismessageisdecoratedwithasalutation.

Thismessageisdecoratedwithavalediction.
Sincerly,Andy
https://en.wikibooks.org/w/index.php?title=C%2B%2B_Programming/Code/Design_Patterns&printable=yes

22/53

10/14/2015

C++Programming/Code/DesignPatternsWikibooks,openbooksforanopenworld

Greetings,
Thismessageisdecoratedwithasalutationandavalediction.
Sincerly,Andy

MessengerWithValedictiondestructorcalled.
Messengerdestructorcalled.
Coredestructorcalled.
MessengerWithValedictiondestructorcalled.
Coredestructorcalled.
Messengerdestructorcalled.
Coredestructorcalled.
Coredestructorcalled.

Facade
TheFacadePatternhidesthecomplexitiesofthesystembyprovidinganinterfacetotheclientfromwhere
theclientcanaccessthesystemonanunifiedinterface.Facadedefinesahigherlevelinterfacethatmakes
thesubsystemeasiertouse.Forinstancemakingoneclassmethodperformacomplexprocessbycalling
severalotherclasses.
/*FacadeisoneoftheeasiestpatternsIthink...Andthisisverysimpleexample.

Imagineyousetupasmarthousewhereeverythingisonremote.SototurnthelightsonyoupushlightsonbuttonAndsame
AC,Alarm,Music,etc...

Whenyouleaveahouseyouwouldneedtopusha100buttonstomakesureeverythingisoffandaregoodtogowhichcouldbe
annoyingifyouarelazylikeme
soIdefinedaFacadeforleavingandcomingback.(Facadefunctionsrepresentbuttons...)SowhenIcomeandleaveIjustma
callandittakescareofeverything...
*/
#include<string>
#include<iostream>
usingnamespacestd;
classAlarm
{
public:

voidalarmOn()

cout<<"Alarmisonandhouseissecured"<<endl;

};

voidalarmOff()
{

cout<<"Alarmisoffandyoucangointothehouse"<<endl;
}

classAc
{
public:

voidacOn()

cout<<"Acison"<<endl;

}
https://en.wikibooks.org/w/index.php?title=C%2B%2B_Programming/Code/Design_Patterns&printable=yes

23/53

10/14/2015

};

C++Programming/Code/DesignPatternsWikibooks,openbooksforanopenworld

voidacOff()
{

cout<<"ACisoff"<<endl;
}

classTv
{
public:

voidtvOn()

cout<<"Tvison"<<endl;

voidtvOff()
{

cout<<"TVisoff"<<endl;
}

};
classHouseFacade
{

Alarmalarm;

Acac;

Tvtv;
public:

HouseFacade(){}

voidgoToWork()
{

ac.acOff();

tv.tvOff();

alarm.alarmOn();
}

voidcomeHome()
{

alarm.alarmOff();

ac.acOn();

tv.tvOn();
}

};
intmain()
{
HouseFacadehf;
//Ratherthancalling100differentonandofffunctionsthankstofacadeIonlyhave2functions...
hf.goToWork();
hf.comeHome();
}

Theoutputoftheprogramaboveis:
ACisoff
TVisoff
Alarmisonandhouseissecured
Alarmisoffandyoucangointothehouse
Acison
Tvison
https://en.wikibooks.org/w/index.php?title=C%2B%2B_Programming/Code/Design_Patterns&printable=yes

24/53

10/14/2015

C++Programming/Code/DesignPatternsWikibooks,openbooksforanopenworld

Flyweight
Thepatternforsavingmemory(basically)bysharingpropertiesofobjects.Imagineahugeamountof
similarobjectswhichallhavemostoftheirpropertiesthesame.It'snaturaltomovethesepropertiesoutof
theseobjectstosomeexternaldatastructureandprovideeachobjectwiththelinktothatdatastructure.
#include<iostream>
#include<string>
#include<vector>
#defineNUMBER_OF_SAME_TYPE_CHARS3;
/*Actualflyweightobjectsclass(declaration)*/
classFlyweightCharacter;
/*

FlyweightCharacterAbstractBuilderisaclassholdingthepropertieswhicharesharedby

manyobjects.Soinsteadofkeepingthesepropertiesinthoseobjectswekeepthemexternally,making

objectsflyweight.Seemoredetailsinthecommentsofmainfunction.
*/
classFlyweightCharacterAbstractBuilder{

FlyweightCharacterAbstractBuilder(){}

~FlyweightCharacterAbstractBuilder(){}
public:

staticstd::vector<float>fontSizes;//letsimaginethatsizesbemayoffloatingpointtype

staticstd::vector<std::string>fontNames;//fontnamemaybeofvariablelength(letstake6bytesisaverage)

};

staticvoidsetFontsAndNames();
staticFlyweightCharactercreateFlyweightCharacter(unsignedshortfontSizeIndex,

unsignedshortfontNameIndex,

unsignedshortpositionInStream);

std::vector<float>FlyweightCharacterAbstractBuilder::fontSizes(3);
std::vector<std::string>FlyweightCharacterAbstractBuilder::fontNames(3);
voidFlyweightCharacterAbstractBuilder::setFontsAndNames(){

fontSizes[0]=1.0;

fontSizes[1]=1.5;

fontSizes[2]=2.0;

fontNames[0]="first_font";
fontNames[1]="second_font";
fontNames[2]="third_font";

classFlyweightCharacter{

unsignedshortfontSizeIndex;//indexinsteadofactualfontsize

unsignedshortfontNameIndex;//indexinsteadoffontname

unsignedpositionInStream;

public:

};

FlyweightCharacter(unsignedshortfontSizeIndex,unsignedshortfontNameIndex,unsignedshortpositionInStream)

fontSizeIndex(fontSizeIndex),fontNameIndex(fontNameIndex),positionInStream(positionInStream){}
voidprint(){

std::cout<<"FontSize:"<<FlyweightCharacterAbstractBuilder::fontSizes[fontSizeIndex]

<<",fontName:"<<FlyweightCharacterAbstractBuilder::fontNames[fontNameIndex]

<<",characterstreamposition:"<<positionInStream<<std::endl;
}
~FlyweightCharacter(){}

FlyweightCharacterFlyweightCharacterAbstractBuilder::createFlyweightCharacter(unsignedshortfontSizeIndex,unsignedshort
https://en.wikibooks.org/w/index.php?title=C%2B%2B_Programming/Code/Design_Patterns&printable=yes

25/53

10/14/2015

C++Programming/Code/DesignPatternsWikibooks,openbooksforanopenworld

FlyweightCharacterfc(fontSizeIndex,fontNameIndex,positionInStream);

returnfc;

intmain(intargc,char**argv){

std::vector<FlyweightCharacter>chars;

FlyweightCharacterAbstractBuilder::setFontsAndNames();
unsignedshortlimit=NUMBER_OF_SAME_TYPE_CHARS;

for(unsignedshorti=0;i<limit;i++){

chars.push_back(FlyweightCharacterAbstractBuilder::createFlyweightCharacter(0,0,i));

chars.push_back(FlyweightCharacterAbstractBuilder::createFlyweightCharacter(1,1,i+1*limit));

chars.push_back(FlyweightCharacterAbstractBuilder::createFlyweightCharacter(2,2,i+2*limit));
}
/*

Eachcharstoreslinkstoit'sfontNameandfontSizesowhatwegetis:

eachobjectinsteadofallocating6bytes(conventionabove)forstring
and4bytesforfloatallocates2bytesforfontNameIndexandfontSizeIndex.

Thatmeansforeachcharwesave6+422=6bytes.
NowimaginewehaveNUMBER_OF_SAME_TYPE_CHARS=1000i.e.withourcode
wewillhave3groupsofcharswhith1000charsineachgroupwhichwillsaveus

3*1000*6(3*6+3*4)=17970savedbytes.

3*6+3*4isanumberofbytesallocatedbyFlyweightCharacterAbstractBuilder.

Sotheideaofthepatternistomovepropertiessharedbymanyobjectstosome

externalcontainer.Theobjectsinthatcasedon'tstorethedatathemselvesthey

storeonlylinkstothedatawhichsavesmemoryandmaketheobjectslighter.

ThedatasizeofpropertiesstoredexternallymaybesignificantwhichwillsaveREALLY

hugeammountofmemoryandwillmakeeachobjectsuperlightincomparissontoit'scounterpart.

That'swherethenameofthepatterncomesfrom:flyweight(i.e.verylight).
*/
for(unsignedshorti=0;i<chars.size();i++){

chars[i].print();
}

std::cin.get();return0;

Proxy
TheProxyPatternwillprovideanobjectasurrogateorplaceholderforanotherobjecttocontrolaccesstoit.
Itisusedwhenyouneedtorepresentacomplexobjectwithasimplerone.Ifcreationofanobjectis
expensive,itcanbepostponeduntiltheveryneedarisesandmeanwhileasimplerobjectcanserveasa
placeholder.ThisplaceholderobjectiscalledtheProxyforthecomplexobject.
CuriouslyRecurringTemplate
Thistechniqueisknownmorewidelyasamixin.Mixinsaredescribedintheliteraturetobeapowerfultool
forexpressingabstractions[citationneeded].
InterfacebasedProgramming(IBP)

https://en.wikibooks.org/w/index.php?title=C%2B%2B_Programming/Code/Design_Patterns&printable=yes

26/53

10/14/2015

C++Programming/Code/DesignPatternsWikibooks,openbooksforanopenworld

InterfacebasedprogrammingiscloselyrelatedwithModularProgrammingandObjectOriented
Programming,itdefinestheapplicationasacollectionofintercoupledmodules(interconnectedandwhich
plugintoeachotherviainterface).Modulescanbeunplugged,replaced,orupgraded,withouttheneedof
compromisingthecontentsofothermodules.
Thetotalsystemcomplexityisgreatlyreduced.InterfaceBasedProgrammingaddsmoretomodular
ProgramminginthatitinsiststhatInterfacesaretobeaddedtothesemodules.Theentiresystemisthus
viewedasComponentsandtheinterfacesthathelpsthemtocoact.
InterfacebasedProgrammingincreasesthemodularityoftheapplicationandhenceitsmaintainabilityata
laterdevelopmentcycles,especiallywheneachmodulemustbedevelopedbydifferentteams.Itisawell
knownmethodologythathasbeenaroundforalongtimeanditisacoretechnologybehindframeworks
suchasCORBA.
Thisisparticularlyconvenientwhenthirdpartiesdevelopadditionalcomponentsfortheestablishedsystem.
Theyjusthavetodevelopcomponentsthatsatisfytheinterfacespecifiedbytheparentapplicationvendor.
Thusthepublisheroftheinterfacesassuresthathewillnotchangetheinterfaceandthesubscriberagreesto
implementtheinterfaceaswholewithoutanydeviation.AninterfaceisthereforesaidtobeaContractual
agreementandtheprogrammingparadigmbasedonthisistermedas"interfacebasedprogramming".

BehavioralPatterns
ChainofResponsibility
ChainofResponsibilitypatternhastheintenttoavoidcouplingthesenderofarequesttoitsreceiverby
givingmorethanoneobjectachancetohandletherequest.Chainsthereceivingobjectsandpassesthe
requestsalongthechainuntilanobjecthandlesit.
Command
CommandpatternisanObjectbehavioralpatternthatdecouplessenderandreceiverbyencapsulatinga
requestasanobject,therebylettingyouparameterizeclientswithdifferentrequests,queueorlogrequests,
andsupportundoableoperations.Itcanalsobethoughtasanobjectorientedequivalentofcallback
method.
CallBack:Itisafunctionthatisregisteredtobecalledatlaterpointoftimebasedonuseractions.
#include<iostream>
usingnamespacestd;
/*theCommandinterface*/
classCommand
{
public:

virtualvoidexecute()=0;
};
/*Receiverclass*/
classLight{

https://en.wikibooks.org/w/index.php?title=C%2B%2B_Programming/Code/Design_Patterns&printable=yes

27/53

10/14/2015

C++Programming/Code/DesignPatternsWikibooks,openbooksforanopenworld

public:

Light(){}

voidturnOn()
{

cout<<"Thelightison"<<endl;
}

};

voidturnOff()
{

cout<<"Thelightisoff"<<endl;
}

/*theCommandforturningonthelight*/
classFlipUpCommand:publicCommand
{
public:

FlipUpCommand(Light&light):theLight(light)
{

virtualvoidexecute()
{

theLight.turnOn();
}

private:

Light&theLight;
};
/*theCommandforturningoffthelight*/
classFlipDownCommand:publicCommand
{
public:

FlipDownCommand(Light&light):theLight(light)

virtualvoidexecute()

theLight.turnOff();

}
private:

Light&theLight;
};
classSwitch{
public:

Switch(Command&flipUpCmd,Command&flipDownCmd)

:flipUpCommand(flipUpCmd),flipDownCommand(flipDownCmd)

voidflipUp()
{

flipUpCommand.execute();
}

voidflipDown()
{

flipDownCommand.execute();
}

private:

Command&flipUpCommand;

Command&flipDownCommand;
https://en.wikibooks.org/w/index.php?title=C%2B%2B_Programming/Code/Design_Patterns&printable=yes

28/53

10/14/2015

C++Programming/Code/DesignPatternsWikibooks,openbooksforanopenworld

};

/*Thetestclassorclient*/
intmain()
{

Lightlamp;

FlipUpCommandswitchUp(lamp);

FlipDownCommandswitchDown(lamp);

Switchs(switchUp,switchDown);
s.flipUp();
s.flipDown();

Interpreter
Givenalanguage,definearepresentationforitsgrammaralongwithaninterpreterthatusesthe
representationtointerpretsentencesinthelanguage.

#include<iostream>
#include<string>
#include<map>
#include<list>
namespacewikibooks_design_patterns
{
//

basedontheJavasamplearoundhere

typedefstd::stringString;
structExpression;
typedefstd::map<String,Expression*>Map;
typedefstd::list<Expression*>Stack;
structExpression{
virtualintinterpret(Mapvariables)=0;

virtual~Expression(){}
};

classNumber:publicExpression{
private:

intnumber;
public:

Number(intnumber){this>number=number;}

intinterpret(Mapvariables){returnnumber;}
};

classPlus:publicExpression{
Expression*leftOperand;
Expression*rightOperand;
public:
Plus(Expression*left,Expression*right){
leftOperand=left;
rightOperand=right;
}
~Plus(){

deleteleftOperand;

deleterightOperand;
}

intinterpret(Mapvariables){
https://en.wikibooks.org/w/index.php?title=C%2B%2B_Programming/Code/Design_Patterns&printable=yes

29/53

10/14/2015

C++Programming/Code/DesignPatternsWikibooks,openbooksforanopenworld

returnleftOperand>interpret(variables)+rightOperand>interpret(variables);
}
};

classMinus:publicExpression{
Expression*leftOperand;
Expression*rightOperand;
public:
Minus(Expression*left,Expression*right){
leftOperand=left;
rightOperand=right;
}
~Minus(){

deleteleftOperand;

deleterightOperand;
}

intinterpret(Mapvariables){
returnleftOperand>interpret(variables)rightOperand>interpret(variables);
}
};

classVariable:publicExpression{
Stringname;
public:

Variable(Stringname){this>name=name;}
intinterpret(Mapvariables){
if(variables.end()==variables.find(name))return0;
returnvariables[name]>interpret(variables);
}
};
//
Whiletheinterpreterpatterndoesnotaddressparsing,aparserisprovidedforcompleteness.

classEvaluator:publicExpression{
Expression*syntaxTree;

public:

Evaluator(Stringexpression){
StackexpressionStack;

size_tlast=0;
for(size_tnext=0;String::npos!=last;last=(String::npos==next)?next:(1+next)){
next=expression.find('',last);
Stringtoken(expression.substr(last,(String::npos==next)?(expression.length()last):(nextlast)));

if(token=="+"){

Expression*right=expressionStack.back();expressionStack.pop_back();
Expression*left=expressionStack.back();expressionStack.pop_back();
Expression*subExpression=newPlus(right,left);
expressionStack.push_back(subExpression);
}
elseif(token==""){
//it'snecessaryremovefirsttherightoperandfromthestack
Expression*right=expressionStack.back();expressionStack.pop_back();
//..andaftertheleftone
Expression*left=expressionStack.back();expressionStack.pop_back();
Expression*subExpression=newMinus(left,right);
expressionStack.push_back(subExpression);
}
else
expressionStack.push_back(newVariable(token));
}
syntaxTree=expressionStack.back();expressionStack.pop_back();
}
~Evaluator(){

deletesyntaxTree;
}
https://en.wikibooks.org/w/index.php?title=C%2B%2B_Programming/Code/Design_Patterns&printable=yes

30/53

10/14/2015

C++Programming/Code/DesignPatternsWikibooks,openbooksforanopenworld

intinterpret(Mapcontext){
returnsyntaxTree>interpret(context);
}
};
}
voidmain()
{

usingnamespacewikibooks_design_patterns;

Evaluatorsentence("wxz+");

static
constintsequences[][3]={

{5,10,42},{1,3,2},{7,9,5},
};
for(size_ti=0;sizeof(sequences)/sizeof(sequences[0])>i;++i){

Mapvariables;

variables["w"]=newNumber(sequences[i][0]);

variables["x"]=newNumber(sequences[i][1]);

variables["z"]=newNumber(sequences[i][2]);

intresult=sentence.interpret(variables);

for(Map::iteratorit=variables.begin();variables.end()!=it;++it)deleteit>second;

std::cout<<"Interpreterresult:"<<result<<std::endl;

Iterator
The'iterator'designpatternisusedliberallywithintheSTLfortraversalofvariouscontainers.Thefull
understandingofthiswillliberateadevelopertocreatehighlyreusableandeasily
understandable[citationneeded]datacontainers.
Thebasicideaoftheiteratoristhatitpermitsthetraversalofacontainer(likeapointermovingacrossan
array).However,togettothenextelementofacontainer,youneednotknowanythingabouthowthe
containerisconstructed.Thisistheiteratorsjob.Bysimplyusingthememberfunctionsprovidedbythe
iterator,youcanmove,intheintendedorderofthecontainer,fromthefirstelementtothelastelement.
Letusstartbyconsideringatraditionalsingledimensionalarraywithapointermovingfromthestarttothe
end.Thisexampleassumesknowledgeofpointerarithmetic.Notethattheuseof"it"or"itr,"henceforth,is
ashortversionof"iterator."
constintARRAY_LEN=42;
int*myArray=newint[ARRAY_LEN];
//Settheiteratortopointtothefirstmemorylocationofthearray
int*arrayItr=myArray;
//Movethrougheachelementofthearray,settingitequaltoitspositioninthearray
for(inti=0;i<ARRAY_LEN;++i)
{
//setthevalueofthecurrentlocationinthearray
*arrayItr=i;
//byincrementingthepointer,wemoveittothenextpositioninthearray.
//Thisiseasyforacontiguousmemorycontainer,sincepointerarithmetic
//handlesthetraversal.
++arrayItr;
}
//Donotbemessy,cleanupafteryourself
delete[]myArray;
https://en.wikibooks.org/w/index.php?title=C%2B%2B_Programming/Code/Design_Patterns&printable=yes

31/53

10/14/2015

C++Programming/Code/DesignPatternsWikibooks,openbooksforanopenworld

Thiscodeworksveryquicklyforarrays,buthowwouldwetraversealinkedlist,whenthememoryisnot
contiguous?Considertheimplementationofarudimentarylinkedlistasfollows:
classIteratorCannotMoveToNext{};//Errorclass
classMyIntLList
{
public:
//TheNodeclassrepresentsasingleelementinthelinkedlist.
//Thenodehasanextnodeandapreviousnode,sothattheuser
//maymovefromonepositiontothenext,orstepbackasingle
//position.NoticethatthetraversalofalinkedlistisO(N),
//asissearching,sincethelistisnotordered.
classNode
{
public:
Node():mNextNode(0),mPrevNode(0),mValue(0){}
Node*mNextNode;
Node*mPrevNode;
intmValue;
};
MyIntLList():mSize(0)
{}
~MyIntLList()
{
while(!Empty())
pop_front();
}//Seeexpansionforfurtherimplementation;
intSize()const{returnmSize;}
//Addthisvaluetotheendofthelist
voidpush_back(intvalue)
{
Node*newNode=newNode;
newNode>mValue=value;
newNode>mPrevNode=mTail;
mTail>mNextNode=newNode;
mTail=newNode;
++mSize;
}
//Removethevaluefromthebeginningofthelist
voidpop_front()
{
if(Empty())
return;
Node*tmpnode=mHead;
mHead=mHead>mNextNode;
deletetmpnode;
mSize;
}
boolEmpty()
{returnmSize==0;}

//Thisiswheretheiteratordefinitionwillgo,
//butletsfinishthedefinitionofthelist,first

private:
Node*mHead;
Node*mTail;
intmSize;
};

Thislinkedlisthasnoncontiguousmemory,andisthereforenotacandidateforpointerarithmetic.Andwe
donotwanttoexposetheinternalsofthelisttootherdevelopers,forcingthemtolearnthem,andkeeping
usfromchangingit.
https://en.wikibooks.org/w/index.php?title=C%2B%2B_Programming/Code/Design_Patterns&printable=yes

32/53

10/14/2015

C++Programming/Code/DesignPatternsWikibooks,openbooksforanopenworld

Thisiswheretheiteratorcomesin.Thecommoninterfacemakeslearningtheusageofthecontainereasier,
andhidesthetraversallogicfromotherdevelopers.
Letusexaminethecodefortheiterator,itself.
/*
*Theiteratorclassknowstheinternalsofthelinkedlist,sothatit
*maymovefromoneelementtothenext.Inthisimplementation,Ihave
*chosentheclassictraversalmethodofoverloadingtheincrement
*operators.Morethoroughimplementationsofabidirectionallinked
*listwouldincludedecrementoperatorssothattheiteratormaymove
*intheoppositedirection.
*/
classIterator
{
public:
Iterator(Node*position):mCurrNode(position){}
//Prefixincrement
constIterator&operator++()
{
if(mCurrNode==0||mCurrNode>mNextNode==0)
throwIteratorCannotMoveToNext();e
mCurrNode=mCurrNode>mNextNode;
return*this;
}
//Postfixincrement
Iteratoroperator++(int)
{
IteratortempItr=*this;
++(*this);
returntempItr;
}
//Dereferencingoperatorreturnsthecurrentnode,whichshouldthen
//bedereferencedfortheint.TODO:Checksyntaxforoverloading
//dereferencingoperator
Node*operator*()
{returnmCurrNode;}
//TODO:implementarrowoperatorandcleanupexampleusagefollowing
private:
Node*mCurrNode;
};
//Thefollowingtwofunctionsmakeitpossibletocreate
//iteratorsforaninstanceofthisclass.
//Firstpositionforiteratorsshouldbethefirstelementinthecontainer.
IteratorBegin(){returnIterator(mHead);}
//Finalpositionforiteratorsshouldbeonepastthelastelementinthecontainer.
IteratorEnd(){returnIterator(0);}

Withthisimplementation,itisnowpossible,withoutknowledgeofthesizeofthecontainerorhowitsdata
isorganized,tomovethrougheachelementinorder,manipulatingorsimplyaccessingthedata.Thisis
donethroughtheaccessorsintheMyIntLListclass,Begin()andEnd().
//Createalist
MyIntLListmyList;
//Addsomeitemstothelist
for(inti=0;i<10;++i)
myList.push_back(i);
//Movethroughthelist,adding42toeachitem.
for(MyIntLList::Iteratorit=myList.Begin();it!=myList.End();++it)
(*it)>mValue+=42;

Thefollowingprogramgivestheimplementationofaniteratordesignpatternwithagenerictemplate:
https://en.wikibooks.org/w/index.php?title=C%2B%2B_Programming/Code/Design_Patterns&printable=yes

33/53

10/14/2015

C++Programming/Code/DesignPatternsWikibooks,openbooksforanopenworld

/************************************************************************/
/*Iterator.h*/
/************************************************************************/
#ifndefMY_ITERATOR_HEADER
#defineMY_ITERATOR_HEADER
#include<iterator>
#include<vector>
#include<set>
//////////////////////////////////////////////////////////////////////////
template<classT,classU>
classIterator
{
public:

typedeftypenamestd::vector<T>::iteratoriter_type;

Iterator(U*pData):m_pData(pData){

m_it=m_pData>m_data.begin();

voidfirst()
{

m_it=m_pData>m_data.begin();
}

voidnext()
{

m_it++;
}

boolisDone()
{

return(m_it==m_pData>m_data.end());
}

iter_typecurrent()

returnm_it;

}
private:

U*m_pData;

iter_typem_it;
};
template<classT,classU,classA>
classsetIterator
{
public:

typedeftypenamestd::set<T,U>::iteratoriter_type;

setIterator(A*pData):m_pData(pData)

m_it=m_pData>m_data.begin();

voidfirst()
{

m_it=m_pData>m_data.begin();
}

voidnext()
{

m_it++;
}

boolisDone()
{

return(m_it==m_pData>m_data.end());
}

https://en.wikibooks.org/w/index.php?title=C%2B%2B_Programming/Code/Design_Patterns&printable=yes

34/53

10/14/2015

C++Programming/Code/DesignPatternsWikibooks,openbooksforanopenworld

iter_typecurrent()
{

returnm_it;
}

private:

iter_type
};
#endif

*m_pData;
m_it;

/************************************************************************/
/*Aggregate.h*/
/************************************************************************/
#ifndefMY_DATACOLLECTION_HEADER
#defineMY_DATACOLLECTION_HEADER
#include"Iterator.h"
template<classT>
classaggregate
{

friendclassIterator<T,aggregate>;
public:

voidadd(Ta)

m_data.push_back(a);

Iterator<T,aggregate>*create_iterator()
{

returnnewIterator<T,aggregate>(this);
}

private:

std::vector<T>m_data;
};
template<classT,classU>
classaggregateSet
{

friendclasssetIterator<T,U,aggregateSet>;
public:

voidadd(Ta)

m_data.insert(a);

setIterator<T,U,aggregateSet>*create_iterator()
{

returnnewsetIterator<T,U,aggregateSet>(this);
}

voidPrint()
{

copy(m_data.begin(),m_data.end(),std::ostream_iterator<T>(std::cout,"\n"));
}

private:

std::set<T,U>m_data;
};
#endif

/************************************************************************/
/*IteratorTest.cpp*/
/************************************************************************/
https://en.wikibooks.org/w/index.php?title=C%2B%2B_Programming/Code/Design_Patterns&printable=yes

35/53

10/14/2015

C++Programming/Code/DesignPatternsWikibooks,openbooksforanopenworld

#include<iostream>
#include<string>
#include"Aggregate.h"
usingnamespacestd;
classMoney
{
public:

Money(inta=0):m_data(a){}

voidSetMoney(inta)
{

m_data=a;
}

intGetMoney()

returnm_data;

private:

intm_data;
};
className
{
public:

Name(stringname):m_name(name){}

conststring&GetName()const
{

returnm_name;
}

friendostream&operator<<(ostream&out,Namename)
{

out<<name.GetName();

returnout;
}

private:

stringm_name;
};
structNameLess
{

booloperator()(constName&lhs,constName&rhs)const

return(lhs.GetName()<rhs.GetName());

}
};
intmain()
{

//sample1

cout<<"________________Iteratorwithint______________________________________"<<endl;

aggregate<int>agg;

for(inti=0;i<10;i++)

agg.add(i);

Iterator<int,aggregate<int>>*it=agg.create_iterator();
for(it>first();!it>isDone();it>next())

cout<<*it>current()<<endl;

//sample2
aggregate<Money>agg2;
Moneya(100),b(1000),c(10000);
agg2.add(a);
agg2.add(b);

https://en.wikibooks.org/w/index.php?title=C%2B%2B_Programming/Code/Design_Patterns&printable=yes

36/53

10/14/2015

C++Programming/Code/DesignPatternsWikibooks,openbooksforanopenworld

agg2.add(c);

cout<<"________________IteratorwithClassMoney______________________________"<<endl;
Iterator<Money,aggregate<Money>>*it2=agg2.create_iterator();
for(it2>first();!it2>isDone();it2>next())

cout<<it2>current()>GetMoney()<<endl;

//sample3
cout<<"________________SetIteratorwithClassName______________________________"<<endl;

setIterator<Name,NameLess,aggregateSet<Name,NameLess>>*it3=aset.create_iterator();
for(it3>first();!it3>isDone();it3>next())

cout<<(*it3>current())<<endl;

aggregateSet<Name,NameLess>aset;
aset.add(Name("Qmt"));
aset.add(Name("Bmt"));
aset.add(Name("Cmt"));
aset.add(Name("Amt"));

Consoleoutput:
________________Iteratorwithint______________________________________
0
1
2
3
4
5
6
7
8
9
________________IteratorwithClassMoney______________________________
100
1000
10000
________________SetIteratorwithClassName___________________________
Amt
Bmt
Cmt
Qmt

Mediator
Defineanobjectthatencapsulateshowasetofobjectsinteract.Mediatorpromotesloosecouplingby
keepingobjectsfromreferringtoeachotherexplicitly,anditletsyouvarytheirinteractionindependently.
#include<iostream>
#include<string>
#include<list>
classMediatorInterface;
classColleagueInterface{

std::stringname;

public:

ColleagueInterface(conststd::string&newName):name(newName){}

std::stringgetName()const{returnname;}

virtualvoidsendMessage(constMediatorInterface&,conststd::string&)const=0;

virtualvoidreceiveMessage(constColleagueInterface*,conststd::string&)const=0;
};
https://en.wikibooks.org/w/index.php?title=C%2B%2B_Programming/Code/Design_Patterns&printable=yes

37/53

10/14/2015

C++Programming/Code/DesignPatternsWikibooks,openbooksforanopenworld

classColleague:publicColleagueInterface{

public:

usingColleagueInterface::ColleagueInterface;

virtualvoidsendMessage(constMediatorInterface&,conststd::string&)constoverride;

private:

virtualvoidreceiveMessage(constColleagueInterface*,conststd::string&)constoverride;
};
classMediatorInterface{
private:

std::list<ColleagueInterface*>colleagueList;
public:

conststd::list<ColleagueInterface*>&getColleagueList()const{returncolleagueList;}

virtualvoiddistributeMessage(constColleagueInterface*,conststd::string&)const=0;

virtualvoidregisterColleague(ColleagueInterface*colleague){colleagueList.emplace_back(colleague);}
};
classMediator:publicMediatorInterface{
virtualvoiddistributeMessage(constColleagueInterface*,conststd::string&)constoverride;
};
voidColleague::sendMessage(constMediatorInterface&mediator,conststd::string&message)const{

mediator.distributeMessage(this,message);
}
voidColleague::receiveMessage(constColleagueInterface*sender,conststd::string&message)const{

std::cout<<getName()<<"receivedthemessagefrom"<<sender>getName()<<":"<<message<<std::endl;
}

voidMediator::distributeMessage(constColleagueInterface*sender,conststd::string&message)const{

for(constColleagueInterface*x:getColleagueList())

if(x!=sender)//Donotsendthemessagebacktothesender

x>receiveMessage(sender,message);
}

intmain(){

Colleague*bob=newColleague("Bob"),*sam=newColleague("Sam"),*frank=newColleague("Frank"),*tom

Colleague*staff[]={bob,sam,frank,tom};

MediatormediatorStaff,mediatorSamsBuddies;

for(Colleague*x:staff)

mediatorStaff.registerColleague(x);

bob>sendMessage(mediatorStaff,"I'mquittingthisjob!");

mediatorSamsBuddies.registerColleague(frank);mediatorSamsBuddies.registerColleague(tom);//Sam'sbuddiesonly

sam>sendMessage(mediatorSamsBuddies,"Hooray!He'sgone!Let'sgoforadrink,guys!");

return0;
}

Memento
WithoutviolatingencapsulationtheMementoPatternwillcaptureandexternalizeanobjectsinternalstate
sothattheobjectcanberestoredtothisstatelater.ThoughtheGangofFourusesfriendasawayto
implementthispatternitisnotthebestdesign[citationneeded].ItcanalsobeimplementedusingPIMPL
(pointertoimplementationoropaquepointer).BestUsecaseis'UndoRedo'inaneditor.
TheOriginator(theobjecttobesaved)createsasnapshotofitselfasaMementoobject,andpassesthat
referencetotheCaretakerobject.TheCaretakerobjectkeepstheMementountilsuchatimeasthe
OriginatormaywanttoreverttoapreviousstateasrecordedintheMementoobject.
Seememoize(http://perldoc.perl.org/Memoize.html)foranoldschoolexampleofthispattern.
https://en.wikibooks.org/w/index.php?title=C%2B%2B_Programming/Code/Design_Patterns&printable=yes

38/53

10/14/2015

C++Programming/Code/DesignPatternsWikibooks,openbooksforanopenworld

#include<iostream>
#include<string>
#include<sstream>
#include<vector>
conststd::stringNAME="Object";
template<typenameT>
std::stringtoString(constT&t){

std::stringstreamss;

ss<<t;

returnss.str();
}
classMemento;
classObject{

private:

intvalue;

std::stringname;

doubledecimal;//andsupposethereareloadsofotherdatamembers

public:

Object(intnewValue):value(newValue),name(NAME+toString(value)),decimal((float)value/100){}

voiddoubleValue(){value=2*value;name=NAME+toString(value);decimal=(float)value/100;}

voidincreaseByOne(){value++;name=NAME+toString(value);decimal=(float)value/100;}

intgetValue()const{returnvalue;}

std::stringgetName()const{returnname;}

doublegetDecimal()const{returndecimal;}

Memento*createMemento()const;

voidreinstateMemento(Memento*mem);
};
classMemento{

private:

Objectobject;

public:

Memento(constObject&obj):object(obj){}

Objectsnapshot()const{returnobject;}//wantasnapshotofObjectitselfbecauseofitsmanydatamembers
};
Memento*Object::createMemento()const{

returnnewMemento(*this);
}
voidObject::reinstateMemento(Memento*mem){

*this=mem>snapshot();
}
classCommand{

private:

typedefvoid(Object::*Action)();

Object*receiver;

Actionaction;

staticstd::vector<Command*>commandList;

staticstd::vector<Memento*>mementoList;

staticintnumCommands;

staticintmaxCommands;

public:

Command(Object*newReceiver,ActionnewAction):receiver(newReceiver),action(newAction){}

virtualvoidexecute(){

if(mementoList.size()<numCommands+1)

mementoList.resize(numCommands+1);

mementoList[numCommands]=receiver>createMemento();//savesthelastvalue

if(commandList.size()<numCommands+1)

commandList.resize(numCommands+1);

commandList[numCommands]=this;//savesthelastcommand

if(numCommands>maxCommands)

maxCommands=numCommands;

numCommands++;
https://en.wikibooks.org/w/index.php?title=C%2B%2B_Programming/Code/Design_Patterns&printable=yes

39/53

10/14/2015

};

C++Programming/Code/DesignPatternsWikibooks,openbooksforanopenworld

(receiver>*action)();
}
staticvoidundo(){
if(numCommands==0)
{
std::cout<<"Thereisnothingtoundoatthispoint."<<std::endl;
return;
}
commandList[numCommands1]>receiver>reinstateMemento(mementoList[numCommands1]);
numCommands;
}
voidstaticredo(){
if(numCommands>maxCommands)
{
std::cout<<"Thereisnothingtoredoatthispoint."<<std::endl;
return;
}
Command*commandRedo=commandList[numCommands];
(commandRedo>receiver>*(commandRedo>action))();
numCommands++;
}

std::vector<Command*>Command::commandList;
std::vector<Memento*>Command::mementoList;
intCommand::numCommands=0;
intCommand::maxCommands=0;
intmain()
{

inti;

std::cout<<"Pleaseenteraninteger:";

std::cin>>i;

Object*object=newObject(i);

Command*commands[3];

commands[1]=newCommand(object,&Object::doubleValue);

commands[2]=newCommand(object,&Object::increaseByOne);

std::cout<<"0.Exit,1.Double,2.Increasebyone,3.Undo,4.Redo:";

std::cin>>i;

while(i!=0)

if(i==3)

Command::undo();

elseif(i==4)

Command::redo();

elseif(i>0&&i<=2)

commands[i]>execute();

else

std::cout<<"Enteraproperchoice:";

std::cin>>i;

continue;

std::cout<<""<<object>getValue()<<""<<object>getName()<<""<<object>getDecimal()<<

std::cout<<"0.Exit,1.Double,2.Increasebyone,3.Undo,4.Redo:";

std::cin>>i;

}
}

Observer

https://en.wikibooks.org/w/index.php?title=C%2B%2B_Programming/Code/Design_Patterns&printable=yes

40/53

10/14/2015

C++Programming/Code/DesignPatternsWikibooks,openbooksforanopenworld

TheObserverPatterndefinesaonetomanydependencybetweenobjectssothatwhenoneobjectchanges
state,allitsdependentsarenotifiedandupdatedautomatically.
Problem
Inoneplaceormanyplacesintheapplicationweneedtobeawareaboutasystemeventoran
applicationstatechange.We'dliketohaveastandardwayofsubscribingtolisteningforsystem
eventsandastandardwayofnotifyingtheinterestedparties.Thenotificationshouldbeautomated
afteraninterestedpartysubscribedtothesystemeventorapplicationstatechange.Therealsoshould
beawaytounsubscribe.
Forces
Observersandobservablesprobablyshouldberepresentedbyobjects.Theobserverobjectswillbe
notifiedbytheobservableobjects.
Solution
Aftersubscribingthelisteningobjectswillbenotifiedbyawayofmethodcall.
#include<list>
#include<algorithm>
#include<iostream>
usingnamespacestd;
//TheAbstractObserver
classObserverBoardInterface
{
public:
virtualvoidupdate(floata,floatb,floatc)=0;
};
//AbstractInterfaceforDisplays
classDisplayBoardInterface
{
public:
virtualvoidshow()=0;
};
//TheAbstractSubject
classWeatherDataInterface
{
public:
virtualvoidregisterOb(ObserverBoardInterface*ob)=0;
virtualvoidremoveOb(ObserverBoardInterface*ob)=0;
virtualvoidnotifyOb()=0;
};
//TheConcreteSubject
classParaWeatherData:publicWeatherDataInterface
{
public:
voidSensorDataChange(floata,floatb,floatc)
{
m_humidity=a;
m_temperature=b;
m_pressure=c;
notifyOb();
}
voidregisterOb(ObserverBoardInterface*ob)
{
m_obs.push_back(ob);
}
voidremoveOb(ObserverBoardInterface*ob)
https://en.wikibooks.org/w/index.php?title=C%2B%2B_Programming/Code/Design_Patterns&printable=yes

41/53

10/14/2015

C++Programming/Code/DesignPatternsWikibooks,openbooksforanopenworld

{
m_obs.remove(ob);
}
protected:
voidnotifyOb()
{
list<ObserverBoardInterface*>::iteratorpos=m_obs.begin();
while(pos!=m_obs.end())
{
((ObserverBoardInterface*)(*pos))>update(m_humidity,m_temperature,m_pressure);
(dynamic_cast<DisplayBoardInterface*>(*pos))>show();
++pos;
}
}
private:
floatm_humidity;
floatm_temperature;
floatm_pressure;
list<ObserverBoardInterface*>m_obs;
};
//AConcreteObserver
classCurrentConditionBoard:publicObserverBoardInterface,publicDisplayBoardInterface
{
public:
CurrentConditionBoard(ParaWeatherData&a):m_data(a)
{
m_data.registerOb(this);
}
voidshow()
{
cout<<"_____CurrentConditionBoard_____"<<endl;
cout<<"humidity:"<<m_h<<endl;
cout<<"temperature:"<<m_t<<endl;
cout<<"pressure:"<<m_p<<endl;
cout<<"_______________________________"<<endl;
}
voidupdate(floath,floatt,floatp)
{
m_h=h;
m_t=t;
m_p=p;
}
private:
floatm_h;
floatm_t;
floatm_p;
ParaWeatherData&m_data;
};
//AConcreteObserver
classStatisticBoard:publicObserverBoardInterface,publicDisplayBoardInterface
{
public:
StatisticBoard(ParaWeatherData&a):m_maxt(1000),m_mint(1000),m_avet(0),m_count(0),m_data(a)
{
m_data.registerOb(this);
}
voidshow()
{
cout<<"________StatisticBoard_________"<<endl;
cout<<"lowesttemperature:"<<m_mint<<endl;
cout<<"highesttemperature:"<<m_maxt<<endl;
cout<<"averagetemperature:"<<m_avet<<endl;
cout<<"_______________________________"<<endl;
}
https://en.wikibooks.org/w/index.php?title=C%2B%2B_Programming/Code/Design_Patterns&printable=yes

42/53

10/14/2015

C++Programming/Code/DesignPatternsWikibooks,openbooksforanopenworld

voidupdate(floath,floatt,floatp)
{
++m_count;
if(t>m_maxt)
{
m_maxt=t;
}
if(t<m_mint)
{
m_mint=t;
}
m_avet=(m_avet*(m_count1)+t)/m_count;
}
private:
floatm_maxt;
floatm_mint;
floatm_avet;
intm_count;
ParaWeatherData&m_data;
};
intmain(intargc,char*argv[])
{

ParaWeatherData*wdata=newParaWeatherData;
CurrentConditionBoard*currentB=newCurrentConditionBoard(*wdata);
StatisticBoard*statisticB=newStatisticBoard(*wdata);
wdata>SensorDataChange(10.2,28.2,1001);
wdata>SensorDataChange(12,30.12,1003);
wdata>SensorDataChange(10.2,26,806);
wdata>SensorDataChange(10.3,35.9,900);
wdata>removeOb(currentB);
wdata>SensorDataChange(100,40,1900);

deletestatisticB;
deletecurrentB;
deletewdata;
return0;
}

State
TheStatePatternallowsanobjecttoalteritsbehaviorwhenitsinternalstatechanges.Theobjectwill
appearashavingchangeditsclass.
#include<iostream>
#include<string>
#include<cstdlib>
#include<ctime>
#include<memory>
enumInput{DUCK_DOWN,STAND_UP,JUMP,DIVE};
classFighter;
classStandingState;classJumpingState;classDivingState;
classFighterState{

public:
https://en.wikibooks.org/w/index.php?title=C%2B%2B_Programming/Code/Design_Patterns&printable=yes

43/53

10/14/2015

};

C++Programming/Code/DesignPatternsWikibooks,openbooksforanopenworld

staticstd::shared_ptr<StandingState>standing;
staticstd::shared_ptr<DivingState>diving;
virtual~FighterState()=default;
virtualvoidhandleInput(Fighter&,Input)=0;
virtualvoidupdate(Fighter&)=0;

classDuckingState:publicFighterState{

private:

intchargingTime;

staticconstintFullRestTime=5;

public:

DuckingState():chargingTime(0){}

virtualvoidhandleInput(Fighter&,Input)override;

virtualvoidupdate(Fighter&)override;
};
classStandingState:publicFighterState{

public:

virtualvoidhandleInput(Fighter&,Input)override;

virtualvoidupdate(Fighter&)override;
};
classJumpingState:publicFighterState{

private:

intjumpingHeight;

public:

JumpingState(){jumpingHeight=std::rand()%5+1;}

virtualvoidhandleInput(Fighter&,Input)override;

virtualvoidupdate(Fighter&)override;
};
classDivingState:publicFighterState{

public:

virtualvoidhandleInput(Fighter&,Input)override;

virtualvoidupdate(Fighter&)override;
};
std::shared_ptr<StandingState>FighterState::standing(newStandingState);
std::shared_ptr<DivingState>FighterState::diving(newDivingState);

classFighter{

private:

std::stringname;

std::shared_ptr<FighterState>state;

intfatigueLevel=std::rand()%10;

public:

Fighter(conststd::string&newName):name(newName),state(FighterState::standing){}

std::stringgetName()const{returnname;}

intgetFatigueLevel()const{returnfatigueLevel;}

virtualvoidhandleInput(Inputinput){state>handleInput(*this,input);}//delegateinputhandlingto's

voidchangeState(std::shared_ptr<FighterState>newState){state=newState;updateWithNewState();}

voidstandsUp(){std::cout<<getName()<<"standsup."<<std::endl;}

voidducksDown(){std::cout<<getName()<<"ducksdown."<<std::endl;}

voidjumps(){std::cout<<getName()<<"jumpsintotheair."<<std::endl;}

voiddives(){std::cout<<getName()<<"makesadiveattackinthemiddleofthejump!"<<std::endl;}

voidfeelsStrong(){std::cout<<getName()<<"feelsstrong!"<<std::endl;}

voidchangeFatigueLevelBy(intchange){fatigueLevel+=change;std::cout<<"fatigueLevel="<<fatigueLev

private:

virtualvoidupdateWithNewState(){state>update(*this);}//delegateupdatingto'state'
};

voidStandingState::handleInput(Fighter&fighter,Inputinput){

switch(input){

caseSTAND_UP:std::cout<<fighter.getName()<<"remainsstanding."<<std::endl;return;

caseDUCK_DOWN:fighter.changeState(std::shared_ptr<DuckingState>(newDuckingState));returnfighter

caseJUMP:fighter.jumps();returnfighter.changeState(std::shared_ptr<JumpingState>(newJumpingState

default:std::cout<<"Onecannotdothatwhilestanding."<<fighter.getName()<<"remainsstandingbyd

}
}
https://en.wikibooks.org/w/index.php?title=C%2B%2B_Programming/Code/Design_Patterns&printable=yes

44/53

10/14/2015

C++Programming/Code/DesignPatternsWikibooks,openbooksforanopenworld

voidStandingState::update(Fighter&fighter){

if(fighter.getFatigueLevel()>0)

fighter.changeFatigueLevelBy(1);
}

voidDuckingState::handleInput(Fighter&fighter,Inputinput){

switch(input){

caseSTAND_UP:fighter.changeState(FighterState::standing);returnfighter.standsUp();

caseDUCK_DOWN:

std::cout<<fighter.getName()<<"remainsinduckingposition,";

if(chargingTime<FullRestTime)std::cout<<"recoveringinthemeantime."<<std::endl;

elsestd::cout<<"fullyrecovered."<<std::endl;

returnupdate(fighter);

default:

std::cout<<"Onecannotdothatwhileducking."<<fighter.getName()<<"remainsinduckingposit

update(fighter);

}
}
voidDuckingState::update(Fighter&fighter){

chargingTime++;

std::cout<<"Chargingtime="<<chargingTime<<"."<<std::endl;

if(fighter.getFatigueLevel()>0)

fighter.changeFatigueLevelBy(1);

if(chargingTime>=FullRestTime&&fighter.getFatigueLevel()<=3)

fighter.feelsStrong();
}

voidJumpingState::handleInput(Fighter&fighter,Inputinput){

switch(input){

caseDIVE:fighter.changeState(FighterState::diving);returnfighter.dives();

default:

std::cout<<"Onecannotdothatinthemiddleofajump."<<fighter.getName()<<"landsfromhis

fighter.changeState(FighterState::standing);

}
}
voidJumpingState::update(Fighter&fighter){

std::cout<<fighter.getName()<<"hasjumped"<<jumpingHeight<<"feetintotheair."<<std::endl;

if(jumpingHeight>=3)

fighter.changeFatigueLevelBy(1);
}

voidDivingState::handleInput(Fighter&fighter,Input){

std::cout<<"Regardlessofwhattheuserinputis,"<<fighter.getName()<<"landsfromhisdiveandisnowstandi

fighter.changeState(FighterState::standing);
}
voidDivingState::update(Fighter&fighter){

fighter.changeFatigueLevelBy(2);
}
intmain(){

std::srand(std::time(nullptr));

Fighterrex("RextheFighter"),borg("BorgtheFighter");

std::cout<<rex.getName()<<"and"<<borg.getName()<<"arecurrentlystanding."<<std::endl;

intchoice;

autochooseAction=[&choice](Fighter&fighter){

std::cout<<std::endl<<DUCK_DOWN+1<<")Duckdown"<<STAND_UP+1<<")Standup"<<JUMP+

<<")Jump"<<DIVE+1<<")Diveinthemiddleofajump"<<std::endl;

std::cout<<"Choicefor"<<fighter.getName()<<"?";

std::cin>>choice;

constInputinput1=static_cast<Input>(choice1);

fighter.handleInput(input1);

};

while(true){

chooseAction(rex);

chooseAction(borg);

}
https://en.wikibooks.org/w/index.php?title=C%2B%2B_Programming/Code/Design_Patterns&printable=yes

45/53

10/14/2015

C++Programming/Code/DesignPatternsWikibooks,openbooksforanopenworld

Strategy
Definesafamilyofalgorithms,encapsulateseachone,andmaketheminterchangeable.Strategyletsthe
algorithmvaryindependentlyfromclientswhouseit.
#include<iostream>
usingnamespacestd;
classStrategyInterface
{
public:
virtualvoidexecute()const=0;
};
classConcreteStrategyA:publicStrategyInterface
{
public:
virtualvoidexecute()const
{
cout<<"CalledConcreteStrategyAexecutemethod"<<endl;
}
};
classConcreteStrategyB:publicStrategyInterface
{
public:
virtualvoidexecute()const
{
cout<<"CalledConcreteStrategyBexecutemethod"<<endl;
}
};
classConcreteStrategyC:publicStrategyInterface
{
public:
virtualvoidexecute()const
{
cout<<"CalledConcreteStrategyCexecutemethod"<<endl;
}
};
classContext
{
private:
StrategyInterface*strategy_;
public:
explicitContext(StrategyInterface*strategy):strategy_(strategy)
{
}
voidset_strategy(StrategyInterface*strategy)
{
strategy_=strategy;
}
voidexecute()const
{
strategy_>execute();
}
};
https://en.wikibooks.org/w/index.php?title=C%2B%2B_Programming/Code/Design_Patterns&printable=yes

46/53

10/14/2015

C++Programming/Code/DesignPatternsWikibooks,openbooksforanopenworld

intmain(intargc,char*argv[])
{
ConcreteStrategyAconcreteStrategyA;
ConcreteStrategyBconcreteStrategyB;
ConcreteStrategyCconcreteStrategyC;
ContextcontextA(&concreteStrategyA);
ContextcontextB(&concreteStrategyB);
ContextcontextC(&concreteStrategyC);
contextA.execute();//output:"CalledConcreteStrategyAexecutemethod"
contextB.execute();//output:"CalledConcreteStrategyBexecutemethod"
contextC.execute();//output:"CalledConcreteStrategyCexecutemethod"

contextA.set_strategy(&concreteStrategyB);
contextA.execute();//output:"CalledConcreteStrategyBexecutemethod"
contextA.set_strategy(&concreteStrategyC);
contextA.execute();//output:"CalledConcreteStrategyCexecutemethod"
return0;
}

TemplateMethod
Bydefiningaskeletonofanalgorithminanoperation,deferringsomestepstosubclasses,theTemplate
Methodletssubclassesredefinecertainstepsofthatalgorithmwithoutchangingthealgorithm'sstructure.
#include<ctime>
#include<assert.h>
#include<iostream>
namespacewikibooks_design_patterns
{
/**
*Anabstractclassthatiscommontoseveralgamesin
*whichplayersplayagainsttheothers,butonlyoneis
*playingatagiventime.
*/
classGame{
public:
Game():playersCount(0),movesCount(0),playerWon(1)
{

srand((unsigned)time(NULL));
}

/*Atemplatemethod:*/
voidplayOneGame(constintplayersCount=0){

if(playersCount)
this>playersCount=playersCount;

InitializeGame();

assert(this>playersCount);
intj=0;
while(!endOfGame()){
makePlay(j);
j=(j+1)%this>playersCount;

if(!j){

++movesCount;

}
}
printWinner();
https://en.wikibooks.org/w/index.php?title=C%2B%2B_Programming/Code/Design_Patterns&printable=yes

47/53

10/14/2015

C++Programming/Code/DesignPatternsWikibooks,openbooksforanopenworld

}
protected:
virtualvoidinitializeGame()=0;
virtualvoidmakePlay(intplayer)=0;
virtualboolendOfGame()=0;
virtualvoidprintWinner()=0;
private:
voidInitializeGame()
{

movesCount=0;

playerWon=1;

initializeGame();

protected:
intplayersCount;
intmovesCount;
intplayerWon;
};

//Nowwecanextendthisclassinorder
//toimplementactualgames:

classMonopoly:publicGame{

/*Implementationofnecessaryconcretemethods*/
voidinitializeGame(){
//Initializeplayers

playersCount=rand()*7/RAND_MAX+2;
//Initializemoney
}
voidmakePlay(intplayer){
//Processoneturnofplayer

//
Decidewinner

if(movesCount<20)

return;

constintchances=(movesCount>199)?199:movesCount;

constintrandom=MOVES_WIN_CORRECTION*rand()*200/RAND_MAX;

if(random<chances)

playerWon=player;
}
boolendOfGame(){
//Returntrueifgameisover
//accordingtoMonopolyrules

return(1!=playerWon);
}
voidprintWinner(){

assert(playerWon>=0);

assert(playerWon<playersCount);
//Displaywhowon

std::cout<<"Monopoly,player"<<playerWon<<"wonin"<<movesCount<<"moves."<<std::endl;
}
private:
enum
{
MOVES_WIN_CORRECTION=20,
};
};

classChess:publicGame{

/*Implementationofnecessaryconcretemethods*/
voidinitializeGame(){
//Initializeplayers
https://en.wikibooks.org/w/index.php?title=C%2B%2B_Programming/Code/Design_Patterns&printable=yes

48/53

10/14/2015

C++Programming/Code/DesignPatternsWikibooks,openbooksforanopenworld

playersCount=2;
//Putthepiecesontheboard
}
voidmakePlay(intplayer){

assert(player<playersCount);
//Processaturnfortheplayer

//
decidewinner

if(movesCount<2)

return;

constintchances=(movesCount>99)?99:movesCount;

constintrandom=MOVES_WIN_CORRECTION*rand()*100/RAND_MAX;

//std::cout<<random<<":"<<chances<<std::endl;

if(random<chances)

playerWon=player;
}
boolendOfGame(){
//ReturntrueifinCheckmateor
//Stalematehasbeenreached

return(1!=playerWon);
}
voidprintWinner(){

assert(playerWon>=0);

assert(playerWon<playersCount);
//Displaythewinningplayer

std::cout<<"Player"<<playerWon<<"wonin"<<movesCount<<"moves."<<std::endl;
}
private:
enum
{

MOVES_WIN_CORRECTION=7,
};
};
}
intmain()
{
usingnamespacewikibooks_design_patterns;
Game*game=NULL;
Chesschess;
game=&chess;
for(unsignedi=0;i<100;++i)

game>playOneGame();
Monopolymonopoly;
game=&monopoly;
for(unsignedi=0;i<100;++i)

game>playOneGame();
return0;
}

Visitor
TheVisitorPatternwillrepresentanoperationtobeperformedontheelementsofanobjectstructureby
lettingyoudefineanewoperationwithoutchangingtheclassesoftheelementsonwhichitoperates.
#include<string>
#include<iostream>
https://en.wikibooks.org/w/index.php?title=C%2B%2B_Programming/Code/Design_Patterns&printable=yes

49/53

10/14/2015

C++Programming/Code/DesignPatternsWikibooks,openbooksforanopenworld

#include<vector>
usingnamespacestd;

classWheel;
classEngine;
classBody;
classCar;

//interfacetoallcar'parts'
structCarElementVisitor
{
virtualvoidvisit(Wheel&wheel)const=0;
virtualvoidvisit(Engine&engine)const=0;
virtualvoidvisit(Body&body)const=0;

virtualvoidvisitCar(Car&car)const=0;
virtual~CarElementVisitor(){};
};

//interfacetoonepart
structCarElement
{
virtualvoidaccept(constCarElementVisitor&visitor)=0;
virtual~CarElement(){}
};

//wheelelement,therearefourwheelswithuniquenames
classWheel:publicCarElement
{
public:
explicitWheel(conststring&name):
name_(name)
{
}
conststring&getName()const
{
returnname_;
}
voidaccept(constCarElementVisitor&visitor)
{
visitor.visit(*this);
}
private:
stringname_;
};

//engine
classEngine:publicCarElement
{
public:
voidaccept(constCarElementVisitor&visitor)
{
visitor.visit(*this);
}
};

//body
classBody:publicCarElement
{
public:
voidaccept(constCarElementVisitor&visitor)
{
visitor.visit(*this);
}
};

//car,allcarelements(parts)together
classCar
{
https://en.wikibooks.org/w/index.php?title=C%2B%2B_Programming/Code/Design_Patterns&printable=yes

50/53

10/14/2015

C++Programming/Code/DesignPatternsWikibooks,openbooksforanopenworld

public:
vector<CarElement*>&getElements()
{
returnelements_;
}
Car()
{
//assumethatneitherpush_backnorWheel(conststring&)maythrow
elements_.push_back(newWheel("frontleft"));
elements_.push_back(newWheel("frontright"));
elements_.push_back(newWheel("backleft"));
elements_.push_back(newWheel("backright"));
elements_.push_back(newBody());
elements_.push_back(newEngine());
}
~Car()
{
for(vector<CarElement*>::iteratorit=elements_.begin();
it!=elements_.end();++it)
{
delete*it;
}
}
private:
vector<CarElement*>elements_;
};

//PrintVisitorandDoVisitorshowbyusingadifferentimplementationtheCarclassisunchanged
//eventhoughthealgorithmisdifferentinPrintVisitorandDoVisitor.
classCarElementPrintVisitor:publicCarElementVisitor
{
public:
voidvisit(Wheel&wheel)const
{
cout<<"Visiting"<<wheel.getName()<<"wheel"<<endl;
}
voidvisit(Engine&engine)const
{
cout<<"Visitingengine"<<endl;
}
voidvisit(Body&body)const
{
cout<<"Visitingbody"<<endl;
}
voidvisitCar(Car&car)const
{
cout<<endl<<"Visitingcar"<<endl;
vector<CarElement*>&elems=car.getElements();
for(vector<CarElement*>::iteratorit=elems.begin();
it!=elems.end();++it)
{
(*it)>accept(*this);
//thisissuesthecallbacki.e.tothisfromtheelement
}
cout<<"Visitedcar"<<endl;
}
};

classCarElementDoVisitor:publicCarElementVisitor
{
public:
//thesearespecificimplementationsaddedtotheoriginalobjectwithoutmodifyingtheoriginalstruct
voidvisit(Wheel&wheel)const
{
cout<<"Kickingmy"<<wheel.getName()<<"wheel"<<endl;
}
voidvisit(Engine&engine)const
{
cout<<"Startingmyengine"<<endl;
}
voidvisit(Body&body)const
https://en.wikibooks.org/w/index.php?title=C%2B%2B_Programming/Code/Design_Patterns&printable=yes

51/53

10/14/2015

C++Programming/Code/DesignPatternsWikibooks,openbooksforanopenworld

{
cout<<"Movingmybody"<<endl;
}
voidvisitCar(Car&car)const
{
cout<<endl<<"Startingmycar"<<endl;
vector<CarElement*>&elems=car.getElements();
for(vector<CarElement*>::iteratorit=elems.begin();
it!=elems.end();++it)
{
(*it)>accept(*this);
//thisissuesthecallbacki.e.tothisfromtheelement
}
cout<<"Stoppedcar"<<endl;
}
};

intmain()
{
Carcar;
CarElementPrintVisitorprintVisitor;
CarElementDoVisitordoVisitor;

printVisitor.visitCar(car);
doVisitor.visitCar(car);
return0;
}

ModelViewController(MVC)
Apatternoftenusedbyapplicationsthatneedtheabilitytomaintainmultipleviewsofthesamedata.The
modelviewcontrollerpatternwasuntilrecently[citationneeded]averycommonpatternespeciallyfor
graphicuserinterlaceprogramming,itsplitsthecodein3pieces.Themodel,theview,andthecontroller.
TheModelistheactualdatarepresentation(forexample,ArrayvsLinkedList)orotherobjects
representingadatabase.TheViewisaninterfacetoreadingthemodelorafatclientGUI.TheController
providestheinterfaceofchangingormodifyingthedata,andthenselectingthe"NextBestView"(NBV).
Newcomerswillprobablyseethis"MVC"modelaswasteful,mainlybecauseyouareworkingwithmany
extraobjectsatruntime,whenitseemslikeonegiantobjectwilldo.ButthesecrettotheMVCpatternis
notwritingthecode,butinmaintainingit,andallowingpeopletomodifythecodewithoutchangingmuch
else.Also,keepinmind,thatdifferentdevelopershavedifferentstrengthsandweaknesses,soteam
buildingaroundMVCiseasier.ImagineaViewTeamthatisresponsibleforgreatviews,aModelTeam
thatknowsalotaboutdata,andaControllerTeamthatseethebigpictureofapplicationflow,handing
requests,workingwiththemodel,andselectingthemostappropriatenextviewforthatclient.
Forexample:Anaivecentraldatabasecanbeorganizedusingonlya"model",forexample,astraightarray.
However,lateron,itmaybemoreapplicabletousealinkedlist.Allarrayaccesseswillhavetoberemade
intotheirrespectiveLinkedListform(forexample,youwouldchangemyarray[5]intomylist.at(5)or
whateverisequivalentinthelanguageyouuse).
Well,ifwefollowedtheMVCpattern,thecentraldatabasewouldbeaccessedusingsomesortofa
function,forexample,myarray.at(5).Ifwechangethemodelfromanarraytoalinkedlist,allwehaveto
doischangetheviewwiththemodel,andthewholeprogramischanged.Keeptheinterfacethesamebut
changetheunderpinningsofit.Thiswouldallowustomakeoptimizationsmorefreelyandquicklythan
before.
https://en.wikibooks.org/w/index.php?title=C%2B%2B_Programming/Code/Design_Patterns&printable=yes

52/53

10/14/2015

C++Programming/Code/DesignPatternsWikibooks,openbooksforanopenworld

OneofthegreatadvantagesoftheModelViewControllerPatternisobviouslytheabilitytoreusethe
application'slogic(whichisimplementedinthemodel)whenimplementingadifferentview.Agood
exampleisfoundinwebdevelopment,whereacommontaskistoimplementanexternalAPIinsideofan
existingpieceofsoftware.IftheMVCpatternhascleanlybeenfollowed,thisonlyrequiresmodificationto
thecontroller,whichcanhavetheabilitytorenderdifferenttypesofviewsdependentonthecontenttype
requestedbytheuseragent.
Retrievedfrom"https://en.wikibooks.org/w/index.php?
title=C%2B%2B_Programming/Code/Design_Patterns&oldid=2989441"

Thispagewaslastmodifiedon2September2015,at19:38.
TextisavailableundertheCreativeCommonsAttributionShareAlikeLicense.additionaltermsmay
apply.Byusingthissite,youagreetotheTermsofUseandPrivacyPolicy.

https://en.wikibooks.org/w/index.php?title=C%2B%2B_Programming/Code/Design_Patterns&printable=yes

53/53

Potrebbero piacerti anche