35
OO Methodology Elaboration Iteration 2 - Design Patterns -

OO Methodology Elaboration Iteration 2 - Design Patterns -

Embed Size (px)

Citation preview

Page 1: OO Methodology Elaboration Iteration 2 - Design Patterns -

OO Methodology

Elaboration Iteration 2

- Design Patterns -

Page 2: OO Methodology Elaboration Iteration 2 - Design Patterns -

2

Table of Contents

• Iteration 1– Use-Case Model

– Process Sale Use Case

– Domain Model

– Design Model

• Iteration 2 Requirements

• GRASP: More Patterns for Assigning Responsibilities– Polymorphism

– Pure Fabrication

– Indirection

– Protected Variations

• Designing Use-Case Realizations with GoF Design Patterns

– Adapter

– Factory

– Strategy

– Composite

– Facade

– Observer

Page 3: OO Methodology Elaboration Iteration 2 - Design Patterns -

3

Iteration 2 Requirements

• Support for variations in third-party external services.

• Complex pricing rules

• Pluggable business rules

• A design to refresh a GUI window when the sale total changes

Page 4: OO Methodology Elaboration Iteration 2 - Design Patterns -

4

Refinements of Analysis-oriented Artifacts

• Use-case Model : Use Cases

• Use-case Model : SSDs– new system operations

– remotely communicating with external systems

• Domain Model

• Use-case Model : Operation Contracts

makeCreditPayment(credNum,expiryDate) reply :=

requestApproval(request)postReceivable( receivable

)

«actor»:CreditAuthorization

Service

«actor»:Accounts

enterItem(itemID,quantity)

:NextGenPOSSystem

: Cashier

endSale()

Process SalePay by Credit Scenario

description,total

total withtaxes

* [more items]

makeNewSale()

«actor»:TaxCalculator

taxLineItems :=getTaxes( sale

)

postSale( sale)

Page 5: OO Methodology Elaboration Iteration 2 - Design Patterns -

5

More GRASP Patterns

• Polymorphism

• Indirection

• Pure Fabrication

• Protected Variations

Page 6: OO Methodology Elaboration Iteration 2 - Design Patterns -

6

Design Patterns

• What is Design Pattern– reuses design

– describes a particular recurring design problem that arises in specific design contexts, and presents a well-proven generic scheme for its solution

• Four essential elements– pattern name

– problem

– solution

– consequences

• Gang of Four[GOF95]– creational patterns – 5 patterns

• concern the process of object creation.

– structural patterns – 7 patterns• deal with the composition of classes or objects.

– behavioral patterns – 11 patterns• characterize the ways in which classes or objects interact and

distribute responsibility.

Page 7: OO Methodology Elaboration Iteration 2 - Design Patterns -

7

Design Pattern Space(GoF)

• Scope– Class patterns deal with relationships between classes and

their subclasses• established through inheritance• they are static—fixed at compile-time

– Object patterns deal with object relationships• can be changed at run-time and are more dynamic.• almost all patterns use inheritance to some extent.

Purpose

Creational Structural Behavioral

Scope

Class Factory Method Adapter Interpreter

Template

Method

Object Abstract Factory

Builder

Prototype

Singleton

Adapter

Bridge

Composite

Decorator

Facade

Flyweight

Proxy

Chain of

Responsibility

Command

Iterator

Mediator

Memento

Observer

State

Strategy

Visitor

Page 8: OO Methodology Elaboration Iteration 2 - Design Patterns -

8

Describing Design Patterns(GoF)

• Pattern Name and Classification

• Intent

• Also Known As

• Motivation

• Applicability

• Structure

• Participants

• Collaborations

• Consequences

• Implementation

• Sample Code

• Known Uses

• Related Patterns

Page 9: OO Methodology Elaboration Iteration 2 - Design Patterns -

9

How Design Patterns Solve Design Problems

– Finding Appropriate Objects• most objects come from the analysis model• abstraction • pure fabrication

– Determining Object Granularity• describe specific ways of decomposing an object into smaller

objects

– Specifying Object Interfaces• subtype• dynamic binding• polymorphism

