Goals

  • Planning a Program
    • Ideas
    • Requirements
    • Scope
  • UML: Universal Modeling Language
    • A Class
    • Fields
    • Methods
    • Relationships
  • Design Patterns
    • Factory
    • Decorator
  • Case Study: Asteroid

Resources

UML
Factory Pattern
Decorator Pattern

"An important work of architecture will create polemics." ~ Richard Meier

Ideas

Every program starts with an idea. Make sure you are working with a topic that you know well and is of interest to you.

Once you have chosen the main idea, research the domain it falls in:

  • Painting Application
  • Generative Art Application
  • Interactive Slideshow
  • Data Visualization
  • Videogame
    • Puzzle Game
    • Arcade Game
    • Action Game

Why does your application fit into this domain? What makes your application similar to existing applications in this domain, and what makes it different?

Requirements

What does your application need to do? Before programming you should make a detailed list of everything that will be included in your application.

Example for painting application:

  • Welcome / start screen
  • 3 brush tool buttons
  • 1 clear screen button
  • 1 save button
  • 3 brush tools
    • 1 regular brush
    • 1 splatter brush
    • 1 geometric brush

Scope

Put a time estimate next to your list of requirements. How long will each take? Give yourself lots of room for error.

Is it too much time? Maybe you can cut some requirements? Maybe the idea is beyond your skill level.

Whatever it is, make sure you have scoped your design to something manageable before you start working.

Choose an idea and research the domain.
Prepare a list of detailed requirements.
Scope the requirements to your skill level.

Universal Modeling Language

Disclaimer: this is a simplified way to write UML. There are in fact many ways to do UML diagrams, and we will only be looking at those features that are important to this course and multimedia programming.

If you'd like to learn more, take a look. This lecture should provide you with the basics.

Modeling a Class

A UML diagram for a class begins with the class name at the top. Clearly we are going to define a Moving Object class, followed by two sub-classes: Player and Enemy.

Adding Fields

Now we've added some fields to the classes, and notice this takes on the same structure as if we were to actually code the class. Define the class name, list the fields, list the methods.

The fields are marked with a dash because they are private. If they were public we would use a + sign.

Adding Methods

When adding methods it is important to encapsulate the method signature (parameters) and the return type. This should give you a clear idea of what the method will be doing based on: name and parameters (signature) and the return type.

Notice how the methods are public since they are written with the + sign.

Relationships

We're only concerned with showing our inheritance relationship in our UML diagrams. This is displayed by drawing a solid white arrow from the subclass pointing to the superclass.

Public fields and methods in UML are listed with a (+) sign.
Private fields and methods in UML are listed with a (-) sign.

Software Design Patterns

There are several ways to organize objects into a functioning application. Software design patterns is the name given to a number of ways of organizing classes and objects. The "Design Patterns" name comes from the book "Design Patterns: Elements of Reusable Object-Oriented Software" by Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides. This book describes a number of ways to organizes classes and objects so that they work well together and so that programmers can easily understand the organization of classes and objects.

As we wish to create more complex and interesting programs, the organization of data (objects and classes), and how those data interact gets more complex. The way we have dealt with this so far has been to have a number of arrays and ArrayLists holding the various objects in the main part of the program. The drawback of this idea of having everything in a big central bucket is that it becomes hard to tease apart one part of a program from another.

At some point we'd like those objects to simply take care of themselves. We're going to look at two useful software design patterns that organize complexity in an application.

Factory Pattern

In the factory pattern there are objects that need to be created with different properties and returned to some object that contains them. A Creator has a factory method to create a Product which can be though of as simply any object that needs creating. Subclasses of the Creator can override the factory method to return products of different types.

Example: Asteroids

A simplified version of this pattern is in the ArmedRocket.fire() method (in Inheritance PPT Slides). The fire() method is part of ArmedRocket, and generates a Missile object.
In the original game, aliens also generate missiles, which can destroy asteroids and your ship.
You can imagine an Alien class that also has a fire() method that generates a Missile

Example: Painting Application

A painting application may have several different instances of a BrushMovement and several different instances of BrushTips. A factory method in the main Brush class can be used to return a single Brush object that combines a BrushMovement with a BrushTip and returns the composite object to the main sketch where it can be added to an ArrayList.

Factory Patterns are useful for creating different objects that may be composed of one or more objects.

Decorator Pattern

The decorator pattern can be used to extend (decorate) the functionality of a certain object statically, or in some cases at run-time, independently of other instances of the same class, provided some groundwork is done at design time. This is achieved by designing a new decorator class that wraps the original class. This wrapping could be achieved by the following sequence of steps:

  1. Subclass the original "Component" class into a "Decorator" class (see UML diagram);
  2. In the Decorator class, add a Component pointer as a field;
  3. Pass a Component to the Decorator constructor to initialize the Component pointer;
  4. In the Decorator class, redirect all "Component" methods to the "Component" pointer; and
  5. In the ConcreteDecorator class, override any Component method(s) whose behavior needs to be modified.
This pattern is designed so that multiple decorators can be stacked on top of each other, each time adding a new functionality to the overridden method(s).

Example: Rewards in a Game

A Player can have a number of power-ups that alter the appearance of the player. As the instance of Player gets powerups, instances of PowerUp are created and are "wrapped around" the player. The player instance is now "decorated" with PoswerUp object. When the PowerUp fades, the player gets un-decorated.

Example: Window systems

As an example, consider a window in a windowing system. To allow scrolling of the window's contents, one may wish to add horizontal or vertical scrollbars to it, as appropriate. Assume windows are represented by instances of the Window class, and assume this class has no functionality for adding scrollbars. One could create a subclass ScrollingWindow that provides them, or create a ScrollingWindowDecorator that adds this functionality to existing Window objects.

Both Decorator and Factory design patterns can be combined and are closely related.
The Decorator Pattern is useful when an object needs to have several different objects added to it.

Case Study: Asteroids

Everyone should be familiar with the game Asteroids, but how would one go about coding it? Let's take a look at the requirements. Not that this is a bit more complex than the example in the Inheritance PPT Slides.

Classes:

  • MovingObject class
  • Player class
  • Missile class
  • Enemy class
  • Asteroid class
  • AsteroidFactory class

Functionality:

  • Player is created and can shoot missiles
  • Asteroids are created from the AsteroidFactory and added a list of active asteroids
  • Enemies are created and added to the list of active enemies
  • A Player, Enemy, Missile, and Asteroid are all subclasses of MovingObject
  • MovingObject will detect collisions between instances of MovingObject
  • MovingObject will store and update the location of the instance
  • Each subclass of MovingObject will implement a handleCollision method
  • The handleCollision method will be overridden and perform the correct function
  • There will be player lives and score displayed on the screen
  • There will be a pause button
  • ...

Basic (incomplete) UML View:

Notice with the UML diagram that if it were complete we would have everything we needed to know in order to create this game. We would know what classes, fields, methods and everything else to implement. It's highly recommended to always create a detailed UML diagram for any application that goes beyond 2 or 3 classes or has more than a few simple functions.