Software architecture
Download
1 / 82

Software Architecture - PowerPoint PPT Presentation


  • 90 Views
  • Uploaded on

Software Architecture. Bertrand Meyer. Lecture 6: More patterns: Visitor, Strategy, Chain, State, Command. Command. 2. Purpose Way to implement an undo-redo mechanism, e.g. in text editors. [OOSC, p 285-290]

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

PowerPoint Slideshow about 'Software Architecture' - luana


An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
Software architecture

Software Architecture

Bertrand Meyer

Lecture 6: More patterns: Visitor, Strategy, Chain, State, Command



Command pattern intent

Purpose

Way to implement an undo-redo mechanism, e.g. in text editors. [OOSC, p 285-290]

”Way to encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations.”

[Gamma et al., p 233]

Application example

EiffelStudio

Command pattern - Intent

3


The problem
The problem

Enabling users of an interactive system to cancel the effect of the last command.

Often implemented as “Control-Z”.

Should support multi-level undo-redo, with no limitation other than a possible maximum set by the user

A good review of O-O techniques


Working example text editor
Working example: text editor

Notion of “current line”. Assume commands such as:

  • Insert line after current position

  • Insert line before current position

  • Delete current line

  • Replace current line

  • Swap current line with next if any

  • ...

    This is a line-oriented view for simplicity, but the discussion applies to more sophisticated views


Underlying class from business model
Underlying class (from “business model”)

class EDIT_CONTROLLER feature

text: LINKED_LIST [STRING]

remove

-- Remove line at current position.

require

notoff

do

text.remove

end

put_right(line: STRING)

-- Insert line after current position.

require

notafter

do

text.put_right(line)

end

...

end


Key step in devising a software architecture
Key step in devising a software architecture

Here:

The notion of “command”

Finding the right abstractions

(Interesting object types)


Keeping the history of the session
Keeping the history of the session

The history list:

Insert

Insert

Remove

Insert

Swap

Oldest

Most recent

history: LINKED_LIST [COMMAND]


What s a command object
What’s a “command” object?

An instance of COMMAND includes information about one execution of a command by the user, sufficient to:

  • Execute the command

  • Cancel the command if requested later

  • For example, in a delete command object, we need:

  • The position of the line being deleted

  • The content of that line


General notion of command
General notion of command

feature

deferred

class

COMMAND

done: BOOLEAN-- Has this command been executed?

execute-- Carry out one execution of this command.

deferred

: done

end

ensurealready:done

undo

-- Cancel an earlier execution of this command.

requirealready:done

deferredend

end


Command class hierarchy
Command class hierarchy

*

execute*

undo*

*

COMMAND

deferred

+

effective

+

+

DELETION

INSERTION

execute+undo+index

...

execute+undo+lineindex

...


A command class sketch no contracts
A command class (sketch, no contracts)

class DELETION inherit COMMAND feature

controller: EDIT_CONTROLLER

-- Access to business model

line: STRING

-- Line being deleted

index: INTEGER

-- Position of line being deleted

execute

-- Remove current line and remember it.

do

line:=controller.item;index:=controller.index

controller.remove;done:=True

end

undo

-- Re-insert previously removed line.

do

controller.go_ith(index)

controller.put_left(line)

end

end


Executing a user command
Executing a user command

decode_user_request

if “Request normal command” then

“Create command object c corresponding to user request”

history.extend(c)

c.execute

elseif “Request UNDO” then

if not history.beforethen -- Ignore excessive requests

history.item.undo

history.back

end

elseif“Request REDO” then

if not history.is_lastthen -- Ignore excessive requests

history.forth

history.item.execute

end

end

Remove

Insert

Insert

Insert

item


Command pattern overall architecture
Command pattern: overall architecture

*

COMMAND

commands

history

APPLICATION

HISTORY

execute*

undo*

redo*

execute

can_undo, can_redo

undo, redo

undo_all, redo_all

extend

+

COMMAND_2

+

COMMAND_1

execute+

undo+

redo+

execute+

undo+

redo+

14


The undo redo pattern
The undo-redo pattern

Has been extensively used

Fairly easy to implement