– Specifying Object Implementations• class inheritance• cf. interface inheritance

– Putting Reuse Mechanisms to Work• Inheritance• Composition• Delegation

– Relating Run-Time and Compile-Time Structures– Designing for Change

• indirect creation of objects• avoiding hard-coded requests• limiting platform dependencies• hiding object implementations• avoiding algorithmic dependencies• loose coupling • using composition and delegation over inheritance• etc.

Page 10: OO Methodology Elaboration Iteration 2 - Design Patterns -

10

How to Use a Design Pattern

• Issues– Is there a pattern that addresses a similar problem

– Does the pattern trigger an alternative solution that may be more acceptable

– Is there a simple solution?

– Is the context of the pattern consistent with that of the problem

– Are the consequences of using the pattern acceptable

– Are constraints imposed by the software environment that would conflict with the use of the pattern

• GoF suggest a procedure1. Read the pattern once through for an overview.

2. Go back and study the Structure, Participants, and Collaborations sections.

3. Look at the Sample Code section to see a concrete example of the pattern in code.

4. Choose names for pattern participants that are meaningful in the application context.

5. Define the classes.

6. Define application-specific names for operations in the pattern

7. Implement the operations to carry out the responsibilities and collaborations in the pattern.

Page 11: OO Methodology Elaboration Iteration 2 - Design Patterns -

11

Adapter Pattern

• The NextGen POS – needs to support several kinds of external third-party

services, including tax calculators, credit authorization services

• Adapter pattern– Context/Problem

• How to resolve incompatible interfaces, or provide a stable interface to similar components with different interfaces?

– Solution• Convert the original interface of a component into another

interface, through an intermediate adapter object, that adapts the varying external interfaces

Page 12: OO Methodology Elaboration Iteration 2 - Design Patterns -

12

Adapter Pattern

• NextGen POS system needs to support several kinds of external third-party services, including tax calculators, credit authorization services, inventory systems etc.

TaxMasterAdapter

getTaxes( Sale ) : List of TaxLineItems

GoodAsGoldTaxProAdapter

getTaxes( Sale ) : List of TaxLineItems

<<interface>>ITaxCalculatorAdapter

getTaxes( Sale ) : List of TaxLineItems

Adapters use interfaces andpolymorphism to add a level ofindirection to varying APIs in othercomponents.

SAPAccountingAdapter

postReceivable( CreditPayment )postSale( Sale )...

GreatNorthernAccountingAdapter

postReceivable( CreditPayment )postSale( Sale )...

<<interface>>IAccountingAdapter

postReceivable( CreditPayment )postSale( Sale )...

<<interface>>IInventoryAdapter

...

<<interface>>ICreditAuthorizationService

Adapter

requestApproval(CreditPayment,TerminalID, MerchantID)...

Page 13: OO Methodology Elaboration Iteration 2 - Design Patterns -

13

Adapter Pattern

• Using an Adapter

• Adapter pattern offers Protected Variations from changing external interfaces or third-party packages through the use of an Indirection object that applies interfaces and Polymorphism

:Register : SAPAccountingAdapter

postSale( sale )

makePayment()

the Adapter adapts tointerfaces in othercomponents

«system»: SAP

SOAP overHTTP

xxx

...

IAccountingAdapter

UML notation to indicate somethingimplements a particular interface

Page 14: OO Methodology Elaboration Iteration 2 - Design Patterns -

14

Adapter Pattern

• Class Adapter– uses multiple inheritance to adapt one interface to another

• Object Adapter– uses object composition

Page 15: OO Methodology Elaboration Iteration 2 - Design Patterns -

15

Adapter Pattern

• Example (Drawing Editor)– TextView interface does not match the domain-specific

interface an application requires

Page 16: OO Methodology Elaboration Iteration 2 - Design Patterns -

16

Adapter Pattern

