Design Patterns Observer Oliver Haase 1 Description Object based - - PowerPoint PPT Presentation

design patterns
SMART_READER_LITE
LIVE PREVIEW

Design Patterns Observer Oliver Haase 1 Description Object based - - PowerPoint PPT Presentation

Design Patterns Observer Oliver Haase 1 Description Object based behavioral pattern Purpose : Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated


slide-1
SLIDE 1

Oliver Haase

Design Patterns

Observer

1

slide-2
SLIDE 2

Description

2

  • Object based behavioral pattern
  • Purpose: Define a one-to-many dependency between
  • bjects so that when one object changes state, all its

dependents are notified and updated automatically.

  • Also Known As: Publish-Subscribe
slide-3
SLIDE 3

Model View 1 View 2 View 3 Observer Subject, Observable notify get update

Motivating Example

3

  • keep consistency between decoupled objects
  • often used in the context of the MVC architectural pattern,

more general, related to event listeners

  • helps build a layered architecture
slide-4
SLIDE 4

update() Observer concreteSubject.get() attach(Observer) detach(Observer) notify() Subject update() ConcreteObserver

  • bservers

get() set(s) state ConcreteSubject concreteSubject state = s notify() return state for each o in observers

  • .update()

General Structure

4

  • knows its observers
  • provides interface for attaching

and detaching observers

  • concrete observed subject
  • maintains state
  • notifies observers about change of state

defines call-back operation to get notified uses concrete subject’s get

  • perations to pull

updated state

slide-5
SLIDE 5

Applicability

Use the Observer pattern when

  • the abstraction has two aspects where one depends on the
  • ther. Encapsulating these aspects in separate objects will

increase the chance to reuse them independently.

  • the subject doesn't know in advance how many observer
  • bjects it will have.
  • the subject should be able to notify its observer objects

without knowing them.

5

slide-6
SLIDE 6

Interactions

  • ConcreteSubject notifies its observers whenever a change

to its internal state happens.

  • After a ConcreteObserver gets notified, it may query the

subject state by using the get() method.

ConcreteObserver uses this information to change its own

internal state.

6

slide-7
SLIDE 7

Pros & Cons

  • Pros:
  • Decoupling of subject and observer, each can be extended

and reused individually.

  • Dynamic addition and removal of observers at runtime.
  • Subject broadcasts notification automatically to all interested
  • bjects, no matter how many or which kind of observers are

registered.

  • Cons:
  • May result in many notifications the observers are not

interested in

  • Potentially difficult for the observers to figure out the

specific state change of the subject.

7

slide-8
SLIDE 8

Push vs. Pull Model

  • In its purest form, notification does not carry updated state

information → Pull Model

  • Variant: notification contains updated state → Push Model

8

Pull Model Push Model signature of notify

  • peration

number of

  • peration calls

unnecessarily exchanged state information independent of subject’s state fields subject to modification if subject’s state fields are changed higher lower fewer more

slide-9
SLIDE 9

Observer in Java

9

Call of notifyObservers without prior call of setChanged has no effect!

update(Observable, Object) <<interface>> Observer + addObserver(Observer) + deleteObserver(Observer) + notifyObservers() # setChanged() Observable update(Observable, Object) MyObserver

  • bservers

getState() setState(s) state MyObservable state = s setChanged() notifyObservers()

slide-10
SLIDE 10

Observer in Java

  • Observable is a class.
  • What if our observable subject already has a super-class?
  • What aspects of inheritance are needed?

10

→ implementation inheritance, and → interface inheritance ⇒ SmartAdapter!

  • Can class Observable be delegated to?

→ No, because setChanged is protected.

  • Adapter & Delegation (see Implementation Reuse patterns)
slide-11
SLIDE 11

Observer in Java: SmartAdapter

11

update(Observable, Object) <<interface>> Observer + addObserver(Observer) + deleteObserver(Observer) + notifyObservers() # setChanged() Observable update(Observable, Object) MyObserver

  • bservers

getState() setState(s) state delegate MyObservable MySuper state = s delegate.setChanged() delegate.notify() + setChanged() + getState() + setState(s) delegate SmartObservableAdapter delegate.setState(s) return delegate.getState() super.setChanged()

slide-12
SLIDE 12

Observer and Concurrency

Naive implementation of attach(), detach(), and notify()

12 public final class NaiveSubject { private final Vector<Observer> observers; ... public final void attach(Observer o) {

  • bservers.addElement(o);

} public final void detach(Observer o) {

  • bservers.removeElement(o);

} public final void notifyObservers() { for(Observer o : observers) {

  • .update();

} } }