Details must be handled carefully (e.g. some commands may not be undoable)

Elegant use of O-O techniques

Disadvantage: explosion of small classes

In Java, can use “inner” classes.


Using agents
Using agents

For each user command, have two routines:

  • The routine to do it

  • The routine to undo it!


The history list using agents
The history list using agents

The history list simply becomes a list of agents pairs:

history: LINKED_LIST [TUPLE

[PROCEDURE [ANY, TUPLE],

PROCEDURE [ANY, TUPLE]]

Basic scheme remains the same, but no need for command objects any more; the history list simply contains agents.

Insert

Insert

Remove

Insert

Swap

De-insert

De-insert

Re-insert

De-insert

Swap


Executing a user command before
Executing a user command (before)

decode_user_request

if “Request is normal command” then

“Create command object c corresponding to user request”

history.extend(c)

c.execute

elseif “Request is UNDO” then

if not history.beforethen --Ignoreexcessiverequests

history.item.undo

history.back

end

elseif“Request is REDO” then

if not history.is_lastthen --Ignoreexcessiverequests

history.forth

history.item.execute

end

end

Remove

Insert

Insert

Insert

item


Executing a user command now
Executing a user command (now)

“Decode user_request giving two agentsdo_itand undo_it”

if “Request is normal command” then

history.extend([do_it, undo_it])

do_it.call([])

elseif “Request is UNDO” then

if not history.beforethen

history.item.item(2) .call ([])

history.back

end

elseif“Request is REDO” then

if not history.is_lastthen

history.forth

history.item.item(1) .call ([])end

end

Insert

Insert

Remove

Swap

De-insert

De-insert

Re-insert

Swap


Command consequences

Command decouples the object that invokes the operation from the one that knows how to perform it.

Commands are first-class objects. They can be manipulated and extended like any other object.

You can assemble commands into a composite command.

It's easy to add new Commands, because you don't have to change existing classes.

Command - Consequences

20


Command participants

Command the one that knows how to perform it.

declares an interface for executing an operation.

Concrete command

defines a binding between a Receiver object and an action.

implements Execute by invoking the corresponding operation(s) on Receiver.

Client

creates a ConcreteCommand object and sets its receiver.

Invoker

asks the command to carry out the request.

Receiver

knows how to perform the operations associated with carrying out a request. Any class may serve as a Receiver.

Command - Participants

21


Some design patterns
Some design patterns the one that knows how to perform it.

Creational

  • Abstract Factory

  • Builder

  • Factory Method

  • Prototype

  • Singleton

    Structural

  • Adapter

  • Bridge

  • Composite

  • Decorator

  • Façade

  • Flyweight

  • Proxy

Behavioral

  • Chain of Responsibility

  • Command (undo/redo)

  • Interpreter

  • Iterator

  • Mediator

  • Memento

  • Observer

  • State

  • Strategy

  • Template Method

  • Visitor


Visitor

Visitor the one that knows how to perform it.

23


Visitor intent

“Represents an the one that knows how to perform it.operation to be performed on the elements of an object structure. Visitor lets you define a new operation without changing the classes of the elements on which it operates.”

[Gamma et al., p 331]

Static class hierarchy

Need to perform traversal operations on corresponding data structures

Avoid changing the original class structure

Visitor - Intent

24


Visitor application example

Set of classes to deal with an Eiffel or Java program (in EiffelStudio, Eclipse ...)

Or: Set of classes to deal with XML documents (XML_NODE, XML_DOCUMENT, XML_ELEMENT, XML_ATTRIBUTE, XML_CONTENT…)

One parser (or several: keep comments or not…)

Many formatters:

Pretty-print

Compress

Convert to different encoding

Generate documentation

Refactor

Visitor application example

25


Inheritance hierarchy
Inheritance hierarchy EiffelStudio, Eclipse ...)

center *

display*

*

rotate*

FIGURE

*

*

OPEN_ FIGURE

perimeter*

CLOSED_ FIGURE

perimeter +

perimeter +

+

SEGMENT

POLYLINE

+

POLYGON

ELLIPSE

...

...

side1

RECTANGLE

side2

TRIANGLE