• Sample Code(Drawing Editor)class Shape {

public: Shape(); virtual void BoundingBox( Point& bottomLeft,

Point& topRight ) const; virtual Manipulator* CreateManipulator() const;

}; class TextView {

public: TextView(); void GetOrigin(Coord& x, Coord& y) const; void GetExtent(Coord& width, Coord& height)

const; virtual bool IsEmpty() const;

}; class TextShape : public Shape, private TextView { // class

adaterpublic:

TextShape(); virtual void BoundingBox( Point& bottomLeft,

Point& topRight ) const; virtual bool IsEmpty() const; virtual Manipulator* CreateManipulator() const;

}; void TextShape::BoundingBox ( Point& bottomLeft, Point&

topRight ) const { Coord bottom, left, width, height;

GetOrigin(bottom, left); GetExtent(width, height); bottomLeft = Point(bottom, left); topRight = Point(bottom + height, left + width);

}

Page 17: OO Methodology Elaboration Iteration 2 - Design Patterns -

17

Adapter Pattern

• Sample Code(Drawing Editor)class TextShape : public Shape { // object

adaterpublic:

TextShape(TextView*); virtual void BoundingBox( Point&

bottomLeft, Point& topRight ) const; virtual bool IsEmpty() const; virtual Manipulator*

CreateManipulator() const; private:

TextView* _text; };

TextShape::TextShape (TextView* t) { _text = t; } void TextShape::BoundingBox ( Point& bottomLeft,

Point& topRight ) const { Coord bottom, left, width, height; _text->GetOrigin(bottom, left); _text->GetExtent(width, height); bottomLeft = Point(bottom, left); topRight = Point(bottom + height, left + width);

}

Page 18: OO Methodology Elaboration Iteration 2 - Design Patterns -

18

Factory Pattern

• NextGen POS– who creates the adapters?

– how to determine which class of adapter to create?

– Choosing a domain object to create the adapters does not support the goal of a separation of concerns and lowers its cohesion

• Factory (Concrete Factory)– Context

• Who should be responsible for creating objects when there are special considerations, such as complex creation logic, a desire to separate to creation responsibilities for better cohesion, etc.?

– Solution• Create a Pure Fabrication object called a Factory that handles

the creation

– Advantages• Separate the responsibility of complex creation into cohesive

helper objects

• Hide potentially complex creation logic

• Allow introduction of performance-enhancing memory management strategies such as object caching or recycling

• GoF– Abstract Factory

– Factory Method

Page 19: OO Methodology Elaboration Iteration 2 - Design Patterns -

19

Factory Pattern

• Factory

• Using data-driven design (Protected Variation)

ServicesFactory

accountingAdapter : IAccountingAdapterinventoryAdapter : IInventoryAdaptertaxCalculatorAdapter : ITaxCalculatorAdapter

getAccountingAdapter() : IAccountingAdaptergetInventoryAdapter() : IInventoryAdaptergetTaxCalculatorAdapter() : ITaxCalculatorAdapter...

note that the factory methodsreturn objects typed to aninterface rather than a class, sothat the factory can return anyimplementation of the interface

{ if ( taxCalculatorAdapter == null ) { // a reflective or data-driven approach to finding the right class: read it from an // external property

String className = System.getProperty( "taxcalculator.class.name" ); taxCalculatorAdapter = (ITaxCalculatorAdapter) Class.forName( className ).newInstance();

} return taxCalculatorAdapter;}

Page 20: OO Methodology Elaboration Iteration 2 - Design Patterns -

20

Singleton Pattern

• NextGen POS– who creates the factory itself, and how is it accessed?

– only one instance of the factory is needed

– this factory may need to be called from various places in the code

• Singleton– Context

• Exactly one instance of a class is allowed.

• Objects need a global and single point of access

– Solution• Define a static method of the class that returns the singleton

Page 21: OO Methodology Elaboration Iteration 2 - Design Patterns -

21

Singleton Pattern

• Factory for external services

1ServicesFactory

instance : ServicesFactory

accountingAdapter : IAccountingAdapterinventoryAdapter : IInventoryAdaptertaxCalculatorAdapter : ITaxCalculatorAdapter

getInstance() : ServicesFactory

