1 Design Patterns Dennis Mancl Lucent Technologies – Bell Labs April 6, 2005.

39
1 Design Patterns Dennis Mancl Lucent Technologies – Bell Labs April 6, 2005
  • date post

    22-Dec-2015
  • Category

    Documents

  • view

    214
  • download

    0

Transcript of 1 Design Patterns Dennis Mancl Lucent Technologies – Bell Labs April 6, 2005.

1

Design Patterns

Dennis Mancl

Lucent Technologies – Bell LabsApril 6, 2005

2

Design Patterns Outline

What is a pattern? The Design Patterns Book One example pattern: Singleton Patterns versus Idioms

Complex algorithms and the Strategy patternCreating new objects: Factories Factory method Abstract factory

Wrapping with Facade objectsRemote access with ProxyStructuring objects with CompositeAdding behavior with Decorator

3

What is a pattern?

A pattern is a solution to a problem in a contextThe problem and context come from some domain (software development, project management, …) The problem and context

contain some “unresolved forces” that need to be addressed.

The solution is a proposed way to resolve the problem

Name: Information Expert

Problem: How to decide which class or object to assign responsibilities to?

Context: A responsibility usually requires some information or data for its fulfillment – information about other objects, an object’s own state, the world around an object, and so on.

Solution: Assign a responsibility to the class that has the information needed to fulfill it. (from Applying UML and Patterns, third edition, Craig Larman)

4

What is a pattern?

Patterns are used to capture knowledge and experience – for example, what to think about when making design choices

Not a cookbook

Each pattern might trigger others

Name: Loose Interfaces

Problem: To avoid development bottlenecks, we need to be able to limit the effect that one team’s work will have on another.

Context: Interfaces need to be somewhat flexible if the teams are working quickly. Requirements may be changing rapidly, and it may be difficult to communicate between geographically distributed subteams.

Solution: Limit the number of explicit, static interfaces. Define larger-grained interfaces that allow developers to code against interfaces defined early, but that do not overly constrain functionality. Consider using the Hierarchy of Factories pattern.(from Organizational Patterns of Agile Software Development, Coplien and Harrison)

5

Software patterns

The first “Object Oriented Design Patterns” are found in the book Design Patterns by Erich Gamma, Richard

Helm, Ralph Johnson, and John Vlissides (known as “Gang of 4” or “GOF”)

23 patterns: three categories (Creational, Structural, Behavioral)

Problems: control the construction of objects create organized collections of objects divide responsibilities among objects for

better encapsulation and easier modification Examples in C++ and Smalltalk The patterns also apply to other languages

(Java, Visual Basic, Perl)

6

Singleton Pattern

Name: Singleton

Problem: We need to restrict the creation of new objects for a particular class: only one instance.

Context: Other objects in the design need a single point of access to use the object.

Solution: Define a “static member function” within the class that returns a pointer (or reference) to the Singleton object. The static member function will create the object the first time it is called. All constructors are made private to prevent other objects from being created.

7

More about Singleton

Simple version of Singleton (in C++, without multi-thread support):

if (instance == 0) { instance = new MySingletonClass();}return instance;

MySingletonClass– instance : MySingletonClass *other attributes …+ getInstance() : MySingletonClass *– MySingletonClass()other operations …

• Access the Singleton like this: MySingletonClass::instance()• Different implementations of the Singleton pattern for Java,

multithreaded support, allocation in special memory, and so on.

underline meansstatic data member

8

Patterns and Idioms

What have we done? We have used a “design trick” that solves a specific problem

Some standard design tricks are called “idioms” they tend to be small, tricky, and language specific example: virtual destructors in C++ example: anonymous inner classes in Java

How are patterns different from idioms? Patterns are more about design Singleton is useful in Java, Smalltalk, Visual Basic, Perl, … different “realizations” of patterns in different languages

9

Patterns in the Design Patterns book

23 Design Patterns: three categories

Creational Structural Behavioral

Abstract Factory Adapter Chain of Responsibility

Observer

Builder Bridge Command State

Factory Method Composite Interpreter Strategy

Prototype Decorator Iterator Template Method

Singleton Facade Mediator Visitor

Flyweight Memento

Proxy

10

Sources of information

So, you want to learn how to use these design patterns to make your OO designs better

Where to look to learn more: the book A Learning Guide to Design Patterns