diagonal

perimeter ++

* deferred

+ effective

++ redefined

perimeter ++

CIRCLE

SQUARE

perimeter ++


Polymorphic data structures
Polymorphic EiffelStudio, Eclipse ...)data structures

figs: LIST [FIGURE]

(ELLIPSE)

(POLYGON)

(CIRCLE)

(POLYGON)

(CIRCLE)

from

figsstart

until

figsafter

loop

figsitemdisplay

figsforth

end


The dirty secret of o o architecture
The dirty secret of O-O architecture EiffelStudio, Eclipse ...)

Is it easy to add types (e.g.LOZENGE) to existing operations

center *

display*

*

rotate*

FIGURE

*

*

OPEN_ FIGURE

perimeter *

CLOSED_ FIGURE

perimeter +

perimeter +

+

SEGMENT

POLYLINE

+

POLYGON

ELLIPSE

...

perimeter ++

...

side1

RECTANGLE

side2

TRIANGLE

diagonal

perimeter ++

CIRCLE

SQUARE

perimeter ++

What about the reverse: adding an operation to existing types?


Vehicle example
Vehicle example EiffelStudio, Eclipse ...)

*

VEHICLE

+

BUS

+

TAXI

We want to add external functionality, for example:

  • Maintenance

  • Schedule a vehicle for a particular day

29


Vehicle operations
Vehicle operations EiffelStudio, Eclipse ...)

Why is this approach bad ?

schedule (v: VEHICLE, d: DAY)

-- Set up schedule of v for d.

require

exists:v /=Void

do

if attached {BUS}v as b then

bschedule (d)

end

if attached {TAXI}v as t then

tput_on_call(d)

end

... Other cases ...

end

end

maintain (v: VEHICLE)

-- Perform maintenance on v.

require

exists:v /=Void

do

if attached {BUS}v as b then

bsend_to_depot

end

if attached {TAXI}v as t then

tsend_to_garage (Next_monday)

end

... Other cases ...

end

end

30


The original view
The original view EiffelStudio, Eclipse ...)

CLIENT

visit

T_TARGET

Client (calls)


Visitor participants

Target EiffelStudio, Eclipse ...) classes

Example: BUS, TAXI

Client classes

Application classes that need to perform

operations on target objects

Visitor classes

Written only to smooth out the collaboration

between the other two

Visitor participants

32


Visitor participants1

Visitor EiffelStudio, Eclipse ...)

General notion of visitor

Concrete visitor

Specific visit operation, applicable to all target elements

Target

General notion of visitable element

Concrete target

Specific visitable element

Visitor participants

33


The original view1
The original view EiffelStudio, Eclipse ...)

CLIENT

visit

T_TARGET

Client (calls)


The visitor ballet
The visitor ballet EiffelStudio, Eclipse ...)

CLIENT

taccept (v)

v

T_TARGET

V_VISITOR

vT_visit(Current)

Client(knows about)

Client (calls)


Visitor class hierarchies
Visitor class hierarchies EiffelStudio, Eclipse ...)

accept*

vT_visit(Current)

*

VISITOR

*

VEHICLE

visit_bus*

visit_tram*

+

BUS

+

TAXI

+

MAINTENANCE_VISITOR

+

SCHEDULE_VISITOR

accept+

accept+

visit_taxi+

visit_taxi+

visit_bus+

visit_bus+

Target classes

Visitor classes

36


The maintenance visitor

class EiffelStudio, Eclipse ...)MAINTENANCE_VISITOR inherit

VISITOR

feature-- Basic operations

visit_taxi(t: TAXI)

-- Perform maintenance operations ont.

do

tsend_to_garage (Next_monday)

end

visit_bus(b:BUS)

-- Perform maintenance operations on b.

do

bsend_to_depot

end

end

The maintenance visitor

37


The scheduling visitor

class EiffelStudio, Eclipse ...)MAINTENANCE_VISITOR inherit

VISITOR

feature-- Basic operations

visit_taxi(t: TAXI)

-- Perform scheduling operations ont.

do

...

end

visit_bus(b:BUS)

-- Perform scheduling operations on b.

do

...

