7 Design Patterns

Transcription

7 Design patternsDefinition– Example–Design Patterns inDistributed systemsObserver– Command– Memento–

Design patterns Definition– A design pattern is a tried & tested solution to acommon design problemCompare with problem frames:––A problem frame is a common form of a problemA design pattern is a common form of a solution in the design space – there are also patterns in theimplementation, e.g. standard bits of codeAs for all patterns, it's an idea, not a rule–Amenable to adaptation

Design patterns A design pattern is characterized by–––A nameA description of the problem it aims to solveA description of the solution Elements of the designRelationships among them––Interactions, responsabilities, collaborationA discussion of the consequences of applyingthe pattern Design trade-offs

An example: MVC One of the most famous patterns: ModelView-ControllerOriginally introduced in the Smalltalk-80 baselibraryProblem: a good general way to handle userinterface componentsSolution: use three different objects, withwell-defined interfaces but arbitraryimplementations–Model, View, Controller

An example: MVC Model: an object that provides a purelyabstract description of the “thing” that is to berepresented by the UI controlView: an object that, given the data in theModel, can render it on-screen in some formController: an object that, given some userinput (e.g., a mouse click or keypress), altersthe Model (or possibly the View) according touser's intentions

An example: MVC The relationship between Model, View andController is dynamic–It can be set-up and changed at runtime e.g., need to disable a GUI element to prevent issuingof invalid commands? Change its Controller to adummy one that ignores all user inputEach object has precise responsabilities–Described in terms of the interfaces it must offerto other objects e.g., all Controllers must implement the same interface,regardless of their actual class

An example: MVC

An example: MVC The basic MVC pattern uses 1:1 relationshipsbetween Model, View, ControllerWith further massaging, these can becomen:m relationshipsMost often seen asmultiple views forthe same model–Hint: in a distributed system,each view can be on a differentmachine and use different media

Design patterns in distributedsystems Most design patterns assume that.––––Objects have a private stateObjects can communicate by invoking operationsObjects can exchange arbitrary data asparameters attached to such operationsObjects have their own control flow Either their own thread, or hijacking the control flow ofthe callerAll these properties can be scaled up to unitsof a distributed systems–Computation memory message-passing

The Observer pattern “Define a one-to-many dependency betweenobjects so that when one object changesstate, all its dependents are notified andupdated automatically”This allows to keep a single copy of the data,and have multiple other objects depend onthem––Used e.g. in multi-view MVCCan be used for asymmetric replication andnotification in distributed systems

The Observer pattern Subject (interface)–– The thing to beobservedMaintains a set ofobserversConcreteSubject(object)––Has the actual stateProvides operationsto retrieve and alterthe state

The Observer pattern Observer (interface)– ConcreteObserver(object)–(note: applicable to parts of state)The thing to benotified–Has a local copy ofthe remoteConcreteSubjectstateGoal is to keep thecopy up-to-date

The Observer pattern Registration– a.k.a., SubscribeAn observer callssubect.attach(self)The subject adds theobserver to the set ofcurrent observersDe-registration– a.k.a., UnsubscribeAn observer callssubject.detach(self)The subject removesthe observer fromthe set of currentobservers

The Observer pattern The state of ConcreteSubject changes–Due to a call to a setState() method or due tosome autonomous eventSetState() couldalso be called by athird party(e.g., a Controller in MVC)

The Observer pattern ConcreteSubject calls notify() of Subject–Most often, Subject is an abstract classimplementing notify() — could also be an interface

The Observer pattern Notify() loops over all registered observers––Calling update() on eachEach observer calls getState() on the subject

Observer vs. Publish & Subscribe The Observer pattern is a variation of a moregeneral protocol known as Publish &SubscribeThe Subscribe part is identical to registrationand de-registration via attach() and detach()The Publish part is more general––In Observer, the only cause for broadcast arechanges in the stateIn P&S, any event can be published Details of the event are often sent as parameters ofupdate(), not retrieved via separate getState()s

Implementation of Observerpublic class Subject {List Observer obs new ArrayList Observer ();public Observable() {super();}public void attach(Observer o) { obs.add(o); }public void detach(Observer o) { obs.remove(o); }public void notify(Object data) {for (Observer o: obs) o.update(this, data);}}Adapted (and simplified) from java.util.Observable

Implementation of Observerpublic interface Observer {public void update(Subject s, Object data);}Adapted (and simplified) from java.util.Observer

Implementation of Observerpublic class concreteSubject extends Subject {declarations for concrete stateconstructors etc.public void setState(args) {updates state based on argumentsthis.notify(object describing change)}public State getState(args) {return state based on arguments}}

