Design patterns: An Introduction to Software Design Patterns

55
I’m sensing a pattern Tony Veale 2018

Transcript of Design patterns: An Introduction to Software Design Patterns

Page 1: Design patterns: An Introduction to Software Design Patterns

I’msensingapattern

TonyVeale2018

Page 2: Design patterns: An Introduction to Software Design Patterns

SsshhhhGreatartistssteal…

Help!

Whenwerefertotheideaof“genre”or“style”or

“paradigm”inArt,ScienceorCommercialDesign,wearereferringtotheideaof

DesignPatterns…

Thesecodifytheunspokennormsofgooddesign,andapplyinmanydisciplines.

Page 3: Design patterns: An Introduction to Software Design Patterns

ReneMagritte’sDesignPatterns

(1928)

Page 4: Design patterns: An Introduction to Software Design Patterns

HowshouldIorganizemyclasses?

Be Wise! Use the

Luke.

Be Wise! Use the

Luke.

Page 5: Design patterns: An Introduction to Software Design Patterns
Page 6: Design patterns: An Introduction to Software Design Patterns
Page 7: Design patterns: An Introduction to Software Design Patterns
Page 8: Design patterns: An Introduction to Software Design Patterns

…andthreatenitwithimminent

destructionbyaninventivemeans.

Page 9: Design patterns: An Introduction to Software Design Patterns
Page 10: Design patterns: An Introduction to Software Design Patterns
Page 11: Design patterns: An Introduction to Software Design Patterns

Wemeetagain,Mr.Bond…

Page 12: Design patterns: An Introduction to Software Design Patterns
Page 13: Design patterns: An Introduction to Software Design Patterns
Page 14: Design patterns: An Introduction to Software Design Patterns

CompartmentalizeresponsibilityMaximizecoherencewithin

compartmentsMinimizedependenciesbetween

compartmentsReduceredundancy&inefficiencyExplicitlyassignresponsibilitiesOrderlyflowofinformation

Scalability&Extensibility

Page 15: Design patterns: An Introduction to Software Design Patterns

Soalone

Page 16: Design patterns: An Introduction to Software Design Patterns

Differentparameterizedconfigurationsofthesameclassareinstantiatedtosuitdifferentcontextsanduses.

Page 17: Design patterns: An Introduction to Software Design Patterns

Flippin’

Nora,that’saBig‘Un…

Therecanbeonlyonesilverback.

Page 18: Design patterns: An Introduction to Software Design Patterns

publicinterfaceQuantifiableextendsIdentifiable{

publicintgetQuantity();

publicintaddQuantity(intdelta);

publicintremoveQuantity(intdelta);

}

Let’sstartbydefininganInterfacetypefortrackingtheingredientsinourrestaurant’spantry…

Cleanthatfridge!

Page 19: Design patterns: An Introduction to Software Design Patterns

publicinterfaceManageable{

publicQuantifiablelookup(Stringidentifier);

publicQuantifiableadd(Quantifiableentry);

publicvoidremove(Quantifiableentry);

}

NowaddanInterfacetypeforbringingallofthisstocktogetherintoaManageablesystem…

InventoryControl!

Page 20: Design patterns: An Introduction to Software Design Patterns

importjava.util.Hashtable;

publicclassCentralPantryimplementsManageable{

privateHashtable<String,Quantifiable>store=null;

privateCentralPantry(){

store=newHashtable<String,Quantifiable>();}}

Wecannowbegintoimplementourcentralpantry.Butwhydoesourclassrequireaprivateconstructor?

Page 21: Design patterns: An Introduction to Software Design Patterns

privatestaticCentralPantrycache=null;

publicstaticsynchronizedCentralPantrygetPantry(){ if(cache==null)

cache=newCentralPantry();

returncache; }

Onlyaclassinstancecancallaprivateconstructor.Soprovideastaticmethodtoinstantiatetheclass.

Sousethestaticmethod,andnottheconstructor

Page 22: Design patterns: An Introduction to Software Design Patterns

