slide1 l.
Download
Skip this Video
Loading SlideShow in 5 Seconds..
Using Design Patterns to Elaborate upon Design Models PowerPoint Presentation
Download Presentation
Using Design Patterns to Elaborate upon Design Models

Loading in 2 Seconds...

play fullscreen
1 / 42

Using Design Patterns to Elaborate upon Design Models - PowerPoint PPT Presentation


  • 91 Views
  • Uploaded on

Using Design Patterns to Elaborate upon Design Models. Moving from Analysis to Design. Examine Design models and initial code to:. Improve cohesion Reduce coupling Enhance Reusability. GoF Design Patterns should be used to rewrite code to promote these goals. Concordance Example.

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 'Using Design Patterns to Elaborate upon Design Models' - lixue


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
slide1

Using Design Patterns to Elaborate upon Design Models

Moving from Analysis to Design

Examine Design models and initial code to:

  • Improve cohesion
  • Reduce coupling
  • Enhance Reusability

GoF Design Patterns should be used to rewrite code to promote these goals

slide2

Concordance Example

A Concordance consists of an alphabetized list of words appearing in a short document together with an ordered list of the distinct line numbers of lines in which each word appears. Design and implement a short document concordance program. Your program should be able to accept any document, generate a Concordance for the document, and display (or print) the document with its concordance.

The domain model will contain the following classes:

Concordance

Document

Word

WordList

Line

LineNumberList

slide3

makes/displays

WordList

Concordance

parses

*

*

Line

Document

contains

Number

*

Word

LineNumberList

forms

Concordance Domain Model

slide4

Implementation

Consider class WordList. It has the following requirements:

Quick Access -- HashTable O(1), BinarySearchTree O(lg(n)), Vector O(n)

Alphabetically ordered display – BinarySearchTree O(ln), Vector O(n),

HashTable

Choose a BinarySearchTree as the most appropriate data structure

Next, consider class LineNumberList.

Line numbers are entered in the order they appear, and are read from front to back.

Consider using either a Vector or a Queue to list line numbers. Choose the Vector for simplicity and because it can be read non-destructively.

slide5

BinSTree

Concordance

root

BinSTreeNode

0..2

Document

children

parent

holds

Vector

Word

Line

number

Class Diagram – First Iteration

slide6

Consequences of Implementation 1

Class Interfaces