getAccountingAdapter() : IAccountingAdaptergetInventoryAdapter() : IInventoryAdaptergetTaxCalculatorAdapter() : ITaxCalculatorAdapter...

singletonstatic attribute

singletonstaticmethod

{// static methodpublic static synchronized ServicesFactory getInstance(){if ( instance == null ) instance := new ServicesFactory()return instance}}

UML notation: in aclass box, anunderlined attribute ormethod indicates astatic (class level)member, rather thanan instance member

UML notation: this '1' can optionally be used toindicate that only one instance will be created (asingleton)

Page 22: OO Methodology Elaboration Iteration 2 - Design Patterns -

22

Singleton Pattern

• Visibility to the singleton (global)public class Register

{

public void initialize() {

...

accountingAdapter = ServiceFactory.getInstance().

getAccountingAdapter();

...

}

...

}

• UML Shorthand

:Register<<singleton>>

:ServicesFactory

aa := getAccountingAdapter()initialize()

...

a UML stereotype can indicate thatvisibility to this instance wasachieved via the Singleton pattern

Page 23: OO Methodology Elaboration Iteration 2 - Design Patterns -

23

Adapter, Factory, Singleton

:Register accountingAdapter:SAPAccountingAdapter

postSale( sale )

makePayment()

«system»: SAP

SOAP overHTTP

xxx

IAccountingAdapter

:Register

<<singleton>>:ServicesFactory

accountingAdapter := getAccountingAdapter()

:Store

create()create()

[ instance == null ]create() : SAPAccounting

Adapter

IAccountingAdapter

: Paymentcreate(cashTendered)

Page 24: OO Methodology Elaboration Iteration 2 - Design Patterns -

24

Abstract Factory

• Context– when a system should be configured with one of multiple

families of products

– a family of related product objects is designed to be used together

– how can these families of products be created

• Solution– provide an interface for creating families of related or

dependent objects without specifying their concrete classes

• Structure

Page 25: OO Methodology Elaboration Iteration 2 - Design Patterns -

25

Abstract Factory

• Example : User Interface Toolkit

• Consequences– It isolates concrete classes

– It makes exchanging product families easy.

– It promotes consistency among products

– Supporting new kinds of products is difficult

Page 26: OO Methodology Elaboration Iteration 2 - Design Patterns -

26

Abstract Factory

• Sample : Maze Game

class MapSite { public: virtual void Enter() = 0; };

class Room : public MapSite { public: Room(int roomNo); MapSite* GetSide(Direction) const; void SetSide(Direction, MapSite*); virtual void Enter(); private: MapSite* _sides[4]; int _roomNumber; };

Page 27: OO Methodology Elaboration Iteration 2 - Design Patterns -

27

Abstract Factory

• Sample : Maze Gameclass Wall : public MapSite { public: Wall(); virtual void Enter(); }; class Door : public MapSite { public: Door(Room* = 0, Room* = 0); virtual void Enter(); Room* OtherSideFrom(Room*); private: Room* _room1; Room* _room2; bool _isOpen; }; class Maze { public: Maze(); void AddRoom(Room*); Room* RoomNo(int) const; private: // ... };

Page 28: OO Methodology Elaboration Iteration 2 - Design Patterns -

28

Abstract Factory

• Sample : Maze Game

– In another class MazeGame, a Maze is created

Maze* MazeGame::CreateMaze () { Maze* aMaze = new Maze; Room* r1 = new Room(1);

Room* r2 = new Room(2); Door* theDoor = new Door(r1, r2); aMaze->AddRoom(r1); aMaze->AddRoom(r2); r1->SetSide(North, new Wall); r1->SetSide(East, theDoor); r1->SetSide(South, new Wall); r1->SetSide(West, new Wall); r2->SetSide(North, new Wall); r2->SetSide(East, new Wall); r2->SetSide(South, new Wall); r2->SetSide(West, theDoor); return aMaze;

}

– hard-coded– how can you change CreateMaze easily so that it

creates another family of components of maze for example, enchanted maze

Page 29: OO Methodology Elaboration Iteration 2 - Design Patterns -

29

Abstract Factory

• Alternative: Abstract Factory

MazeFactory

EnchantedMazeFactory

BombedMazeFactory

Maze

EnchantedMaze

BombedMaze

Room

EnchantedRoom

BombedRoom

Wall

EnchantedWall

BombedWall

MazeGame

Page 30: OO Methodology Elaboration Iteration 2 - Design Patterns -

30

Abstract Factory

• Alternative: Abstract Factory– MazeFactory classclass MazeFactory {

public: MazeFactory(); virtual Maze* MakeMaze() const { return new Maze; } virtual Wall* MakeWall() const { return new Wall; } virtual Room* MakeRoom(int n) const

{ return new Room(n); } virtual Door* MakeDoor(Room* r1, Room* r2) const { return new Door(r1, r2); }

};

– creating a maze using an abstract factoryMaze* MazeGame::CreateMaze (MazeFactory&

factory) { Maze* aMaze = factory.MakeMaze();

Room* r1 = factory.MakeRoom(1); Room* r2 = factory.MakeRoom(2); Door* aDoor = factory.MakeDoor(r1, r2); aMaze->AddRoom(r1); aMaze->AddRoom(r2); r1->SetSide(North, factory.MakeWall()); r1->SetSide(East, aDoor); r1->SetSide(South, factory.MakeWall());

....r2->SetSide(West, aDoor); return aMaze;

}

Page 31: OO Methodology Elaboration Iteration 2 - Design Patterns -

31

Abstract Factory

• Alternative: Abstract Factory

– enchanted maze factory

class EnchantedMazeFactory : public MazeFactory { public:

EnchantedMazeFactory(); virtual Room* MakeRoom(int n) const { return new EnchantedRoom(n,

CastSpell()); } virtual Door* MakeDoor(Room* r1,

Room* r2) const { return new DoorNeedingSpell(r1, r2); }

protected: Spell* CastSpell() const;

};

– create a bombed maze

MazeGame game; BombedMazeFactory factory; game.CreateMaze(factory);

Page 32: OO Methodology Elaboration Iteration 2 - Design Patterns -

32

Factory Method

• Intent– Define an interface for creating an object, but let subclasses

decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.

• Motivation– Consider a framework for applications that can present

multiple documents to the user.

Page 33: OO Methodology Elaboration Iteration 2 - Design Patterns -

33

Factory Method

• Applicability– a class can't anticipate the class of objects it must create.

– a class wants its subclasses to specify the objects it creates.

• Structure

• Consequences– eliminates the need to bind application-specific classes

– provides a hooks for subclasses

Page 34: OO Methodology Elaboration Iteration 2 - Design Patterns -

34

Factory Method

• Sample Codeclass MazeGame { public:

Maze* CreateMaze(); // factory methods: virtual Maze* MakeMaze() const { return new Maze; } virtual Room* MakeRoom(int n) const

{ return new Room(n); } virtual Wall* MakeWall() const { return new Wall; } virtual Door* MakeDoor(Room* r1, Room* r2) const { return new Door(r1, r2); }

}; Maze* MazeGame::CreateMaze () {

Maze* aMaze = MakeMaze(); Room* r1 = MakeRoom(1); // using factory methodsRoom* r2 = MakeRoom(2); Door* theDoor = MakeDoor(r1, r2); aMaze->AddRoom(r1); aMaze->AddRoom(r2); r1->SetSide(North, MakeWall()); r1->SetSide(East, theDoor); r1->SetSide(South, MakeWall());

....return aMaze; }

Page 35: OO Methodology Elaboration Iteration 2 - Design Patterns -

35

Factory Method

• Sample Code

– EnchantedMazeGame subclass refines factory methods

class EnchantedMazeGame : public MazeGame { public:

EnchantedMazeGame(); virtual Room* MakeRoom(int n) const

{ return new EnchantedRoom(n, CastSpell()); } virtual Door* MakeDoor(Room* r1, Room* r2) const { return new DoorNeedingSpell(r1, r2); }

protected: Spell* CastSpell() const;

};

– creating a maze

EnchantedMazeGame game;game.CreateMaze();