slide-13
SLIDE 13

Observer and Concurrency

  • Vector is thread-safe, but NaiveSubject is not.
  • NaiveSubject will throw

ConcurrentModificationException if a thread adds or

removes an observer while another notifies the observers.

  • Possible solutions:
  • Java Monitor Pattern (risky because of alien method call)
  • Use CopyOnWriteArrayList
  • Copy vector before iteration (this is how JDK Observable

does it)

13

slide-14
SLIDE 14

Observer and Concurrency

  • Do not attach observer to subject inside observer’s

constructor!

14

→ Otherwise the observer’s this reference escapes before the subject is fully constructed. Reminder: In general, do not register a listener at an event source within listener’s constructor!

slide-15
SLIDE 15

Relationship with other Patterns

15

MVC architectural pattern almost always uses Observer pattern.

slide-16
SLIDE 16

Mediator

16

slide-17
SLIDE 17

Motivation

17

  • Complex systems often require that the participating
  • bjects know each other.
  • This might end up in a nontransparent situation which is

hard to understand.

  • The Mediator now supervises this communication.
  • It knows all the objects taking part and the objects are only

aware of the mediator.

slide-18
SLIDE 18

Description

18

  • Object based behavioral pattern
  • Purpose: Define an object that encapsulates how a set of
  • bjects interact. Mediator promotes loose coupling by

keeping objects from referring to each other explicitly, and it lets you vary their interaction independently.

  • Also Known As: Broker
slide-19
SLIDE 19

Mediator Colleague ConcreteMediator ConcreteColleague2 ConcreteColleague1 mediator

General Structure

19

  • Each colleague-class knows its broker-class
  • Each colleague-object works with its broker

and not with the other colleague-objects

  • implements the general

behavior by coordinating the colleague-objects

  • knows and manages its

colleague-objects defines an interface for the interaction with colleague-objects

slide-20
SLIDE 20

Applicability

Use the Mediator pattern when

  • there are many objects that have to work with each other,

but the dependencies are unstructured and hard to understand.

  • reusability of object is hard, because it has dependencies to

many other objects.

  • a behavior that's distributed between several classes should

be customizable without a lot of subclassing

20

slide-21
SLIDE 21

Pros & Cons

  • Pro:
  • Limits subclassing
  • Decoupled colleague-objects
  • n:n-relations converted to 1:n-relations
  • Abstracts how the colleague-objects work with each other
  • Centralized control
  • Con:
  • Broker class might turn into a hard to maintain monolith

21

slide-22
SLIDE 22

Relationship with other Patterns

  • Facade: Subsystem-classes don‘t know about the facade;

colleague-classes know their broker.

  • Colleague objects can notify the broker using the

Observer pattern.

  • If the Mediator alters message then it is an Adapter

pattern.

22

slide-23
SLIDE 23

Memento

23

slide-24
SLIDE 24

Description

24

  • Object based behavioral pattern
  • Purpose: Capture the internal state of an object without

violating encapsulation and thus providing a mean for restoring the object into initial state when needed.

  • Also Known As: Token
slide-25
SLIDE 25

Description

25

  • Used for: Undo functionality
  • A Memento is an object which saves a snapshot of an
  • riginator’s internal state.
  • Only the originator has access to the state of the memento
  • bject.
slide-26
SLIDE 26

return new Memento(state) CareTaker getState() setState(state) state Memento createMemento() setMemento(Memento m) state Originator memento state = m.getState()

General Structure

26

  • Creates a memento object

capturing the originator’s internal state.

  • Use the memento object to restore

its previous state. The memento is opaque to the caretaker, and the caretaker must not operate on it.

  • Saves the state information
  • Full access only from the originator
slide-27
SLIDE 27

Interactions

27

:Caretaker :Originator aMemento:Memento

createMemento() new Memento() setState() setMemento(aMemento) getState()

slide-28
SLIDE 28

Applicability

Use the Memento pattern if

  • an object's state must be captured so that it can be

restored later on, and if

  • explicitly passing the state of the object would violate

encapsulation.

28

slide-29
SLIDE 29

Consequences

  • Preserves encapsulation.
  • CareTaker simplifies originator code.
  • Using the memento pattern can be expensive.
  • In some languages it is hard to ensure that only the

Originator can access the Memento’s state.

  • How can we ensure this in Java?

29

→ Make Memento an inner class of Originator

slide-30
SLIDE 30

Ensure encapsulation in Java

