Visitor Pattern, Creational Patterns Introduction, and Abstract Factory

This excerpt completes the Visitor pattern discussion from the Lexi document editor case study, summarizes all eight patterns applied in that case study, introduces the Creational Patterns category, and presents the Abstract Factory pattern in full detail — including intent, structure, consequences, implementation techniques, and a maze-building code example.

Key Concepts

Commands and Syntax

Visitor accept/visit protocol:


class Visitor {
public:
    virtual void VisitCharacter(Character*) { }
    virtual void VisitRow(Row*) { }
    virtual void VisitImage(Image*) { }
};

// In each Glyph subclass:
void Character::Accept(Visitor& v) { v.VisitCharacter(this); }

Maze component hierarchy (creational patterns example):


enum Direction {North, South, East, West};

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;
};

Abstract Factory — MazeFactory:


class MazeFactory {
public:
    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); }
};

Parameterized CreateMaze using Abstract Factory:


Maze* 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);
    // ... remaining sides
    return aMaze;
}

Concrete factory via subclassing (EnchantedMazeFactory):


class EnchantedMazeFactory : public MazeFactory {
public:
    virtual Room* MakeRoom(int n) const
        { return new EnchantedRoom(n, CastSpell()); }
    virtual Door* MakeDoor(Room* r1, Room* r2) const
        { return new DoorNeedingSpell(r1, r2); }
};

Prototype-based factory in Smalltalk:


make: partName
    ^ (partCatalog at: partName) copy

addPart: partTemplate named: partName
    partCatalog at: partName put: partTemplate

Relationships

Exam-Relevant Points