Yakov Fain - Design Patterns a Deep Dive

32
Design Pa*erns, a Deep Dive By Yakov Fain Farata Systems (c) Farata Systems

description

Design patterns suggest approach to common problems that arise during software development regardless of what programming language. But implementation of these patterns is specific to the language. The main goal of this presentation is to highlight selected patterns as they may be implemented taking advantages of Flex framework.You'll see a not so obvious implementation of a Singleton, how a Proxy can dramatically change the behavior of an object, why a Mediator is a must-have in each Flex application. Do you know how to write Data Transfer Objects that are so important in Flex remoting? If time permits, we'll review the Class Factory pattern too.

Transcript of Yakov Fain - Design Patterns a Deep Dive

Page 1: Yakov Fain - Design Patterns a Deep Dive

DesignPa*erns,aDeepDive

ByYakovFainFarataSystems

(c)FarataSystems

Page 2: Yakov Fain - Design Patterns a Deep Dive

2

Farata Systems: What do we wo

Consulting and training

Software development (for free) (open source project Clear Toolkit on Sourceforge.net)

Writing tech. books and articles on Java and Adobe Flex (making from $0 to $1 per hour)

www.faratasystems.com

($$$$$$$$$$$$$$$$$$)

Page 3: Yakov Fain - Design Patterns a Deep Dive

Whatisthisabout?

Designpa*ernssuggestanapproachtocommonproblemsthatariseduringsoCwaredevelopmentregardlessofwhatprogramminglanguageyouuse.

ButthegoalofthispresentaGonistohighlightselectedpa*ernsasyoumayimplementthemtakingadvantageoftheFlexframework.

(c)FarataSystems

Page 4: Yakov Fain - Design Patterns a Deep Dive

We’lltalkaboutthesepa*erns

•  Singleton•  Proxy•  Mediator

•  DataTransferObject•  AsynchronousToken

(c)FarataSystems

Page 5: Yakov Fain - Design Patterns a Deep Dive

SingletonYoucancreateonlyoneinstanceofsuchaclassThere’snoprivateconstructorsinAcGonScript

ConsiderasamplefileMySingleton.as

packagesomePackage{publicclassMySingleton{

privatestaGcconst_instance:MySingleton=newMySingleton(Lock);publicstaGcfuncGongetinstance():MySingleton{return_instance;}publicfuncGonMySingleton(lock:Class){if(lock!=Lock){thrownewError("IllegalinstanGaGon.");}}}//EndofpackageclassLock{}

(c)FarataSystems

Page 6: Yakov Fain - Design Patterns a Deep Dive

Haveyoueverseenthis?

varmodel:AppModelLocator=AppModelLocator.getInstance();

andthis?service=ServiceLocator.getInstance().getHTTPService('loadEmployeesService');

(c)FarataSystems

Page 7: Yakov Fain - Design Patterns a Deep Dive

EnhancingtheApplicaGonobjectpublicdynamicclassDynamicApplica5onextendsApplica5onimplementsIApplicaGonFacade{publicfuncGonDynamicApplicaGon(){

super();}

publicstaGcvarservices:DicGonary=newDicGonary();

publicfuncGongetService(name:String):Object{ returnservices[name];}publicfuncGonaddService(name:String,value:Object):void{ services[name]=value;}publicfuncGonremoveService(name:String):void{ deleteservices[name];}publicfuncGongetServices():DicGonary{ returnservices;}

}

TheIApplicaGonFacadejustdeclaresthesefourmethodstoenableFlexBuilder’sintellisensehelpwhencasGng.var myApp:IApplicationFacade = …

(c)FarataSystems

Page 8: Yakov Fain - Design Patterns a Deep Dive

AddinganyproperGestomyModel

(c)FarataSystems

Page 9: Yakov Fain - Design Patterns a Deep Dive

SampledynamicapplicaGon(beginning)<?xmlversion="1.0"encoding="uc‐8"?><fx:DynamicApplicaGonxmlns:mx="h*p://www.adobe.com/2006/mxml"layout="absolute"xmlns:fx="h*p://www.faratasystems.com/2009/components"creaGonComplete="addAllServices();"><mx:Script>

<![CDATA[importcom.farata.core.DynamicApplicaGon;importmx.core.ApplicaGon;

//AddrequiredservicestotheApplica3onobject,i.e.myModelandmyServicesprivatefunc5onaddAllServices():void{

DynamicApplicaGon.services["myModel"]=newObject(); DynamicApplicaGon.services["myServices"]=newObject(); }

privatefunc5ongetData(serviceName:String,key:Object):Object{

returnDynamicApplicaGon.services[serviceName][key];}

privatefunc5onsetData(serviceName:String,key:Object,value:String):void{

DynamicApplicaGon.services[serviceName][key]=newString(value);}

]]></mx:Script> (c)FarataSystems

Page 10: Yakov Fain - Design Patterns a Deep Dive

<!‐‐AddingvaluestomyModel‐‐><mx:Bu*onlabel="AddtomyModel"x="193"y="59”click="setData('myModel',key.text,value.text)"/>