class Word {

private String word;

private Vector theLines;

public Word (String s, int lineNum) {….}

public void addLine(int num) {

theLines.add(new Integer(num));

public boolean equals(Word w) { … }

public String toString( ) { … }

public String getWord( ) { … }

public String getLineNums( ) { … }

}

The statements highlighted in blue indicate attributes and operations flagged by a “House Unwordy Activities Committee” as not properly belonging to class Word.

In the interest of high cohesion we will redesign the class

slide7

TreeIterator

BinSTree

Association

Vector

root

root

key

holds

BinSTreeNode

0..2

children

parent

Word

Modified Class Diagram

slide8

Builder

Director

makePart( )

getPart( )

ConcreteBuilder

Product

makePart( )

getPart( )

Additional Design Modification

Who is responsible for creating Associations? Concordance?

Better Solution – use a Builder to construct Association objects

(Concordance)

(Association)

Builder Pattern

(AssocBuilder)

slide9

Implementation of Builder Pattern

public class Concordance {

private Builder assBuilder = new AssocBuilder( );

private BinsSTree bst = new BinsSTree( );

public void readLines(Document doc) {

String delims = " \t\n.,!?;:";

for (int line = 1; true; line++) {

try {

String text = doc.readLine( );

if (text == null) return;

text = text.toLowerCase( );

Enumeration e = new StringTokenizer(text, delims);

while (e.hasMoreElements( ))

enterWord((String)e.nextElement( ),line);

}catch(IOException e) {System.err.println(e.toString( ));}

}

}

private void enterWord(String word, int line) {

Word w = new Word(word);

assBuilder.buildPart(w, line);

Association ass = assBuilder.getPart( );

if (!bst.contains(ass) ) {

bst.add(ass);

}

else {

boolean flag = false:

Iterator itr = bst.iterator( );

while (itr.hasNext( ) && !flag) {

Association visit = (Association)

itr.next( );

if (visit.equals(ass)) {

flag = true;

visit.addLine(Integer(line));

}

}

}

}

slide10

Implementation of Builder Pattern

class AssocBuilder implements Builder{

private Association theProduct;

public void buildPart(Word w, int lineNum) {

theProduct = new Association(w, new Integer(linNum) );

}

public Object getPart( ) {

return theProduct;

}

}

class Association implements Comparable{

private Word word;

private Vector v;

private String key;

public Association ( ) {

word = null; v = new Vector( ); key = null;

}

public Association(Word w, Integer lineNum) {

word = w; v = new Vector( );

key = w.getWord( ); v.add(lineNum);

}

public addWord(Word w) {

word = w; key = w.getWord( );

}

public addLine(Integer lineNum) {

v.add(lineNum);

}

//methods equals, compareTo, toString, etc.

}

Note! getPart( returns a generic Object – client must cast to get the desired return type.

slide11

Implementation of Builder Pattern

When there is only one part to build, as the Association in the Concordance example, it makes sense to omit the abstract builder interface and just use a concrete class. We compromised and kept the abstract interface, but wrote the buildPart method with parameters specific to the single product (Association) in the example.

slide12

Builder Pattern

Intent – Separate the construction of a complex object from its representation, so that the same construction process can create different representations (in our example – Association and Document)

Participants

  • Builder –an Abstract Interface for creating parts of a Product object.
  • ConcreteBuilder –
  • Implements the Builder Interface
  • Defines and keeps track of the representation it creates
  • provides an interface for retrieving the product
  • Director (Concordance)
  • Constructs a Product object using the Builder Interface
  • Product (Association)
  • includes classes that define the constituent parts, including interfaces for assembling the parts into the final result.
slide13

Builder Pattern

Collaborations

  • The client creates the Director object and configures it with the desired Builder object.
  • The Director notifies the ConcreteBuilder whenever a part of the Product should be built.
  • The Builder handles requests from the Director and adds parts to the Product
  • The client retrieves the Product from the Builder
slide14

create( )

new Director( )

new Association

Alternative Design

Follow the pattern more closely and create a separate Director that directs the construction of the BinSTree and the Document (not shown)

Concordance

aDirector

aTreeBuilder

aBinSTree

new TreeBuilder( )

parseText(Document )

anAssoc

loop

buildPart(word,line)

add(anAssoc)

printConcordance( )

getResult( )

iterator( )

slide15

The docBuilder constructs a String – the Document – from a text file

Alternative Design Classes

public class Concordance {

private Builder docBuilder = new DocumentBuilder( );

private DocParser director;

private Document theText;

public Concordance( ) {

director = new DocParser( );

}

public void makeConcordance( String filename) {

docBuilder.buildPart( filename);

theText = docBuilder.getPart( );

director .parseText(theText);

}

public void printConcordance( ) {…}

}

slide16

Alternative Design Classes

class DocParser {

private Builder treeBuilder = new TreeBuilder( );

private Document theText;

public parseText(Document doc) {

theText = doc;

readLines(theText);

}

public void readLines( ) {

String delims = " \t\n.,!?;:";

for (int line = 1; true; line++) {

try {

String text = doc.readLine( );

if (text == null) return;

text = text.toLowerCase( );

Enumeration e = new StringTokenizer(text, delims);

while (e.hasMoreElements( ))

enterWord((String)e.nextElement( ),line);

}

} catch(IOException e) {System.err.println(e.toString( ));}

}

private void enterWord(String word, int line) {

Word w = new Word(word);

treeBuilder.buildPart(w, line);

}

}

The Concordance is relieved of any responsibility for forming Associations or performing operations on a tree.

slide17

Alternative Design

class TreeBuilder implements Builder{

private BinSTree bst = new BinSTree( );

private Association ass;

publicvoid buildPart(Word w, int line) {

ass = new Association(w, new Integer(line) );

if (!bst.contains(ass) ) {

bst.add(ass);

}

else {

boolean flag = false:

Iterator itr = bst.iterator( );

while (itr.hasNext( ) && !flag) {

Association visit = (Association)

itr.next( );

if (visit.equals(ass)) {

flag = true;

visit.addLine(Integer(line));

}

}

}

}

public Iterator getResult ( ) {

return bst.iterator( );

}

slide18

Additional Patterns

Singleton

Adapter

Composite

Decorator

Flyweight

slide19

Singleton Pattern

Intent

Ensure a class only has one instance, and provide a global point of access to it.

Applicability

  • Use Singleton pattern when
  • There must be exactly one instance of a class, and it must be accessible to clients from a well-known access point.
  • When the sole instance should be extensible by sub-classing, and clients should be able to use an extended instance without modifying their code.

Consequences

  • Controlled access to sole instance. Singleton class encapsulates its sole instance and has strict control over how and when clients access it.
  • Reduced name space. It avoids polluting the name space with global variables that store sole instances.
  • Permits refinement of operations and representation. It can be subclassed.
slide20

Singleton Pattern – Example code

Singleton class declaration

Implementation of Singleton

class Singleton {

public:

static Singleton* Instance( );

protected:

Singleton( );

private:

static Singleton * _instance;

}

Singleton * Singleton:: _instance = 0;

Singleton * Singleton::Instance( ) {

if (_instance == 0)

_instance = new Singleton( );

return _instance;

}

slide21

Target

Adaptee

Client

request( )

specialRequest( )

Adapter

specialRequest( )

request( )

Adapter Pattern

Class Adapter

Adapter lets classes work together that couldn’t otherwise because of incompatible interfaces.

slide22

Target

Adaptee

Client

request( )

specialRequest( )

Adapter

adaptee  specialRequest( )

request( )

Adapter Pattern

adaptee

Object Adapter

Adapter can add additional functionality to the Adaptee object that the Adaptee object lacks but that Target requires.

slide23

Adapter (a.k.a. Wrapper)

Applicability

  • Use the Adapter pattern when
  • You want to use an existing class and its interface does not match the one you need.
  • You want to create a reusable class that cooperates with unrelated or unforseen classes, that is, classes that don’t necessarily have compatible interfaces.
  • (object adapter) you need to use several existing subclasses, but it’s impractical to adapt their interface by subclassing every one. An object adapter can adapt the interface of its parent class.

Participants

Target

-- defines the domain-specific interface that Client uses.

Client

-- collaborates with objects conforming to the Target interface.

Adaptee

-- defines an existing interface that needs adapting.

Adapter

-- adapts the interface

of Adaptee to the

Target interface

slide24

Component

Client

*

Operation( )

Add(Component)

Remove(Component)

GetChild(int)

Composite

Leaf

For all g in children

g.Operation( );

Operation( )

Add(Component)

Remove(Component)

GetChild(int)

Operation( )

Composite Pattern

slide25

Composite Pattern

Applicability

You want to be able to ignore the difference between compositions of objects and individual objects. Clients will treat all objects in the composite structure uniformly.

Participants

  • Component

-- declares the interface for objects in the composition

-- implements default behavior for the interface common to all classes, as

appropriate

-- declares an interface for accessing and managing its child components.

  • Leaf

-- defines behavior for primitive objects in the composition.

  • Composite

-- defines behavior for components having children.

-- stores child components

-- implements child-related operations in the Component interface.

slide26

Composite Pattern

Collaborations

Clients use the Component class interface to interact with object in the composite structure. If the recipient is a Leaf, then the request is handled directly. If the recipient is a Composite, then it usually forwards request to its child components, possibly performing additional operations before and/or after forwarding.

Consequences

  • Defines class hierarchies consisting of primitive objects and composite objects. Wherever client code expects a primitive object, it can also take a composite object.
  • Makes the client simple. Clients can treat composite structures and individual objects uniformly.
  • Makes it easier to add new kinds of components. Newly defined Composite or Leaf subclasses work automatically with existing structures and client code.
  • Can make your design overly general. It makes it harder to restrict the components of a composite.
slide27

Equipment

Client

*

Operation( )

Add(Component)

Remove(Component)

GetChild(int)

CompositeEquipment

FloppyDisk

CDDrive

For all g in children

g.Operation( );

Operation( )

Operation( )

Add(Component)

Remove(Component)

GetChild(int)

Operation( )

Example of Composite Pattern

slide28

Sample Code

class Equipment {

public:

virtual ~Equipment( );

constchar* name( ) { return _name; }

virtual Watt Power( );

virtual Currency NetPrice( );

virtual Currency DiscountPrice( );

virtual void Add(Equipment *);

virtual void Remove(Equipment *);

virtual Iterator<Equipment*> * CreateIterator( );

protected:

Equipment (const char * );

private:

constchar * _name;

}

class FloppyDisk : public Equipment {

public:

FloppyDisk(const char*);

virtual ~FloppyDisk( );

virtual Watt Power( );

virtual Currency NetPrice( );

virtual Currency DiscountPrice( );

}

class Chassis : public CompositeEquipment{

public:

Chassis (const char* );

virtual ~Chassis( );

virtual Watt Power( );

virtual Currency NetPrice( );

virtual Currency DiscountPrice( );

}

slide29

Sample Code for Composite Example

class CompositeEquipment: public Equipment {

public:

virtual ~CompositeEquipment( );

virtual Watt Power( );

virtual Currency NetPrice( );

virtual Currency DiscountPrice( );

virtual void Add(Equipment *);

virtual void Remove(Equipment *);

virtual Iterator<Equipment *> * CreateIterator( );

protected:

CompositeEquipment(const char *);

private:

List<Equimpent *> _equipment;

}

An implementation of NetPrice( )

Currency CompositeEquipoment::NetPrice( ) {

Iterator<Equipment *> * i = CreateIterator( );

Currency total = 0;

for (i -> first( ); i -> isDone( ); i -> next( ) ) {

total += i -> currentItem( ) -> NetPrice( );

}

delete i;

return total;

}

slide30

Sample code for Composite Pattern Example

Assume we have additional Equipment classes such as Bus, Cabinet, etc. We can assemple equipment into a (simple) computer (CompositeEquipment object).

Cabinet * cabinet = new Cabinet(“PC Cabinet”);

Chassis * chassis = new Chassis(PC Chassis”);

cabinet -> Add(chassis);

Bus * bus = new Bus(“MCA Bus”);

bus -> Add(new Card(“100 Mbs Ethernet”) );

chassis ->Add(bus);

chassis -> Add (new FloppyDisk(“3.5 in Floppy”) );

cout << “ the net price is “ << chassis -> NetPrice( ) << endl;

slide31

aBorderDecorator

aScrollPaneDecorator

component

component

aTextView

Decorator Pattern

Allows the programmer to add responsibilities to individual objects, not to an entire class. The decorator conforms to the interface of the component it decorates so that its presence is transparent to the component’s clients.

An example of a decorator is the scroll pane in java. We may add scroll bars as needed. We may also add a border around the scroll pane. Another example of the Decorator Pattern in java is the Stream classes.

slide32

Component

operation( )

ConcreteComponent

Decorator

component.operation();

operation( )

operation( )

ConcreteDecoratorA

ConcreteDecoratorB

operation( )

super.operation();

addedBehavior();

operation( )

addedBehavior( )

addedState

Decorator Pattern

slide33

Decorator Pattern

Participants

  • Component – defines the interface for objects that can be “decorated”
  • ConcreteComponent (JTextArea) – defines an object to which additional responsibilities can be added (can be “decorated”)
  • Decorator – maintains a reference to a Component object and defines an interface that conforms to Components interface.
  • ConcreteDecorator (JScrollPane) – adds responsibilities to the Component.
slide34

Decorator Pattern

Consequences

More flexible than static inheritance.

Avoids feature-laden classes high up in the hierarchy. Instead of trying to support all foreseeable features in a complex, customizable class, you can define a simple class and add functionality incrementally with Decorator objects.

A Decorator and its Component are not identical. A decorator acts as a transparent enclosure.

slide35

Decorator Pattern -- Example

import java.awt.*;

import javax.swing.*;

public class JScrollDemo extends JFrame {

JTextArea area = new JTextArea(10, 60);

JScrollPane sp = new JScrollPane(area,

JScrollPane.VERTICAL_SCROLLBAR_ASNEEDED,

JScrollPane.HORIZONTAL_SCROLLBAR_ASNEEDED);

public JScrollBarDemo( ) {

Container cp = getContentPane( );

area.setFont(new Font(“Monospaced”, Font.PLAIN, 12));

cp.add(sp, BorderLayout.CENTER);

setVisible(true);

setDefaultCloseOperation(EXIT_ON_CLOSE);

}

}

slide36

Flyweight Pattern

Intent

Use sharing to support a large number of fine-grained objects efficiently. The Flyweight pattern describes how to share objects to allow their use at fine granularities without prohibitive storage cost.

Applicability -- Apply the Flyweight pattern when all of the following are true.

  • An application uses a large number of objects.
  • Storage costs are high because of the sheer quantity of objects.
  • Most object state can be made extrinsic. (Intrinsic state is stored in the flyweight – it is context independent. Extrinsic state depends upon the flyweight’s context and can’t be shared.)
  • Many groups of objects may be replaced by relatively few shared objects once extrinsic state is removed.
  • The application does not depend upon object identity (since flyweight objects are shared,identity tests will return true for conceptually distinct objects.)
slide37

FlyweightFactory

Flyweight

getFlyweight(key)

operation(extrinsicState)

if(flyweight(key) exists) {

return existing flyweight; }

else {

create new flyweight;

add it to pool of flyweights

return the new flyweight; }

ConcreteFlyweight

UnsharedConcreteFlyweight

Client

operation(extrinsicState)

operation(extrinsicState)

intrinsicState

allState

Flyweight Pattern

slide38

aClient

aClient

flyweight

pool

aConcreteFlyweight

aConcreteFlyweight

aFlyweightFactory

intrinsicState

intrinsicState

flyweights

Flyweight Pattern

The following object diagram shows how flyweights are shared

slide39

Flyweight Pattern

Participants

  • Flyweight (Glyph) – declares an interface through which flyweights can receive and act on extrinsic state.
  • ConcreteFlyweight (Character) – implements the Flyweight interface and adds storage for intrinsic state. It must be sharable and any stored state must be independent of the flyweight’s context.
  • UnsharedConcreteFlyweight (Row, Column) – not all Flyweight subclasses need to be shared. The Flyweight interface enables sharing; it doesn’t enforce it. It’s common for UnsharedConcreteFlyweight objects to have ConcreteFlyweight objects as children at some level of the flyweight object structure.
  • FlyweightFactory – creates and manages flyweight objects. When a client requests a flyweight object, the factory supplies an existing flyweight object if one exists and creates one if it doesn’t.
  • Client – maintains a reference to flyweights and computes or stores their extrinsic state.
slide40

Flyweight Pattern

ConcreteFlyweight -- Character

Intrinsic state – character code

Extrinsic state – font, color, position

public interface Glyph {

public void draw(Window w, GlyphContext gc);

public void setFont(Font f, GlyphContext gc);

public Font getFont(GlyphContext gc);

……..

}

public class Character implements Glyph {

//implement all of the Glyph methods

public Character(char c) {_charcode = c;}

private char _charcode;

}

public class Row implements Glyph {

//implement all of the Glyph mehods

}

slide41

Shared flyweights

Unshared flyweights

Flyweight Pattern

public class GlyphFactory {

private static final int NUMCHARS = 128;

private Glyph[ ] charPool;

public GlyphFactory {

charPool = new Glyph[NUMCHARS];

for (int i = 0; i < NUMCHARS; i++) {charPool[i] = null; }

}

public Character createCharacter(char ch) {

if (charPool[ch] == null) charPool[ch] = new Character(ch);

return charPool[ch];

}

public Row createRow( ) {

returnnew Row( );

}

}

slide42

Flyweight Pattern

Class GlyphContext must store or compute the extrinsic state of each flyweight object in the document. If each character in the document is indexed, then we would need to locate the start index and duration of substrings using a particular font.