(http://www.industriallogic.com/papers/learning.html) Pattern Stories Wiki (http://wiki.cs.uiuc.edu/PatternStories) http://c2.com/cgi/wiki?DesignPatterns other books:

Pattern-Oriented Software Architecture by Frank Buschmann et. al. Design Patterns Java Workbook by Steven John Metsker Refactoring to Patterns by Joshua Kerievsky Design Patterns Explained by Alan Shalloway and James R. Trott

11

Why learn the Design Patterns?

Your own designs will improve borrowing well-tested ideas pattern descriptions contain some analysis of tradeoffs

You will be able to describe complex design ideas to others assuming that they also know the same patterns

You can use patterns to “refactor” existing code refactoring is improving the structure of existing code without

adding new functionality some techniques for transforming and adapting legacy code are

based on design patterns

12

Strategy Pattern

Problem: An application needs to use a family of similar algorithms the selection of which algorithm depends on the client making the

request or some characteristics in the data

Context: Two possible situations: you have a group of classes that contain the same data, but they

have different behavior (functions); or you have a class that defines many behaviors, and these

behaviors appear as multiple conditional statements in the operations of the class

Solution: Define a family of algorithms, encapsulate each one, and make them interchangeable there will be a family of classes, one per algorithm variation

13

Example of Strategy

Internet-based business When a customer accesses the

home page, you want to present a few products that the customer might be interested in

Web presentation program uses one or more “recommendation engines”

commercial off the shelf software uses customer survey information

or previous purchase history to make a recommendation

Might use multiple engines Might also want to highlight special

sale items

Customer

getAdvisor()getRecommended()

GroupAdvisorrecommend(Customer)

ItemAdvisorrecommend(Customer)

PromotionAdvisorrecommend(Customer)

Advisor<<abstract>>

recommend(Customer) :ProductSet

call one of therecommendation

engines

call a promotion-based selector

14

Strategy consequences

Strategy implements a flexible algorithm Separate a varying algorithm from the rest of the design Use a class hierarchy and virtual functions to allow

application code to select the correct algorithm at execution time

It’s easy to add new algorithms – assuming the interface is the same

But there are tradeoffs: Complex coupling between context and strategy Some concrete strategy classes might not use

everything that is supplied by the context

15

More patterns examples

Polymorphic creation with Factories: an application might need to make new objects from

several related classes

Defining clean interfaces with Facade: wrapper classes – might even wrap non-OO code

Remote access with Proxy

Building complex structures with Composite

Adding variations with Decorator

16

Factory Method Pattern

Problem: An application needs to create an object the application isn’t sure which type of object to create

Context: the application knows which “family” of classes the

created object will belong to: the object to be created will always support a specific abstract interface

Solution: Define a factory method in the object creator’s base class, define subclasses that each create the correct type of object for a specific situation

17

Creation methods

To lead up to an example of a Factory Method – first think about creation methods in many OO languages (C++,

Java), objects are created by constructor functions

if you want a specific kind of object, you can use a normal declaration in C++, or call the new operator in C++ or Java

OR, you can move the creation of the object to a separate function (a creation method)

class Myclass {public: Myclass(); // default constructor Myclass(int maxcalls); Myclass(std::string config_name); …};

int main() { Myclass m1, m2(100); Myclass *mptr1 = new Myclass; Myclass *mptr2 = make_object(50);}

Myclass *make_object(int n) { return new Myclass(n);}

18

Creation methods

Creation methods are a good supplement to constructors It is possible to give the creation method a name that indicates its

purpose; the name of a constructor is always the name of the class A creation method might be defined to both “construct” an object

plus associate a strategy object with the new object A creation method might use another pattern as a construction

shortcut: such as the Prototype pattern (fill in an object from an existing object)

Where to define a creation method? Three options Define the creation method as a static member function of the

class being created In a special Factory class Within the class that uses the constructed class

19

Multiple related creation methods

You might be in a situation where you need multiple creation methods in one situation, you want to create an InternalCall in another situation, you want to create a RegularCall and in yet another situation, you want to create an InternationalCall AND, all three classes are part of the same hierarchy

Call

RegularCallInternalCall InternationalCall

Call *make_int_call(string num) { return new InternalCall(num);}Call *make_reg_call(string num) { return new RegularCall(num);}Note: no design patterns happening yet…

We’ll get there is another slide or two…

20

Why are dynamic objects important?

It is natural for object oriented designs to have dynamic objects: heterogeneous collections (a collection containing a mixture of similar objects) objects with a short lifetime (tasks, events, messages, dialogs)

ChannelCard <<abstract>>

CC_model2CC_model1 CC_model3

CardShelf

cards : ChannelCard *[5]

shelf_status : STATUS*

This array points to all ofthe ChannelCard objects

for the current configurationif (get_shelf_signature_signal(i) == MODEL1) { cards[i] = new CC_model1();}

Example: An OA&M subsystem may need to keep information about number of different physical objects

21

InternatFaxSender

create_call_for_faxing

Factory Method

In Factory Method – the responsibility for creating an object will be assigned to the class that uses it…

We need to look at how a class hierarchy might be used in an application: For example, a FaxSender class might have a fax_it() member function which needs

to create a Call object The type of Call is usually a RegularCall, but subclasses (such as an

InternatFaxSender) are allowed to override the creation

FaxSendermycall : Call*fax_itcreate_call_for_faxing

fax_it() calls this->create_call_for_faxing()

an extension class

virtual Call *create_call_for_faxing(string num) { return new RegularCall(num); }

virtual Call *create_call_for_faxing(string num) { return new InternationalCall(num); }

Note: the fax_it() function works the

same way for a FaxSender or an

InternatFaxSender

22

Factory Method

A Factory Method is a creation method in any base class within an application The “design trick” is: subclasses are permitted to

create any compatible object The base class Factory Method almost always returns a

“pointer to a base class” (or a “pointer to an abstract interface”)

Subclasses that redefine the Factory Method will still return a pointer to base class, but they might create a different kind of concrete object

23

Facade Pattern

Problem: The application needs a simple interface to a complex subsystem the subsystem might have been written by someone else

Context: it is important to control the dependencies between the application

and the complex subsystem – you want to reduce the effort to maintain the system

Solution: Define a single Facade class: the Facade class has knowledge of the internal details of the subsystem, but the Facade class provides a simple to use interface for the application each Facade public function might call many subsystem operations

24

Facade diagram

A Facade class wraps a bunch of operations on other classes (or a bunch of legacy code operations) into a convenient package

application Facade classpointers to other dataobjects within asubsystemget_val1()build_trans2()do_trans3()commit_trans4()

application callssome of the Facade

class operations

scanner

databaseinterface

parser

formatterthe Facade accessessome of the internals

of a complex subsystem toimplement its operations

25

Planning a Facade

Part of the OO design process: create a simplified model of the classes in the overall system using CRC cards (informal technique using index cards, one card

per class) using UML Class Diagrams

Look for a group of classes that collaborate closely together: call them a “subsystem”

Try to “put the subsystem behind a wall” – define a single interface class that defines an API for the subsystem

26

Proxy example

A Proxy object is a “stand-in” for an object that might be: located on another machine (example: CORBA objects, Java RMI) or it might be large and complicated, so you want to defer building it or it might require a special access method (to check the users’

permissions)

client application

network

ORB (server)

CORBAIDL stubs

IDL skeletons

InterfaceRepository

ObjectImplementations

CORBA example

requests responses

Stub objects have fullpublic interface, but no data.They just push a message

over to the server.

Generatedby a tool

Developersfill in details

27

Proxy pattern

Problem: The application needs to operate on a distant objectContext: Need a placeholder for an object if the actual object is far away (on another computer or on a disk),

the placeholder should be in the local address space

Solution: Define a Proxy class: this class will have the same public interface as the real class, and when a Proxy operation is called, the internals of a Proxy object will arrange for the same function to be called on a real object Proxy might send interprocess or intermachine messages Proxy might resurrect an object that has been written to disk Proxy might acquire special permissions to access a protected real

object

28

How to tell the difference?

How can I tell which one I am using? Facade or Proxy? Both patterns are separating the implementation details from an

abstract interface But the intent is different for each pattern

Facade: the application wants to use services of an entire subsystem or package (usually tens or hundreds of objects in the subsystem)Facade is also a common way to interface with non-OO modulesProxy provides convenient access to an object – the object might be on disk, in another process, on another computer

29

Multiple related creation classes

The Abstract Factory pattern: define multiple parallel creation classes whenever you define a new subclass of Call, define a new creation class

Call

RegularCall

InternalCall

InternationalCallCall *IntCallFactory::make_call(string num) { return new InternalCall(num);}

CallFactory

RegCallFactory

IntCallFactory

InternatCallFactory

Call *RegCallFactory::make_call(string num) { return new RegularCall(num);}

30

Composite Pattern

From Design Patterns: “Graphics applications like editors let users build complex diagrams out of simple components” how to represent a complex diagram? diagram is a combination of primitive items (lines, boxes, text objects) in addition, a group of primitive items (a “picture”) could be represented

as a single object and a picture might contain other pictures

Line Line Line Line

Picture Box

Picturepicture four lines and a box

31

Composite class diagram

Here is one proposed design:

Line

Draw

Box

Draw

Text

Draw

Picture

DrawAdd(Graphic *g)Remove(Graphic *g)GetChild(int)

Graphic

DrawAdd(Graphic *g)Remove(Graphic *g)GetChild(int)

this supports the recursive containment

for all g in children g->Draw();

children

32

General diagram for Composite

In general, the Composite is

Leaf

Operation()

Composite

Operation()Add(Component *g)Remove(Component *g)GetChild(int)

Component

Operation()Add(Component *g)Remove(Component *g)GetChild(int)

for all g in children g->Operation();

children

several different kinds of Leaf classes can be

subclasses of Component

33

Consequences

Applications treat composite and leaf objects uniformly – in the example, the Draw() function on a composite will recursively draw the lower level objects

Easy to add new leaf classes within the framework

34

Decorator Pattern

Problem: You want to add operations to specific objects.Context: There may be lots of different combinations of data and operations

needed. Defining new subclasses for each combination would be too

tedious. You may also want to add data and behavior dynamically. You don’t want to affect ordinary objects.

Solution: Define one or more Decorator classes that define a set of new operations. Then attach a Decorator object to the object whose operations you want to augment. a Decorator is very similar to an Adapter

35

Decorator Pattern example

Suppose Call is an abstract interface, and RegularCall is the most commonly created concrete subclass

Instead of subclassing RegularCall to add new functions, we can “decorate” RegularCall instead

Call <<abstract>>

get_idset_uptear_down

RegularCall

call_id

get_idset_uptear_down

CallDecorator<<abstract>>

Call *component

get_idset_uptear_down

d1 : PictureMailCallDecorator

component

d2 : EmailviewCallDecorator

component

d3 : WiretapCallDecorator

component

call1 : RegularCall

call_id = “3517711”

concrete Decoratorclasses are derived

from this class

WiretapCallDecorator

set_up

EmailviewCallDecorator

set_up

36

Decorator diagram

This pattern permits the definition of one or more Concrete Decorator classes these Decorator classes implement the entire public interface of the “Decoratee” implemented by delegation: abstract Decorator has forwarding functions; concrete Decorator

subclasses can overrideComponent <<abstract>>

Operation()

Decorator <<abstract>>

Operation()

ConcreteComponent

… attributes …

Operation()

// delegate to ConcreteComponent component->Operation();

ConcreteDecoratorA

… extra attributes …

Operation()Added_operation()

this is the “Decoratee”

(no real restrictions on the structure or

behavior)

component

component->Operation(); this->Added_operation();

37

Designing the Decorator

Decorator avoids subclassing the Decoratee class the design just gets lots of small classes that optionally add

nuggets of functionality to an existing class since each Decorator implements the full set of behaviors of the

base Component class, a pointer to a Decorator can be passed into any function that expects the base Component

If you start your design with just a Concrete Component, you have to do some refactoring of the existing application to change “concrete” to “abstract” wherever it makes sense this is a good design practice anyway and it makes way for decorated objects being applicable anywhere

a plain object is OK

38

Consequences

A Decorator is a transparent enclosure – any member function call will be forwarded to the component class

If a component class has a large public interface (more than 10 or 12 public member functions), it can be a lot of work to define a Decorator because each Decorator must at a minimum define the same public

interface as the component class

Decorator add new behavior in little objects that cling to the main domain classes don’t want to obscure the main lines of the design and the most

frequently executed scenarios

39

Summary

Design Patterns: an important set of object oriented design concepts these patterns are useful in many applications every pattern has a documented set of “Consequences”

Many more design patterns exist: http://hillside.net/patterns/onlinepatterncatalog.htm http://www.martinfowler.com/articles/enterprisePatterns.html http://java.sun.com/blueprints/corej2eepatterns