end

end

The scheduling visitor

38


Changes to the target classes

class EiffelStudio, Eclipse ...)BUS inherit

VEHICLE

feature

accept (v: VISITOR)

-- Apply bus visit to v.

do

v.visit_bus (Current)‏

end

end

Changes to the target classes

deferred class

VEHICLE

feature

... Normal VEHICLE features ...

accept (v: VISITOR)

-- Apply vehicle visit to v.

deferred

end

end

class TAXI inherit

VEHICLE

feature

accept (v: VISITOR)

-- Apply taxi visit to v.

do

v.visit_taxi (Current)‏

end

end

39


The full picture
The full picture EiffelStudio, Eclipse ...)

vT_visit(Current)

*

VISITOR

accept*

*

VEHICLE

visit_bus*

visit_tram*

Target classes

Visitor classes

vT_visit(Current)

+

MAINT_VISITOR

+

SCHEDULE_VISITOR

+

TAXI

+

V_VISITOR

+

T

+

BUS

accept+

accept+

accept+

visit_taxi+

visit_taxi+

visit_taxi+

visit_bus+

visit_bus+

visit_bus+

v

taccept (v)

Example client calls:

bus21.accept (maint_visitor)

fleet.item.accept (maint_visitor)

CLIENT

40


Visitor consequences

Makes adding new operations easy EiffelStudio, Eclipse ...)

Gathers related operations, separates unrelated ones

Avoids assignment attempts

Better type checking

Adding new concrete element is hard

Visitor - Consequences

Does the visitor pattern observe the Open-Closed Principle ?

41


Visitor vs dynamic binding

Dynamic binding: EiffelStudio, Eclipse ...)

Easy to add types

Hard to add operations

Visitor:

Easy to add operations

Hard to add types

Visitor vs dynamic binding

42


The visitor pattern
The visitor pattern EiffelStudio, Eclipse ...)

vT_visit(Current)

*

VISITOR

accept*

*

VEHICLE

visit_bus*

visit_tram*

Target classes

Visitor classes

vT_visit(Current)

+

MAINT_VISITOR

+

SCHEDULE_VISITOR

+

TAXI

+

V_VISITOR

+

T

+

BUS

accept+

accept+

accept+

visit_taxi+

visit_taxi+

visit_taxi+

visit_bus+

visit_bus+

visit_bus+

v

taccept (v)

Example client calls:

bus21.accept (maint_visitor)

fleet.item.accept (maint_visitor)

CLIENT

43


The visitor library

One generic class EiffelStudio, Eclipse ...)VISITOR [G]

e.g. maintenance_visitor:VISITOR [VEHICLE]

Actions represented as agents

actions:LIST [PROCEDURE [ANY, TUPLE [G]]]

No need for accept features

visitdetermines the action applicable to the given element

For efficiency

Topological sort of actions (by conformance)

Cache (to avoid useless linear traversals)

The Visitor Library

44


Visitor library interface 1 2

class EiffelStudio, Eclipse ...)

VISITOR[G]

create

make

feature{NONE} -- Initialization

make

--Initializeactions.

feature--Visitor

visit(an_element: G)

--Selectactionapplicabletoan_element.

require

an_element_not_void: an_element/= Void

feature--Access

actions: LIST[PROCEDURE[ANY, TUPLE[G]]]

--Actions tobeperformeddependingontheelement

Visitor Library interface (1/2)

45


Visitor library interface 2 2

feature EiffelStudio, Eclipse ...)-- Element change

extend(action: PROCEDURE[ANY, TUPLE[G]])

--Extendactionswithaction.

require

action_not_void: action/= Void

ensure

one_more: actions.count= oldactions.count+ 1

inserted: actions.last= action

append(some_actions: ARRAY[PROCEDURE[ANY, TUPLE[G]]])

--Appendactionsinsome_actions

--totheendoftheactionslist.

require

some_actions_not_void: some_actions/= Void

no_void_action: notsome_actions.has(Void)

invariant

actions_not_void: actions/= Void

no_void_action: notactions.has(Void)

end

Visitor Library interface (2/2)

46


Using the visitor library