<mx:Labelx="14"y="42"text="Key"fontWeight="bold"/><mx:Labelx="14"y="14"fontWeight="bold"fontSize="14"><mx:text>Addoneormorekey/valuepairstotheobjectMyModel</mx:text>

<mx:Labelx="91"y="42"text="Value"fontWeight="bold"/><mx:TextInputx="8"y="59"id="key"width="75"/><mx:TextInputx="89"y="59"id="value"width="96"/>

<!‐‐RetrievingthevaluefromaSingleton.‐‐><mx:Bu*onlabel="Showthevalue"x="8"y="122"click="retrievedValue.text=getData('myModel',key.text)asString"/><mx:Labelx="135"y="121"width="95"id="retrievedValue"fontWeight="bold"fontSize="15"/><mx:Labelx="10"y="94"fontWeight="bold"fontSize="14"><mx:text>RetrieveanddisplaythevaluefromMyModelbykey</mx:text></fx:DynamicApplicaGon>

SampledynamicapplicaGon(ending)

(c)FarataSystems

Page 11: Yakov Fain - Design Patterns a Deep Dive

ProxyAproxyisanobjectthatrepresentsanotherobjectandcontrolsaccesstoit.

Thinkofasecretarythatreceivesapackageforherboss.

InAcGonScriptyoucanwraptheclassXYZinmx.uGl.ObjectProxy,whichwillbeaproxythatcontrolsaccesstotheXYZ’sproperGes.

(c)FarataSystems

Page 12: Yakov Fain - Design Patterns a Deep Dive

How[Bindable]works?[Bindable]varlastName:String;

Flexcompilergeneratesawrapperclasswithase*erthatdispatchespropertyChangeeventoneachmodificaGonoflastName

Youcandoitonyourownbyusingtheclassmx.uGls.ObjectProxy

(c)FarataSystems

Page 13: Yakov Fain - Design Patterns a Deep Dive

packagecom.farata{publicdynamicclassPerson {publicvarlastName:String="Johnson";publicvarsalary:Number=50000;}}

WrappingPersoninObjectProxy

(c)FarataSystems

Page 14: Yakov Fain - Design Patterns a Deep Dive

RunningthePersonproxy

(c)FarataSystems

Page 15: Yakov Fain - Design Patterns a Deep Dive

ExtendingObjectProxy

AddsomeapplicaGonlogictoit.Ifthesalaryofapersonincreasesover$55K,shebecomesenGtledforthepensionintheamountof2%ofthesalary.YouwanttoaddthisfuncGonalitywithouttouchingthecodeoftheclassPerson.

InasubclassofObjectProxy,youcanoverridegetProperty() andsetProperty() fromthenamespaceflash_proxy.

Ifyou’llwriteMyPersonProxy.lastName=”McCartney”,thisobjectwillcallitsownmethodsetProperty(“lastName”, “McCartney”). InterceptthiscallandaddsomeprocessingtototheoverriddenmethodsetProperty().

(c)FarataSystems

Page 16: Yakov Fain - Design Patterns a Deep Dive

TesGngMyPersonProxy

ACer3clicksaddingpension property

(c)FarataSystems

Page 17: Yakov Fain - Design Patterns a Deep Dive

Mediator

Anycomplexscreen,moreorless,ofabusinessapplicaGonconsistsofanumberofcontainersandcomponents.

Wewanttocreateloosely‐coupledcustomcomponentsthatareselfcontained,donotknowaboutexistenceofeachotherandcancommunicatewiththe“outsideworld”bysendingandreceivingevents.

(c)FarataSystems

Page 18: Yakov Fain - Design Patterns a Deep Dive

BeforethetraderclickedonthePricePanel

ACerthetraderclickedonthePricePanel

WallStreet:StockTradingApplicaGon

PricePanelcomponenthasthreevariables:symbol, bid and ask

PricePaneldispatchestheOrderEventdispatchEvent(new OrderEvent( OrderEvent.PREPARE_ORDER_EVENT, symbol, bid,ask,buy));

OrderPanellistenstoOrderEventaddEventListener(OrderEvent.PLACE_ORDER_EVENT,orderEventHandler)

func5onorderEventHandler(evt:OrderEvent){sym.text=evt.symbol;operaGon.text=evt.buy?"Buy":"Sell";price.text=(oper.text=="Buy"?evt.bid:evt.ask);}

(c)FarataSystems

Page 19: Yakov Fain - Design Patterns a Deep Dive

PricePanelComponent.Take1

OrderEventcarries4variables

(c)FarataSystems

Page 20: Yakov Fain - Design Patterns a Deep Dive

CustomEventOrderEvent

TheMediatorreceivesthiseventfromPricePanelanddispatchesittoOrderPanel

Toomanyuservariables.ItwouldbeagoodideatoencapsulatetheminoneDTO–DataTransferObjecta.k.a.ValueObject

(c)FarataSystems

Page 21: Yakov Fain - Design Patterns a Deep Dive

TheMediatorapplicaGonListentotheOrderEventfromPricingPanel

…andsendittoOrderPanel

(c)FarataSystems

Page 22: Yakov Fain - Design Patterns a Deep Dive

DataTransferObject