Implementation of Observerpublic class concreteObserver implements Observer {.public void update(Subject s, Object data) {ObservedState s.getState(args);Reacts to changes – for example, byupdating a local copy of the Subject's state,or by redrawing a View, larityclarity Error checking Error checking Synchronization Synchronization Optimization Optimization

Observer in a distributed system When applied in adistributed application––Subject and Observeroften reside ondifferent nodesCommunicationsamong the two can be SlowCostlyUnreliableLimited capacity

Observer in a distributed system Invoking operationsacross different nodes–Several options Use CORBA, RMI, orother RPC mechanismsSend a messageencoding the requestaccording to someagreed-upon protocolUse ad-hoc signaling–e.g., on receipt of anSMS with text “update”the machine will.

Observer in a distributed system Invoking operationsacross different nodes–Several options Use CORBA, RMI, orother RPC mechanismsSend a messageencoding the requestaccording to someagreed-upon protocolUse ad-hoc signaling–e.g., on receipt of anSMS with text “update”the machine will.A theme for a NetworkProgramming course(will discuss it later on)

Observer in a distributed system Establishing identityacross different nodes–attach() and detach()are easy with localobjects –Storing a pointer to theobserver sufficesMore complex in adistributed system Need some sort ofunique ID

Observer in a distributed system Concurrent executionof updates––Each node can performwhatever its ownupdate() requires inparallel with othersNo need for a call toupdate() to be blocking Same holds locally,proper synchronizationUse broadcast forupdate()

Building a cost model for Observer Cost for attach() and detach()–– Cost for each update()–– One call passing of ID for each(possible hidden cost for accessing a network ID)One call [for update()] passing of ID passingof dataOne call [for getState()] passing of stateCost for each notify()–K updates(), with K number of registeredobservers

Building a cost model for Observer Cost for attach() and detach()–– One call passing of ID for each(possible hidden cost for accessing a network ID)Cost for each update()These are typically infrequent– One operationscall [for update()]of data passing of ID passingIn most systems, only performed atboot-upor shutdown– Onecall[for getState()] passing of stateCost for each notify()In some system, performed when anode joins/leaves the distributedsystem–K updates(), with K number of registeredRarely, hugely dynamicobservers

Building a cost model for ObserverThis part is paid at each state change Cost proportional to (serialized) size ofthe state and to the number of observersCost for attach() and detach()–– Cost for each update()–– One call passing of ID Canfor becomeeach HUGE!(possible hidden cost for accessing a network ID)One call [for update()] passing of ID passingof dataOne call [for getState()] passing of stateCost for each notify()–K updates(), with K number of registeredobservers

Optimizing the distributedObserver We need strategies to reduce the cost ofObserver in a distributed applicationMain venues:––– Reduce the number of updatesReduce the size of each updateReduce the number of observersThe particular problem will often dictate what ispossible and what is notStrike a balance between code complexity( robustness) and performance ( efficiency)

Reducing the # of updates Coalescing––At times, it is not sensible to send out many littleupdates: it's better to coalesce many setState()calls, then send out a single cumulative notify()Add two operations to Subject hold() - suspends all updatesrelease() - resumes sending out updates–––Also, sends out a first notify() if there was any change w.r.t.the previous hold()Risk: hold() without release()!Increases code complexity (e.g., multiple calls)

Reducing the # of updates Partitioning––– Upon registration, express interest in somesubset of the stateOnly send out updates to Observers that haveexpressed interest in the changed partitionEquivalent to having many smaller SubjectsImplementation–Add a parameter interest to attach() (often, abitmask), orAdd an operation setInterest(o,i) to express thatobserver o is interested in facet i of the state

Reducing the # of updates Flow control––– Stop sending further updates until the Observerhas finished processing the previous setAlso helps with the overrun concernNeeds an additional cost to signal completionImplementation––––In notify(), use an asynch invocation for update()Put every notified Observer in a “suspended” setAdd an operation done() to resume an observerIn the implementation of notify(), call done() oncefinished

Reducing the # of updates Flow control––– Stop sending further updates until the ObserverApplicablewhentherecenthas finished nterestAlso helps with applications)Needs an additional cost to signal altransactions)transactions)In notify(), use an asynch invocation for update()Put every notified Observer in a “suspended” setAdd an operation done() to resume an observerIn the implementation of notify(), call done() oncefinished

Reducing the # of updates Shifting responsibility to clients––––Instead of triggering an update at each setState(),allow clients to call notify() when they think thatobservers need to be notifiedOnly applicable if clients of the Subject have anidea about the needs of ObserversReduces decoupling, makes systems moretangledIncreases chances of missing an update i.e., client “forgets” to call notify()

Reducing the size of each update Using small getters–––In our scheme, update() has a negligible payloadgetState() is where the largest amount of data istransferredReplace getState() with finer-grain getters Each get.() pays the cost of 1 call the cost fortransferring the dataBalancing: too many getters to call, and you end uppaying more than a single call to transfer the wholestate

Reducing the size of each update Put the payload in update()–– Instead of having update() cause a call togetState(), pass the state change as parameterOpposite to coalescing, friendly to partitionImplementationpublic void setX(T x) {T oldValue x;this.x x;notify("x", oldValue, x); update}

Reducing the size of each update Push model–– Each setX() sendsfull notification forthat particular updateObserver has it all Pull model––Each setX() sendsjust a notify(void)Observer decides if,what, when to get.()Intermediate models––Some of the information about a change is sentwith update()Some is retrieved by the Observer upon need

Reducing the # of observers Rarely we have the luxury of deciding how manyobservers we will have– At times, it can be decided at design timeIt might be possible to keep the number ofobservers low by dynamic attach()/detach()– e.g.: web browsers on a page from our serverBalancing the cost for those with the cost for updatesWe can set a hard limit––the (K 1)th attach() will failQoS to already registered observers wins

Complex update aaseparateseparatemediatormediatorobjectobject

The Command pattern “Encapsulate a request as an object, therebyletting you parametrize clients with differentrequests, queue or log requests, and supportundoable operations”Normally operations are requested byinvoking a methodWith Command, operations are requested bypassing an object––The object can carry an implementation with itBUT, only few communication channels can carrycode

The Command pattern Command: aninterface to executean operationConcreteCmd: implements executionClient: creates and sends CommandsInvoker: causes the execution of a CommandReceiver: knows how to manage Commands

The Command pattern

The Command pattern execute() vs. action()–– The Invoker calls execute() on the Commandexecute() in turns calls one or more operations( action() )on the receiver to produce the desiredeffectLeeway about how much processing should bedone in execute(), and how much in action()––The Command could be very autonomous and do allthe state changing itselfThe Command could be just a delegate and simplycall an operation of the receiver

Implementing Commandpublic interface Command {public abstract void execute();}public class Genesis implements Command {public void execute() { universe.start(); }}public class Armageddon implements Command {public void execute() { universe.stop(); }}public class MinorMiracle implements Command {public void execute() { universe.setState(.); }}

Implementing Commandpublic interface Command {Receiver, here accessed statically.public abstract void execute();Could be a parameter set in theconstructor of Command.}public class Genesis implements Command {public void execute() { universe.start(); }}public class Armageddon implements Command {action() of the Receiver.public void execute() { universe.stop(); }}public classCould also be a complex set ofchanges, or include significantbusiness logicMinorMiracleimplementsCommand {public void execute() { universe.setState(.); }}

Implementing Commandpublic interface Invoker {public void storeCommand(Command c);}public class PermissionInvoker {public void storeCommand(Command c) {if (requiresPermission(c))askUser(c); exception if viledgedCommands.Commands.

Implementing Commandpublic class UndoInvoker implements Invoker {Stack State undoStack new Stack State ();public void storeCommand(Command c) public void undo() o.

Distributing eedsneedstotobebetransmittedtransmitted

Distributing finedset).set).

Distributing Mightrequirerequirecodecodemigration.migration.

Distributing rnaling,journaling,etc.etc.

Goals for Command Implement delayed execution– Implement logging/journaling/stat collection– Commands can be queued and executed laterA record is kept of who issued which commandsto whom, execution times, etc.Implement undo/redo/repeat–––Whenever a command is executed, add it to a listof undoable operationsCommand can have undo() and redo()Alternatively, can use a stack of states

Goals for Command Implement Command queue inspectiontechniques–Buffering and coalescing commands –Accumulation “only last valid command counts”Transform move(dx1, dy1); move(dx2, dy2) tomove(dx1 dx2, dy1 dy2)Implement preemptible Commands–Allows changing your mind Send! — then, you can press Cancel sending in thenext 5 seconds

Goals for Command Allows multiple sources for the sameCommand–––– An icon in the tool barA menu entryA keyboard shortcutA scripting interfaceAllows multiple destinations for the sameCommand–“Cut” can be sent to a text, to a picture, to asound sample.

The Memento pattern “Without violating encapsulation, capture andexternalize an object's internal state so thatthe object can be resotred to this state later”In practice, we want an opaque container forthe private state of some object–––The owner can “lend” the state to someone elseOnly the owner can recover the internal stateStill, the opaque state can be stored, transmittedetc.

The Memento pattern Originator has the state, can create MementosMemento holds the state in the opaque formCaretaker can only store/retrieve/passMementos

The Memento pattern

The Memento ementoMementototothetheCaretakerCaretaker

The Memento ullfullstatestateofofthetheOriginator.Originator.

Distributing MementoMemento spansboth nodes

Design patterns Definition – A design pattern is a tried & tested solution to a common design problem Compare with problem frames: – A problem frame is a common form of a problem – A design pattern is a common form of a solution in the design space – there are also patterns in the implementation, e.g. standard bits of code As fo