maintenance_visitor EiffelStudio, Eclipse ...): VISITOR[BORROWABLE]

createmaintenance_visitor.make

maintenance_visitor.append([

agentmaintain_taxi,

agentmaintain_trolley

])

maintain_taxi(a_taxi: taxi)...

maintain_trolley(a_trolley: TROLLEY)...

Using the Visitor Library

,

agent maintain_tram

maintain_tram(a_tram: BUS)...

47


Topological sorting of agents 1 2
Topological sorting of agents (1/2) EiffelStudio, Eclipse ...)

*

BORROWABLE

*

BUS

*

VEHICLE

+

TROLLEY

+

TRAM

48


Topological sorting of agents 2 2

schedule_visitor.extend EiffelStudio, Eclipse ...)(agentschedule_taxi)

Topological sorting of agents (2/2)

schedule_visitor.extend(agentschedule_bus)

schedule_visitor.extend(agentschedule_vehicle)

schedule_visitor.extend(agentschedule_tram)

schedule_visitor.extend(agentschedule_trolley)

For agent schedule_a(a: A) and schedule_b(b: B), if A conforms to B, then position of schedule_ais before position of schedule_bin the agent list

schedule_taxi

schedule_

bus

schedule_

vehicle

schedule_

vedio_tram

schedule_

tram

1 5 2 4 3

schedule_visitor.visit(a_bus)

49


Strategy
Strategy EiffelStudio, Eclipse ...)

50


Strategy intent

Purpose EiffelStudio, Eclipse ...)

“Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it”.

[Gamma et al., p 315]

Example application

selecting a sorting algorithm on-the-fly

Strategy - Intent

51


Life without strategy a sorting example

feature EiffelStudio, Eclipse ...)-- Sorting

sort (il: LIST [INTEGER ];st: INTEGER)

--Sortilusingalgorithmindicatedbyst.

require

il/=Void

is_strategy_valid (st)

do

inspect

st

when binary then …

when quickthen …

when bubblethen …

else …

end

ensure

a_list_sorted: …

end

Life without strategy: a sorting example

What if a new algorithm is needed ?

52


Strategy pattern overall architecture

+ EiffelStudio, Eclipse ...)

STRATEGY_A

Strategy pattern: overall architecture

strategy

*

STRATEGY

+

CONTEXT

do_something*

do_something

+

STRATEGY_B

+

STRATEGY_C

do_something+

do_something+

do_something+

53


Class strategy

deferred class EiffelStudio, Eclipse ...)

STRATEGY

feature -- Basic operation

do_something

-- Do something (perform some algorithm).

deferred

end

end

Class STRATEGY

54


Class context 1 3

class EiffelStudio, Eclipse ...)

CONTEXT

create

make

feature{NONE} -- Initialization

make(s: likestrategy)

--Makes the new strategy.

require

s/= Void

do

strategy:=s

ensure

strategy_set: strategy= s

end

Class CONTEXT (1/3)

55


Class context 2 3

feature EiffelStudio, Eclipse ...)– Basic operations

do_something

-- Do something (call algorithm cooresponding to strategy).

do

strategy.do_something

end

set_strategy(s: likestrategy)

-- Set strategytos.

require

s/=Void

do

strategy := s

ensure

strategy=s

end

Class CONTEXT (2/3)

56


Software architecture

Class CONTEXT (3/3) EiffelStudio, Eclipse ...)

feature{NONE} – Implementation

strategy: STRATEGY

-- Strategy to be used

invariant

strategy_not_void: strategy/= Void

end

57


Using strategy pattern

sorter_context EiffelStudio, Eclipse ...): SORTER_CONTEXT

bubble_strategy: BUBBLE_STRATEGY

quick_strategy: QUICK_STRATEGY

createsorter_context.make(bubble_strategy)

sorter_context.sort(a_list)

sorter_context.set_strategy(quick_strategy)

sorter_context.sort(a_list)

Using strategy pattern

Now, what if a new algorithm is needed ?

hash_strategy: HASH_STRATEGY

sorter_context.set_strategy(hash_strategy)

sorter_context.sort(a_list)

58


