Back Home Up Next

PROTOTYPE

1 Purpose

2 Problem Description

3 Domain Definitions

4 Elisa Components

1 Purpose

Specify the kinds of objects to create using a prototypical instance, and create new objects by copying this prototype.

2 Problem Description

You could build an editor for music scores by customizing a general framework for graphical editors and adding new objects that represent notes, rests, and staves. The editor framework may have a palette of tools for adding these music objects to the score. The palette would also include tools for selecting, moving, and otherwise manipulating music objects. Users will click on the quarter-note tool and use it to add quarter notes to the score. Or they can use the move tool to move a note up or down on the staff, thereby changing its pitch.

Let's assume the framework provides an abstract Graphic class for graphical components, like notes and staves. Moreover, it'll provide an abstract Tool class for defining tools like those in the palette. The framework also predefines a GraphicTool subclass for tools that create instances of graphical objects and add them to the document.

But GraphicTool presents a problem to the framework designer. The classes for notes and staves are specific to our application, but the GraphicTool class belongs to the framework. GraphicTool doesn't know how to create instances of our music classes to add to the score. We could subclass GraphicTool for each kind of music object, but that would produce lots of subclasses that differ only in the kind of music object they instantiate. We know object composition is a flexible alternative to subclassing. The question is, how can the framework use it to parameterize instances of GraphicTool by the class of Graphic they're supposed to create?

The solution lies in making GraphicTool create a new Graphic by copying or "cloning" an instance of a Graphic subclass. We call this instance a prototype. GraphicTool is parameterized by the prototype it should clone and add to the document. If all Graphic subclasses support a Clone operation, then the GraphicTool can clone any kind of Graphic.

So in our music editor, each tool for creating a music object is an instance of GraphicTool that's initialized with a different prototype. Each GraphicTool instance will produce a music object by cloning its prototype and adding the clone to the score.

We can use the Prototype pattern to reduce the number of classes even further. We have separate classes for whole notes and half notes, but that's probably unnecessary. Instead they could be instances of the same class initialized with different bitmaps and durations. A tool for creating whole notes becomes just a GraphicTool whose prototype is a MusicalNote initialized to be a whole note. This can reduce the number of classes in the system dramatically. It also makes it easier to add a new kind of note to the music editor.

3 Domain Definitions

We will transform the document application into a set of corresponding domain definitions:

 Tool = GraphicTool | RotateTool | Graphic | . . . 

 Graphic = Staff | MusicalNote 

 MusicalNote = WholeNote | HalfNote 

The next step is to translate the domain definitions into a number of Elisa components.

4 Elisa components

Based on the domain definitions a set of related components can be derived.

All three domain definitions are selection domains. They specify a number of alternative domains. The implementation of selection domains is based on the concepts of categories.  The following component implements the Graphic = Staff | MusicalNote.

component Graphics;
type Graphic = category(Staff, MusicalNote);
     Draw(Graphic, Position) -> optional(boolean);
     Clone(Graphic)          -> optional(Graphic);
begin
     Draw(Staff:staff, position) = Draw(staff, position);
     Draw(note, position) = Draw(MusicalNote:note, position);

     Clone(Staff:staff) = Graphic:Clone(staff);
     Clone(note) = Graphic:Clone(MusicalNote:note);
end component Graphics;


The definitions in this component use  patterns for dynamic type matching to select the definition rule which corresponds to the matching type. 

The following component implements the MusicalNote = WholeNote | HalfNote:

component MusicalNotes;
type MusicalNote = category(WholeNote, HalfNote);
     Draw(MusicalNote, Position) -> optional(boolean);
     Clone(MusicalNote)          -> optional(MusicalNote);
begin
     Draw(WholeNote:Note, Position) = Draw(Note, Position);
     Draw(HalfNote: Note, Position) = Draw(Note, Position);

     Clone(WholeNote:Note) = MusicalNote:Clone(Note);
     Clone(HalfNote: Note) = MusicalNote:Clone(Note);
end component MusicalNotes;

The following component sketches an implementation for Staffs:

component Staffs;
type Staff;
     CreateStaff( )        -> Staff;
     Draw(Staff, Position) -> boolean;
     Clone(Staff)          -> Staff;
begin
            <<implementations of >>
     CreateStaff( ) = ...;
     Draw(staff, Position) = ...;
     Clone(staff) = ...;
end component Staffs;    

The following component is an example of a WholeNotes component:

 

component WholeNotes;
type WholeNote;
     CreateWholeNote( )        -> WholeNote;
     Draw(WholeNote, Position) -> boolean;
     Clone(WholeNote)          -> WholeNote;
begin
        <<implementations of >>
     CreateWholeNote( ) = ...;
     Draw(WholeNote, Position) = ...;
     Clone(WholeNote) = ...;
end component WholeNotes;

A similar component is for HalfNotes:

 

component HalfNotes;
type HalfNote;
     CreateHalfNote( )        -> HalfNote;
     Draw(HalfNote, Position) -> boolean;
     Clone(HalfNote)          -> HalfNote;
begin
       <<implementations of >>
     CreateHalfNote( ) = ...;
     Draw(HalfNote, Position) = ...;
     Clone(HalfNote) = ...;
end component HalfNotes;

Back Home Up Next

  Part 5: Design Patterns   Prototype

            
Introduction

Home | Highlights of Elisa | Integrating Different Paradigms | Getting Started with Elisa | Demo's  | What is Domain Orientation | Bibliography | Copyright | News | Contact | Contents

Language Description:

Lexical Elements | Basic Data Types and Expressions | Definitions | Streams | Backtracking | Statements and Special Expressions | Arrays | Lists | Descriptors | Components | Collections | Generic Components | Terms | Categories | Types | Built-in Definitions | Higher-order Definitions | External Interfaces | Index 

Data Structures: Sequences | Examples involving Lists | Trees | Graphs | Searching State Spaces | Language Processing | Knowledge Representations
Domain Modeling:

Domain Modeling | Concepts | Domain Definitions | Domain Operations | Domain Implementations | Systems | Case study: an Order processing system | Case study: an Airport Support system | Domain Orientation versus Object Orientation

Design Patterns:

Introduction | Abstract Factory | Builder | Factory Method | Prototype | Singleton | Adapter | Bridge | Composite | Decorator | Facade | Flyweight | Proxy | Chain of Responsibility | Command | Interpreter | Iterator | Mediator | Memento | Observer | State | Strategy | Template Method | Visitor 

 

click tracking

 

Send me your comments

 

This page was last modified on 13-11-2012 16:12:53   

free hit counter