DataTransferObjects(DTO)a.k.a.ValueObjects(VO)areusedfordataexchangebetweenvariousapplicaGoncomponents,whichcanbeeitherco‐locatedinthesameprocessoronremotecomputers.

TheseDTO’scanevenbewri*enindifferentprogramminglanguages,forexampleJavaandAcGonScript.

(c)FarataSystems

Page 23: Yakov Fain - Design Patterns a Deep Dive

IntroducingDTOinStockTradingApp.

Insteadofpassingseveralvariablesbetweenpricingandorderpanels,we’llencapsulateorderdetailsintheOrderDTO classandsenditinsidetheeventobjecttothemediator.

(c)FarataSystems

Page 24: Yakov Fain - Design Patterns a Deep Dive

PricePanelComponent.Take2

startDataFeed() emulatesexternaldatafeed

PackagingaDTOinsidetheeventOrderEvent2

UIcomponentsareboundtoDTOproperGes

(c)FarataSystems

Page 25: Yakov Fain - Design Patterns a Deep Dive

NowPricePanelDispatchesOrderEvent2

Theapplica5on(mediator)willgetthiseventanddispatvhittotheOrderPanel:

varorderEvt:OrderEvent2=newOrderEvent2(OrderEvent2.PLACE_ORDER_EVENT,evt.orderInfo);

ordPanel.dispatchEvent(orderEvt); (c)FarataSystems

Page 26: Yakov Fain - Design Patterns a Deep Dive

OrderPanelreceivestheevent…

…extractstheDTOfromtheevent

…andpopulatesUIcomponentsofOrderPanel

(c)FarataSystems

Page 27: Yakov Fain - Design Patterns a Deep Dive

AdvancedDTOs

Ifyouenvisiondynamicupdatestothedataontheclient,declaretheseclassesas[Bindable].

UseanArrayCollecGonofsuchbindableDTO’sasadataProviderinyourDataGrid,List,andsimilarcomponents.

Makesurethatbothserver‐sideandclient‐sideDTOsprovideuniquepropertyuuid.FlexusesthispropertytouniquelyidenGfythedataelementsoftheList‐basedcontrols.

ConsiderreplacingeachpublicproperGeswiththege*erandse*ertohavemorecontroloverthemodificaGonsoftheseproperGes.

Youcanandaddthecodetothesese*ers/ge*ersthatwillintercepttheacGonofdatamodificaGonandperformaddiGonalprocessingbasedonwhat’sbeingchanged.Then,these*ercandispatchtheeventPropertyChangeeventasshownonthenextslide

(c)FarataSystems

Page 28: Yakov Fain - Design Patterns a Deep Dive

SampleDTOwithbidproperty

FarataSystemshascreatedDTOgeneratorforJavaprogrammerscalledDto2FxthatcreatesAcGonScriptDTOsfromtheirJavacounterparts.It’safreeware,andyoucangetitath*p://flexblog.faratasystems.com/?p=357

(c)FarataSystems

Page 29: Yakov Fain - Design Patterns a Deep Dive

AsynchronousToken

TheusermakesseveralRemoteObjectrequestsandresultscomebackasynchronouslyinarbitraryorder.

EachrequestcallsaresulthandlerfuncGonprovidingtheresultevent.

HowtheapplicaGoncodecanmaparrivingresultobjectsbacktotheiniGalrequestors?

(c)FarataSystems

Page 30: Yakov Fain - Design Patterns a Deep Dive

AsyncTokenClassThegoaloftheAsynchronousTokenpa*ernistoproperlyroutetheprocessingontheclientinresponsetothedataarrivingasynchronouslyformtheserver

AsyncTokenisadynamicclass,youcanaddanyproperGestothisclassduringrunGme<mx:RemoteObjectid=”ord”desGnaGon=”Orders”/>…

privatefuncGonsendOrder(/*argumentsgohere*/):void{

vartoken:AsyncToken=ord.placeOrder({item:”SonyTV”});token.orderNumber=”12345”;

token.responder=newResponder(processOrderPlaced,processOrderFault);token.addResponder(newResponder(createShipment,processOrderFault));}

(c)FarataSystems

Page 31: Yakov Fain - Design Patterns a Deep Dive

Whentheresultcomesback

AsyncTokenisalocalobject.ItisidenGfiedbyamessageId thatispassedwiththerequesttoserver.

Whentheserverresponds,itincludesacorrelationId propertyinthemessageheader,andFlexautomaGcallycallstheappropriateAsyncTokenrespondersintheordertheyweredefined.

privatefuncGonprocessOrderPlaced(event:ResultEvent):void{

myOrderNumber:Object=event.token.orderNumber;

//ifmyOrderNumberis12345,processitaccordingly}

(c)FarataSystems

Page 32: Yakov Fain - Design Patterns a Deep Dive

ContactInfo&LinksEmail:[email protected]

Website:h*p://www.faratasystems.com

ClearToolkit:h*p://sourceforge.net/projects/cleartoolkit/

O’ReillyBook“EnterpriseDevelopmentwithFlex”:h*p://my.safaribooksonline.com/9780596801465

(c)FarataSystems