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 Alexander’s 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;

}