Transcript
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


Top Related