30 public final class Originator { private int state; public Memento createMemento() { return new Memento(state); } public void setMemento(Memento memento) { state = memento.getState(); } public static final class Memento { private final int state; private Memento(int state) { this.state = state; } private int getState() { return state; } } }

private method of static inner class can be called by outer class

slide-31
SLIDE 31

Relationship with other Patterns

  • Command objects can use mementos to maintain state

for undoable operations.

  • Iterator can use memento objects to save state of

iteration.

31

slide-32
SLIDE 32

Strategy

32

slide-33
SLIDE 33

Description

33

  • Object based behavioral pattern
  • Purpose: Define a family of algorithms, encapsulate each
  • ne, and make them interchangeable. Strategy lets the

algorithm vary independent of clients that use it.

  • Also Known As: Policy
slide-34
SLIDE 34

Motivating Example

34

@Immutable public final class OriginalAIOpponent { private final Level skill; public OriginalAIOpponent(Level skill) { this.skill = skill; } public void repelMove(int posX, int posY) { switch (skill) { case LOUSY: // do something break; case ... } } public void printCoolSlogan() { switch (skill) { case LOUSY: // print something break; case ... } } } public enum Level { LOUSY, STRONG; }

slide-35
SLIDE 35

Motivating Example

  • Options if we need to add a new skill level?
  • add case to Opponent class (easy to forget an occurrence)
  • create subclass of Opponent
  • outsource different behavior

35

slide-36
SLIDE 36

Motivating Example

Define strategy interfaces:

36 public interface RepelStrategy { void repelMove(int posX, int posY); } public interface SloganStrategy { void printCoolSlogan(); }

Sample implementation:

public class LousySloganStrategy implements SloganStrategy { @Override public void printCoolSlogan() { System.out.println("Please don't hurt me!"); } }

slide-37
SLIDE 37

Motivating Example

37 public class AIOpponent { private final RepelStrategy repelStrategy; private final SloganStrategy sloganStrategy; public AIOpponent(RepelStrategy repelStrategy, SloganStrategy sloganStrategy) { this.repelStrategy = repelStrategy; this.sloganStrategy = sloganStrategy; } public void repelMove(int posX, int posY) { repelStrategy.repelMove(posX, posY); } public void printCoolSlogan() { sloganStrategy.printCoolSlogan(); } } AIOpponent o = new AIOpponent( new LousyRepelStrategy(), new LousySloganStrategy());

slide-38
SLIDE 38

Sample Structure

38

printCoolSlogan() <<interface>> SloganStrategy sloganStrategy.printCoolSlogan() printCoolSlogan() LousySloganStrategy ContextInterface() AIOpponent printCoolSlogan() StrongSloganStrategy sloganStrategy

slide-39
SLIDE 39

AlgorithmInterface() Strategy strategy.AlgorithmInterface() AlgorithmInterface() ConcreteStrategyA ContextInterface() Context AlgorithmInterface() ConcreteStrategyB strategy

General Structure

39

  • gets configured with ConcreteStrategy
  • bject
  • may define interface that lets Strategy

access its data implements the algorithm using the Strategy interface interface common to all supported algorithms

slide-40
SLIDE 40

Applicability

Use the Strategy pattern when

  • many related classes differ only in their behavior. Strategies

provide a way to configure a class with one of many behaviors.

  • need of different variants of algorithms.
  • an algorithm uses data that clients shouldn’t know about
  • A class defines many behaviors (use of multiple conditional

statements).

  • Remark: be aware of switch-case-statements, they have a smell

40

slide-41
SLIDE 41

Interactions

  • A context forwards requests from its clients to its strategy.
  • Data handover:
  • A context may hand over all data required by the algorithm

to the strategy method.

  • The context can pass itself as an argument to Strategy

method.

41

slide-42
SLIDE 42

Pros & Cons

  • Pro:
  • Re-usability of algorithms
  • An alternative to sub-classing of the context class
  • Choice of different implementations
  • Elimination of conditional statements
  • clean separation of different algorithms ➔ easier to test
  • Con:
  • Clients must be aware of different strategies
  • Communication overhead
  • Increased number of objects

42

slide-43
SLIDE 43

Real World Examples

  • ThreadPoolExecutor gets RejectedExecutionHandler
  • bject to decide strategy for tasks that cannot be executed

(AbortPolicy, CallerRunsPolicy, DiscardOldestPolicy,

DiscardPolicy)

  • Java Comparator interface
  • Java AWT and Swing, e.g. paintBorder() method of

JComponent

43

slide-44
SLIDE 44

Relationship with other Patterns

  • Flyweight can be used to implement strategy objects.

44