Strategy consequences
Strategy - Consequences EiffelStudio, Eclipse ...)

  • Families of related algorithms

  • An alternative to subclassing

  • Eliminate conditional statements

  • A choice of implementations

  • Clients must be aware of different Strategies

  • Communication overhead between Strategy and Context

  • Increased number of objects

59


Strategy participants

Strategy EiffelStudio, Eclipse ...)

declares an interface common to all supported algorithms.

Concrete strategy

implements the algorithm using the Strategy interface.

Context

is configured with a concrete strategy object.

maintains a reference to a strategy object.

Strategy - Participants

60


Chain of responsibility
Chain of responsibility EiffelStudio, Eclipse ...)

61


Chain of responsibility intent
Chain of responsibility - Intent EiffelStudio, Eclipse ...)

Purpose

“Avoid[s] coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. [It] chain[s] the receiving objects and pass[es] the request along the chain until an object handles it.”

[Gamma et al., p 223]

Example application

A GUI event is passed from level to level (such as from button to dialog and then to application)

62


Chain of responsibility overall architecture
Chain of responsibility: overall architecture EiffelStudio, Eclipse ...)

*

HANDLER[G]

APPLICATION

next

handle

can_handle*

do_handle*

handled

set_next

+

INTERMEDIATE_ HANDLER[G]

+

FINAL_HANDLER[G]

can_handle+

do_handle+

can_handle+

do_handle+

63


Class handler g 1 3

deferred class EiffelStudio, Eclipse ...)

HANDLER[G]

create default_create,make

feature{NONE } -- Initialization

make(n : likenext)

-- Set nextto n.

do

next:= n

ensure

next_set: next= n

end

feature-- Access

next: HANDLER[G]

-- Successor in the chain of responsibility

feature-- Status report

can_handle(r: G): BOOLEANdeferred end

-- Can this handler handle r?

handled: BOOLEAN

-- Has request been handled?

Class HANDLER [G] (1/3)

64


Class handler g 2 3

feature EiffelStudio, Eclipse ...)-- Basic operations

handle(r: G)

--Handle rifcan_handleotherwiseforwardittonext.

--Ifnonext,sethandledtoFalse.

do

ifcan_handle(r) then

do_handle(r) ; handled:= True

else

ifnext/= Voidthen

next.handle(r) ; handled:= next.handled

else

handled:= False

end

end

ensure

can_handle(r) implieshandled

(notcan_handle(r) and next/= Void) implies handled= next.handled

(notcan_handle(r) and next= Void) implies nothandled

end

Class HANDLER [G] (2/3)

65


Class handler g 3 3

feature EiffelStudio, Eclipse ...)-- Element change

set_next(n: likenext)

--Set nextto n.

do

next:= n

ensure

next_set: next= n

end

feature{NONE} – Implementation

do_handle(r: G)

--Handle r.

require

can_handle: can_handle(r)

deferred

end

end

Class HANDLER [G] (3/3)

66


Using chain of responsibility

btn_help_provider EiffelStudio, Eclipse ...): BUTTON_HELP_HANDLER [CLICK_REQUEST]

dialog_help_provider: DIALOG_HELP_HANDLER [CLICK_REQUEST]

win_help_provider: WINDOW_HELP_HANDLER [CLICK_REQUEST]

createwin_help_provider

createdialog_help_provider.make (win_help_provider)

createbtn_help_provider.make(dialog_help_provider)

btn_help_provider.handle (a_click_request)

Using chain of responsibility

btn_helper_provider

dialog_help_provider

win_help_provider

67


Chain of responsibility consequences

Reduced coupling EiffelStudio, Eclipse ...)

An object only has to know that a request will be handled "appropriately“. Both the receiver and the sender have no explicit knowledge of each other

Added flexibility in assigning responsibilities to objects

Ability to add or change responsibilities for handling a request by adding to or otherwise changing the chain at run-time

Receipt isn't guaranteed

therequestcanfallofftheend of thechainwithouteverbeinghandled

Chain of responsibility - Consequences

68


Chain of responsibility participants

Handler EiffelStudio, Eclipse ...)

defines an interface for handling requests.

(optional) implements the successor link.