publicclassCentralPantryimplementsManageable{

publicstaticCentralPantrygetPantry(){ returnSingletonCache.ONE;}privatestaticclassSingletonCache{

publicstaticfinalCentralPantryONE=newCentralPantry();

}

privateCentralPantry(){…}

OR:WecanexploitJava’slazyevaluationofassignmentsJavalazilyloadsclassesonlyastheyareneeded…

Page 23: Design patterns: An Introduction to Software Design Patterns

staticgetInstance()singletonOperations()getSingletonData()

staticuniqueInstancesingletonData

returnuniqueInstance;

Here’stheSingletonpatterninanutshell.

Page 24: Design patterns: An Introduction to Software Design Patterns

P1

P2

P3

P4

P5 P6

P8

P7

P9

P0

P10

P11

Page 25: Design patterns: An Introduction to Software Design Patterns

Whenaclasshasacomplicated,multi-stepsetupprocedure,andadiversityofconfigurationoptions,thenitmakessensetodefineanotherclass,calledaBuilder,whoseresponsibilityisthe

constructionofnewinstances ofthemorecomplexclass.

Take,forexample,themakingofapizza…

Page 26: Design patterns: An Introduction to Software Design Patterns

publicclassCommodityimplementsQuantifiable{ privateStringidentifier=null; privateintamount=1; publicCommodity(Stringname){ identifier=name; } publicStringgetIdentifier(){ returnidentifier; }

First,let’screatethemostgenericandreusablesetofclassesandinterfacesforourourexample…

Continuedoverleaf…

Pizzasarecommodities

Page 27: Design patterns: An Introduction to Software Design Patterns

publicintgetQuantity(){ returnamount; } publicintaddQuantity(intdelta){ amount+=delta; returnamount; } publicintremoveQuantity(intdelta){ amount+=delta; returnamount; }}

ImplementQuantifiableinterface

Page 28: Design patterns: An Introduction to Software Design Patterns

publicinterfaceBakeable{ publicvoidsetDough(Quantifiabledough); publicvoidaddSauce(Quantifiablesauce); publicvoidaddTopping(Quantifiabletopping); }

BeforedefiningaPizzaclass,generalizetothecategoryofallbakeablecommodities…

Pizzasimplementthesemethods

Page 29: Design patterns: An Introduction to Software Design Patterns

publicclassPizzaextendsCommodityimplementsBakeable{

privateQuantifiabledough=null,sauce=null; Vector<Quantifiable>toppings

=newVector<Quantifiable>(); publicPizza(Stringname){ super(name); }

NowwedefinePizzaastheclassofbakeablecommodities

Continuedoverleaf…

Page 30: Design patterns: An Introduction to Software Design Patterns

publicvoidsetDough(Quantifiabledough){ this.dough=dough; } publicvoidaddSauce(Quantifiablesauce){ this.sauce=sauce; } publicvoidaddTopping(Quantifiabletopping){ toppings.add(topping); }}

ImplementBakeablerequirementsforpizzavariations

Page 31: Design patterns: An Introduction to Software Design Patterns

publicinterfaceSubcontractable{ publicvoidbuildSequence(); publicvoidstartProduct(Stringname);

publicCommoditygetProduct();}

Asubcontractorisabuildertowhichwedelegatejobs.EachsubcontractormustimplementSubcontractable…

Ourpizzabuilderswillimplementthis

Page 32: Design patterns: An Introduction to Software Design Patterns

publicinterfaceContractable{ publicvoidsetSubcontractor(Subcontractable

subcontractor); publicCommoditydeliverContract();}

AContractorcanformacontractwithasubcontractortodeliveronacontractforacommoditywithaclient….

Thinkofthelinkbetweenachefandasouschef

Page 33: Design patterns: An Introduction to Software Design Patterns

abstractpublicclassPizzaBuilderimplementsSubcontractable{

privatePizzapizza=null; publicvoidbuildSequence(){ buildDough(); buildSauce(); buildToppings(); }

APizzaBuilderisasubcontractableclassthatcombinesspecificdough,sauceandtoppingstomakeapizza

Continuedoverleaf…

Page 34: Design patterns: An Introduction to Software Design Patterns

publicCommoditygetProduct(){ returnpizza; }

publicvoidstartProduct(Stringname){ pizza=newPizza(name); }

abstractpublicvoidbuildDough();

abstractpublicvoidbuildSauce();

abstractpublicvoidbuildToppings();}

Abstractmethodsmustbeimplementedbyspecificbuilders

Page 35: Design patterns: An Introduction to Software Design Patterns

publicclassHawaiianBuilderextendsPizzaBuilder{ publicvoidbuildDough(){ startProduct(“Hawaiian”);

((Bakeable)getProduct()).setDough(newCommodity("thincrust"));

} publicvoidbuildSauce(){ ((Bakeable)getProduct())

.addSauce(newCommodity("marinara")); } publicvoidbuildToppings(){ ((Pizza)getProduct()).setDough(new

Let’slookataspecificbuilderforaspecifickindofpizza…

Continuedoverleaf…

Page 36: Design patterns: An Introduction to Software Design Patterns

publicvoidbuildToppings(){

((Bakeable)getProduct()).addTopping(newCommodity("Mozzarella"));

((Bakeable)getProduct())

.addTopping(newCommodity("ham"));

((Bakeable)getProduct()) .addTopping(newCommodity("pineapple"));

}}

Aspecificbuilderappliesspecificelementstothebuild

Page 37: Design patterns: An Introduction to Software Design Patterns

publicclassPizzaContractorimplementsContractable{ privatePizzaBuildersubcontractor=null; publicvoidsetSubcontractor(Subcontractable

subcontractor){ this.subcontractor=(PizzaBuilder)subcontractor; } publicCommoditydeliverContract(){ subcontractor.buildSequence(); returnsubcontractor.getProduct(); }

APizzaContractordeliversonacontractforapizza

Continuedoverleaf…

Page 38: Design patterns: An Introduction to Software Design Patterns

publicstaticvoidmain(String[]args){

PizzaBuildersouschef=newHawaiianBuilder();

Contractablechef=newPizzaContractor();

chef.setSubcontractor(souschef);

Commoditypizza=chef.deliverContract();

if(pizza.getIdentifier()=="Hawaiian") System.out.println("Aloha!");}

}

Atlastwecreateacontractorandasubcontractorforpizza

ALOHA!

Page 39: Design patterns: An Introduction to Software Design Patterns

ExpertBuilder

+startProduct()+getProduct()

ExpertBuilder

+startProduct()+getProduct()

Subcontractor

buildSequence()

Contractor

deliverContract()

Commodity

ExpertBuilder

+startProduct()+getProduct()

forallaspectsofschemesubcontractor.buildSequence();

Page 40: Design patterns: An Introduction to Software Design Patterns
Page 41: Design patterns: An Introduction to Software Design Patterns

Exemplar1

+startProduct()+getProduct()

Exemplar1

+startProduct()+getProduct()

Exemplar1

+startProduct()+getProduct()

Exemplar1

+startProduct()+getProduct()

Commodity

clone()

Contractor

prototype

deliverContract()

Exemplar1

clone()

ExemplarN

clone()

returnprototype.clone();

Page 42: Design patterns: An Introduction to Software Design Patterns

publicstaticvoidmain(String[]args){

Pizzahawaiian=newPizza("MagnumP.I.");

hawaiian.setDough(newCommodity("thincrust"));

hawaiian.addSauce(newCommodity("barbecue"));

hawaiian.addTopping(newCommodity("ham"));

hawaiian.addTopping(newCommodity("mushroom"));

hawaiian.addTopping(newCommodity("pineapple"));

Let’sbuildaHawaiianpizzadirectly,withNoBuilderclass

Page 43: Design patterns: An Introduction to Software Design Patterns

Pizzasicilian=newPizza("TheGodfather");

sicilian.setDough(newCommodity("deeppan"));

sicilian.addSauce(newCommodity("spicy"));

sicilian.addTopping(newCommodity("salami"));

sicilian.addTopping(newCommodity("pepperoni"));

sicilian.addTopping(newCommodity("chilies"));

sicilian.addTopping(newCommodity("blackolives"));

Nowbuildanotherprototypepizza,withNoBuilderclass

Page 44: Design patterns: An Introduction to Software Design Patterns

publicCommodityclone(){ try{ return(Commodity)super.clone(); }catch(Exceptione){ returnnull; } }

IntheCommodityclasswedefineamethodto“clone”acommodity,catchinganyexceptionsthatarethrown…

A“clone”isacopyofanobjectwiththesame(==)field

values

Page 45: Design patterns: An Introduction to Software Design Patterns

publicclassCommodityContractorimplementsContractable{

privateCommoditystyle=null; publicvoidsetStyle(Commodityexemplar){ this.style=exemplar; }

publicvoidsetSubcontractor(Subcontractablesub){}; publicCommoditydeliverContract(){ returnstyle.clone(); }}

WecansimplifyourContractorclassesgreatlynow…

Page 46: Design patterns: An Introduction to Software Design Patterns

CommodityContractorchef=newCommodityContractor();

chef.setStyle(sicilian);

CommoditymyPizza=chef.deliverContract();

System.out.println(myPizza.getIdentifier());

chef.setStyle(hawaiian);

myPizza=chef.deliverContract();

System.out.println(myPizza.getIdentifier());

Let’srevisitourpizza-makingexampleviaourPrototypes

“MagnumP.I.”

“TheGodfather”

Page 47: Design patterns: An Introduction to Software Design Patterns

NoticehowtheSingleton,BuilderandPrototypepatternsalterthewayweviewclassinstantiation.

Wherepossible,wedelegatethisresponsilibitytoexpertswhohide

(byencapsulation)thetruecomplexityofobjectcreation.

Iprefermy

pizzatobemadebyanexpert!

Page 48: Design patterns: An Introduction to Software Design Patterns

CommodityContractorchef=newCommodityContractor();

chef.setStyle(sicilian);

Contractablechef=newPizzaContractor();

chef.setSubcontractor(hawaiianChef);

NoticehowinboththeBuilderandPrototypeweuseinterfacestominimizedependenciesbetweencontractorandsubcontractor…Weinjectthesedependencieslateinthegame

Page 49: Design patterns: An Introduction to Software Design Patterns

SomedevelopersconsiderDependencyInjectiontobeadesignpatterninitsownright.Whatisclearisthatitisakeypartofmanyotherdependency-reducingpatterns.

Wecallthisstrategy

DependencyInjection

Page 50: Design patterns: An Introduction to Software Design Patterns

Whenwewantafamilyofrelatedbuildersthatconstructathematically-consistentfamilyofrelatedcommodities

Page 51: Design patterns: An Introduction to Software Design Patterns

AfactoryofGUIwidgetsforMACOScanreplace

AfactoryofGUIwidgetsforWindows.

Page 52: Design patterns: An Introduction to Software Design Patterns

Factory_Style1

getPart1(),…,getPartN(),

Factory_Style1

getPart1(),…,getPartN(),

Factory_Style1

getPart1(),…,getPartN(),

Factory

getPart1(),…,getPartN(),

Consumer

factory

useParts()

Factory_Style_1

getPart1(),…,getPartN(),

Factory_Style_N

getPart1(),…,getPartN(),

Page 53: Design patterns: An Introduction to Software Design Patterns

publicclassPizzaFactoryextendsPizzaContractor{ publicCommoditygetPizza(){ returndeliverContract(); } publicCommoditygetSandwich(){ Pizzapie=(Pizza)deliverContract(); pie.setDough(newCommodity("crustyroll")); returnpie; }

Let’sturnourPizzamakerintoaFactoryofItaliandishes

Continuedoverleaf…

Page 54: Design patterns: An Introduction to Software Design Patterns

publicCommoditygetCalzone(){ Pizzapie=(Pizza)deliverContract();

pie.setDough(newCommodity("foldedcrust"));

returnpie; } publicCommoditygetLasagne(){ Pizzapie=(Pizza)deliverContract();

pie.setDough(newCommodity("lasangasheets"));

returnpie; }}

Addcalzonesandevenlasagnesforgoodmeasure…

Page 55: Design patterns: An Introduction to Software Design Patterns

publicstaticvoidmain(String[]args){

PizzaBuilderstylist=newHawaiianBuilder();

PizzaFactoryfactory=newPizzaFactory();

factory.setSubcontractor(stylist);

Commoditylunch=factory.getSandwich();

if(lunch.getIdentifier()=="Hawaiian") System.out.println("TheEnd");}

}

Nowourpizzafactorymakesthematicallyconsistentdishes

TheEnd