Kĩ thuật lập trình - Lecture 18: Design patterns command, decorator, state, proxy

Command Pattern Decorator Pattern State Pattern Proxy Pattern Protection Proxy

ppt31 trang | Chia sẻ: thuychi16 | Lượt xem: 731 | Lượt tải: 0download
Bạn đang xem trước 20 trang tài liệu Kĩ thuật lập trình - Lecture 18: Design patterns command, decorator, state, proxy, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
Ivan MarsicRutgers UniversityLECTURE 18: Design Patterns Command, Decorator, State, Proxy1TopicsCommand PatternDecorator PatternState PatternProxy PatternProtection Proxy2Command Pattern MotivationClientAServerBdoAction( params )(a)ClientAexecute()ReceiverBdoAction( params )Commandcreate( params )(b)unexecute()(Server)3Command Pattern MotivationMotivation: To separate parameter preparation from passing program control (decision on when to call)ClientAServerBdoAction( params )ClientAexecute()ReceiverBdoAction( params )Commandcreate( params )unexecute()Reasons for separation:Separate preparation of calling parameters (which may become available much before the execution time or may become available incrementally)All calling parameters become localized in a Command object (“encapsulated”)Parameters may be prepared for the Client by a different object (“Custodian”)Client and Custodian objects’ codes may evolve separatelyI.e., different developers develop and maintain or upgrade these classesMay prepare all Commands in a list (with different parameters or different Receivers) and simply iterate through the list to execute allFor un-execute (roll-back) capabilityParameters may be prepared by a different object (“Custodian”)(Server)PreparationExecution4Command Pattern MotivationProblem: Variable and evolving method signatureIf Server code changes, Client code needs to change, tooMethod 1Method 2ClientServer (Receiver)Before:5Command Pattern ImprovementMethod 1Method 2ClientServer (Receiver)Before:After: The interface to the Server object is much simpler.execute()execute()ClientCommand 1Command 2Method 1Method 2Server (Receiver)The change towards the Cmd. pattern may not appear radical when viewed overall, but looking from the client’s standpoint, the simplification is significant.6Command Pattern ImprovementCommand provides a uniform method signature (“interface”) to the ServerThe Command interface never changes, so Server changes do not force Client changesClient only decides when to execute()Client evolution is decoupled from Server implementation and Command implementationClient versus Server/Command can be responsibilities of different developers 7Command Pattern(a)Forwardexecution(do)(c)(b)8Command AdvantagesExecution is usually called with other business logicNow it is decoupled from parameter preparation, which can be done at another place (“staging area”), not interfering with business logic (“execution area”)Business logic is decoupled from parameter preparationClient and Custodian codes may evolve independently, by different developers9Command Pattern InteractionMany times commands can be reversed/undoneExtended interface to check for reversibility and, if true, undo(a)(b)Reverse execution(undo)10Decorator Pattern MotivationMotivation: To separate essential from non-essential functions and allow easy adding of new non-essential functionsImplies only one Subject — one essential function, one “responsibility”Solution: Client only has a pointer to the “head of the list” (of services) and does not know the true identity of the head objectAll services in the list look the same since all implement the same interface (here, “list” is not a list data structure!!)Advantages:When a new optional function/service is added, client code does not need to changeOnly need to program the new function/service and insert it in the “linked list” ( “dependency injection”)11DecoratorClient only knows the head-of-the-listBut doesn’t know it’s identity (RealSubject vs. Decorator), because all list elements implement the same abstract interface (Subject)Client doesn’t know how many Decorators are in the list  The list can seamlessly expand or shrink(a)(b)12Decorator(a)(c)(b)Uniform method calling, regardless of the head-of-the-list object identityPre-processingPost-processingPre- versus Post-processing is defined relative to the essential feature:the request() of RealSubject13Decorator Example – GUI Options14Decorator - Example15Deco Example – Unlock Use Case16Example: Midterm #2, Spring 2013State diagram for Display Interaction:ReadyFaultymeasurement-initiated /failure-detected /Measuring[battery-level  threshold] /Dischargedmeasurement-completed /battery-charged /button-pressed / display msg [battery-level  threshold] /button-pressed / display msg button-pressed / display msg button-pressed / display msg button-pressed / display msg Not-Wornwearing-detected /Problem: Design the UML sequence diagram; apply design patternsGiven:17Student solution: Class diagramclient«interface»DeviceCheck+ check() ButtonCheck+ increment()Subject andDecorator interface BatteryCheck+ checkBattery() DeviceWearChk+ checkWearing() FaultyCheck+ checkSensor()Concrete Decorators MeasuringCheck+ chkMeasuring() BP_Check+ checkBP()+ display() HR_Check+ checkBP()+ display() AL_Check+ checkAL()+ display() BL_Check+ checkBL()+ display()Real SubjectsBP = blood pressureHR = heart rateAL = activity levelBL = battery level18Student solution: Class diagramWhat went wrong?Decorators and Subjects don’t implement the top-level interfaceMethods are named differentlyMore than 1 SubjectNot in the spirit of this patternclient«interface»DeviceCheck+ check() ButtonCheck+ increment()Subject andDecorator interface BatteryCheck+ checkBattery() DeviceWearChk+ checkWearing()nextDevice FaultyCheck+ checkSensor()Concrete Decorators MeasuringCheck+ chkMeasuring() BP_Check+ checkBP()+ display() HR_Check+ checkBP()+ display() AL_Check+ checkAL()+ display() BL_Check+ checkBL()+ display()Real Subjects19displayStudent sol’n: Sequence diagram: DeviceWearChk: FaultCheck: Measuring CheckcheckFault()client :display error msgalt[else]buttonPress( )device not worn OR faulty OR measuringcheckWearing()checkMeasuring(): BPCheckcheckBP(): HRCheckcheckHR()display20displayStudent sol’n: Sequence diagramWhat went wrong?Decorator objects are not forming a “linked list” and calling each other uniformly — instead, the Client is calling all decorators in sequence!!: DeviceWearChk: FaultCheck: Measuring CheckcheckFault()client :display error msgalt[else]buttonPress( )device not worn OR faulty OR measuringcheckWearing()checkMeasuring(): BPCheckcheckBP(): HRCheckcheckHR()display21Another Student SolutionCorrect use of the Decorator pattern: All Decorators implement the same interfaceclient«interface»Subject+ request() Measurement+ request() Decorator+ request()next objectSafetyZoneChecker+ request()ActivityLevelChecker+ request()22Another Student SolutionUniform calling approach — client calls only the head of the “linked list”: ActivityLevelChecker: MeasurementresultcheckActivityLevel( ): SafetyZoneCheckerclient :request( args )checkSafetyZones( )result‡request( args )request( args )result and ‡ denote added special-case processing23State Pattern MotivationMotivation: To separate state-dependent event-handling functions from each other and allow easy adding of new states and eventsSolution: Event-handling object (“server” or “context”) externalizes its state-dependent functionality into different “state objects”Context only has a reference to the current state object and does not know its true identity (knows that it’s a state, but not which one)All State objects look the same (all implement the same interface)Advantages:When a new state or event is added, client code does not need to changeInstead of implementing a single big state-transition table, say 10 states by 15 events, we implement 10 State objectsEach State object maintains only a small part of the big table relevant to it (input-event / next-state)Only need to program the new State object and link it with other states according to the transition diagram ( “dependency injection”)24State Pattern(a)(b)(c)25State Pattern(a)(b)(c)(d)26State PatternAll State objects are instantiated and mutually interlinked with each other (“dependency injection”)A State object knows the next states (depending on input events and guard conditions)State’s method handle(Event) returns the next stateThe Context object knows only about one State object (representing the “current state”) and keeps updating it as told by the return value from currentState.handle(Event) .Context does not know (nor need to know!) the true identity of the current state object – all State objects implement the same abstract interface27ProxyNotes:Proxy is structurally the same as Decorator, but has different intentionWe could have a “linked list” of Proxies, like with Decorators(a)(b)(c)28Protection Proxy – Example (1)What if we wanted to add a Maintenance role & access privileges?Instead of hard-coding the new role privileges, we just define a new Protection Proxy29Protection Proxy – Example (2)30Protection Proxy – Example (3)31