Concrete handler

handles requests it is responsible for.

can access its successor.

if the Concrete handler can handle the request, it does so; otherwise it forwards the request to its successor.

Client

initiates the request to a Concrete handler object on the chain.

Chain of responsibility - Participants

69


State
State EiffelStudio, Eclipse ...)

70


State intent

Purpose EiffelStudio, Eclipse ...)

“Allowsan object to alter its behavior when its internal state changes. The object will appear to change its class”.

[Gamma et al., p 305]

Application example:

add attributes without changing class

state machine simulation

State - Intent

71


State overall architecture

+ EiffelStudio, Eclipse ...)

INITIAL_STATE

State: overall architecture

context

*

STATE

+

CONTEXT

do_something*

state

do_something

+

FINAL_STATE

+

INTERMEDIATE

_STATE

do_something+

do_something+

do_something+

What’s the difference between state and strategy ?

72


Class context

class EiffelStudio, Eclipse ...)

CONTEXT

feature– Basic operations

do_something

-- Do something depending on the state.

do

state.do_something

end

feature {NONE} -- Implementation

state:STATE

-- Current state

some_other_state:STATE

-- Other managed state

end

Class CONTEXT

73


Class state

deferred class EiffelStudio, Eclipse ...)

STATE

feature– Basic operations

do_something

-- Do something

deferred

end

feature-- Access

context:CONTEXT

-- Context where current is used

end

Class STATE

74


Class concrete state

class EiffelStudio, Eclipse ...)

CONCRETE_STATE

inherit

STATE

feature– Basic operations

do_something

-- Do something

do

context.set_state (context.some_other_state)

end

end

Class CONCRETE_STATE

75


Using state 1 5 class website context

class EiffelStudio, Eclipse ...)WEBSITE_CONTEXT

feature– Basic operations

login

-- Login.

do

state.login

end

logout

-- Logout.

do

state.logout

end

visit_url(a_url:URL)

-- Visit URLa_url.

do

state.visit(a_url)

end

Using state (1/5): Class WEBSITE_CONTEXT

76


Using state 2 5 class website context

feature EiffelStudio, Eclipse ...){NONE} -- Implementation

state: ACCOUNT_STATE

-- Current state

feature {ACCOUNT_STATE} -- Implementation

loggedin_state,

loggedout_state:likestate

-- States

set_state(a_state:likestate)

-- Logout state

require

a_state_not_void:a_state/=Void

do

state:=a_state

ensure

state_set:state=a_state

end

end

Using state (2/5): Class WEBSITE_CONTEXT

77


Using state 3 5 class account state

deferred class EiffelStudio, Eclipse ...)ACCOUNT_STATE

feature– Basic operations

logindeferred end

logout deferred end

visit_url(a_url:URL)

require

a_url_not_void:a_url/=Void

deferred

end

feature{NONE} – Implementation

context:WEBSITE_CONTEXT

-- Context

end

Using state (3/5): Class ACCOUNT_STATE

78


Using state 4 5 class login state

class EiffelStudio, Eclipse ...)

LOGGEDIN_STATE

inherit

ACCOUNT_STATE

feature– Basic operations

logindoend

logout

do

context.set_state(context.loggedout_state)

end

visit_url(a_url:URL)

do

-- Go to URL.

end

end

Using state (4/5): Class LOGIN_STATE

79


Using state 5 5 class logout state

class EiffelStudio, Eclipse ...)

LOGGEDOUT_STATE

inherit

ACCOUNT_STATE

feature– Basic operations

login

do

context.set_state(context.loggedin_state)

end

logoutdoend

visit_url(a_url:URL)

do

-- Disallow visit.

end

end

Using state (5/5): Class LOGOUT_STATE

80


State consequences

It localizes state-specific behavior and partitions behavior for different states

It makes state transitions explicit

State objects can be shared

State - Consequences

81


State participants

Context for different states

defines the interface of interest to clients.

maintains an instance of a Concrete state subclass that defines the current state.

State

defines an interface for encapsulating the behavior associated with a particular state of the Context.

Concrete state

each subclass implements a behavior associated with a state of the Context

State - Participants

82