CSE503: Software Engineering
Lecture 8 (January 22, 1999)

David Notkin

 

v     Today: More on patterns

      A little history

      Notation

      A study of a specific pattern

v     A little background on design patterns (Gang of Four and others)

      In 1977, Christopher Alexander and colleagues (Center for Environmental Structure) wrote a collection of three books architecture, building, and planning

        More on Alexander is available on the web

      One of them, A Pattern Language, is based on the notion that in designing their environments, people always rely on certain `languages, which, like the languages we speak, allow them to articulate and communicate an infinite variety of designs within a formal system which gives them coherence.

      Indeed, the book discusses over two hundred patterns that are intended to give concrete guidance in designing towns, buildings, and construction

      Example: Activity Pockets (#124)

        The life of a public square forms naturally around the edge. If the edge fails, then the space never becomes lively.

        Therefore: Surround public gathering places with pockets of activity---small, partly enclosed areas at the edges, which jut forward into the open space between the paths, and contain activities which make it natural for people to pause and get involved.

      One can push the analogies to Alexanders work too far; but it is taken very seriously by many members of the computing research community; Alexander gave a keynote at OOPSLA, for instance

v     Notation

      The patterns in the GoF (Gang of Four---Gamma, Helm, Johnson, Vlissides) book (Amazon Sales Rank 257) are described in an "OMT-based notation"

      OMT was one of several popular notations for describing aspects of object-oriented models/designs (Booch, Coad/Yourdon, and others were also common)

      A number of the OO analysis/design bigwigs (in particular, Booch, Rumbaugh, and Jacobson) combined at Rational to design UML, the "Unified Modeling Language"

      UML, with significant input from many many companies and individuals, is becoming adopted as an industry-standard notation

        Amazon today lists 31 books with "UML" in the title, including ones that rank 124, 248, 571, 894, and 1693

      While I don't want to go into full detail (UML is quite large and complex), I think it's important to be able to read the basics of UML

        The current documentation of UML is almost 700 pages!

      Someone in Finland has converted all the GoF pattern structures into UML

      Here's the flyweight pattern description in UML (comes at the end of the file/page)

        The boxes represent classes (except for the box hanging off FlyweightFactory by a dotted line), with the bold-faced name indicating the class that is being represented

        <stereotype> is a UML detail (you won't find it in the OMT notation in the GoF book) that basically says, hey, this is a completely new class, don't treat it like anything else that has structural similarity (the Ada type system lets you do this, too, as do some other programming languages)

        The elements in the subbox underneath the class name indicate the operations provided (UML allows for attributes to be defined, too, but this example shows only operations)

        The "+" indicates that the operations are public (with "-" and "#" representing private and protected, respectively)

        The arrows of various sorts represent relationships between the classes

        The arrow between FlyweightFactory and Flyweight indicates that Flyweight is part-of; the "1" at the right side of this arrow indicates that there is precisely one Flyweight instance in instantiations of FlyweightFactory

        The arrows from ConcreteFlyweight and from UnsharedConcreteFlyweight to Flyweight are inheritance relations (they each inherit from Flyweight)

        The three lines from Client represent that Client owns references to instances of these three classes

        The box associated with FlyweightFactory shows pseudocode that captures the basics of the exported operation

      More information on each participant

        Flyweight

        Declares an interface through which flyweights can receive and act on extrinsic state

      So, if you were managing (lots of) character objects, you might prefer to keep font and style information extrinsic (external to) the objects, since there are in general far fewer fonts and styles used than characters

        FlyweightFactory

      Creates and manages flyweight objects

      Ensures that flyweights are shared properly

      When a client requests a flyweight, the FlyweightFactory object supplies an existing instance or creates one, if none exists

        ConcreteFlyweight

      Implements the Flyweight interface (thus the inheritance in the diagram) and adds storage for the intrinsic state, if any

      Intrinsic state is that which is independent of the context in which the ConcreteFlyweight object is used (e.g., a specific character, like "a")

      Must be sharable

        UnsharedConcreteFlyweight

      Allows for Flyweight instances that are not shared

      Can have shared ConcreteFlyweight children, too

      An example is where you have columns of text, each containing rows of characters

      The columns and the rows might be UnsharedConcreteFlyweights, while the characters themselves might be ConcreteFlyweights

        Client

      Maintains reference to flyweight(s)

      Computes or stores extrinsic state of flyweights

      Code from the GoF for a use of Flyweight

 

 

#include "defs.H"

class Window;

class GlyphContext;

class Font {

public:

Font(char*);

};

class BTree;

 

class Glyph {

public:

virtual ~Glyph();

 

virtual void Draw(Window*, GlyphContext&);

 

virtual void SetFont(Font*, GlyphContext&);

virtual Font* GetFont(GlyphContext&);

 

virtual void First(GlyphContext&);

virtual void Next(GlyphContext&);

virtual bool IsDone(GlyphContext&);

virtual Glyph* Current(GlyphContext&);

 

virtual void Insert(Glyph*, GlyphContext&);

virtual void Remove(GlyphContext&);

protected:

Glyph();

};

 

class Character : public Glyph {

public:

Character(char);

 

virtual void Draw(Window*, GlyphContext&);

private:

char _charcode;

};

 

class GlyphContext {

public:

GlyphContext();

virtual ~GlyphContext();

 

virtual void Next(int step = 1);

virtual void Insert(int quantity = 1);

 

virtual Font* GetFont();

virtual void SetFont(Font*, int span = 1);

private:

int _index;

BTree* _fonts;

};

 

void dummy () {

 

GlyphContext gc;

Font* times12 = new Font("Times-Roman-12");

Font* timesItalic12 = new Font("Times-Italic-12");

// ...

 

gc.SetFont(times12, 6);

 

gc.Insert(6);

gc.SetFont(timesItalic12, 6);

 

}

 

class Row {

};

class Column {

};

 

const int NCHARCODES = 128;

 

class GlyphFactory {

public:

GlyphFactory();

virtual ~GlyphFactory();

 

virtual Character* CreateCharacter(char);

virtual Row* CreateRow();

virtual Column* CreateColumn();

// ...

private:

Character* _character[NCHARCODES];

};

 

GlyphFactory::GlyphFactory () {

for (int i = 0; i < NCHARCODES; ++i) {

_character[i] = 0;

}

}

 

Character* GlyphFactory::CreateCharacter (char c) {

if (!_character[c]) {

_character[c] = new Character(c);

}

 

return _character[c];

}

 

Row* GlyphFactory::CreateRow () {

return new Row;

}

 

Column* GlyphFactory::CreateColumn () {

return new Column;

}