Index
Video


Video accompanying this page...

Overview


This page will show us how to take a design and turn it into program code.

We'll use our recently completed Example #2 from this chapter.

Turning Design Into Code


Recall our third normal form (3NF) design outcome as shown here.

Our coding to-do list is:

  • Code three classes (abstract class Turtle, and concrete subclasses SimpleTurtle and AnimatedTurtle)
  • In the abstract Turtle class we add an instance variable named shape of type Shape
  • We will add four delegated methods to class Shape
  • We will code two methods (turn and forward) to class Shape that may be overridden by subclass methods
  • Finally we code the logic for the draw methods


Now let's now turn this design into program code.
         Turtle
           |
  ---------+---------
  |                 |
Simple           Animated
Turtle            Turtle

    Turtle
------------------------
(components/ivars)
shape
(behaviors/methods)
moveBy*
scale*
setColor*
setStyle*
turn
forward

    SimpleTurtle
------------------------
drawOn*

    AnimatedTurtle
------------------------
drawAnimationOn

*delegated method
Component "shape" is object type "Shape"
Add the three new classes that we need to code.
public class Turtle {
	//...
}

public class SimpleTurtle extends Turtle {
	//...
}

public class AnimatedTurtle extends Turtle {
	//...
}
We came up with one component "shape":

(components/ivars)
shape

We code that in the normal way, in the Shape class.
public class Turtle {

	//---------------------------------------------------
	// Instance Vars
	
	private Shape shape;

	//...

}
We now code a set the methods we found that could be classified as delegated methods

A delegated method requires minimal coding, and we trust that the target type, and method we are calling (e.g. method moveBy in object type Shape) is fully pre-tested
//---------------------------------------------------
// Instance Methods (Delegated)

public void moveBy(Point vector) {
	// Delegate to component "shape"
	this.shape.moveBy(vector);
}

public void scale(double factor) {
	// Delegate to component "shape"
	this.shape.scale(factor);
}

public void setColor(Color color) {
	// Delegate to component "shape"
	this.shape.setColor(color);
}

public void setStyle(String style) {
	// Delegate to component "shape"
	this.shape.setStyle(style);
}
We now code a set the methods we found that could be classified as delegated methods.

A delegated method is simply a method where we call the same method on the component. A couple examples are highlighted.
//---------------------------------------------------
// Instance Methods (Coded)

public void turn(int angleAsDegrees) {
	this.direction = new Direction(angleAsDegrees);
}

public void forward(int aDistance) {
	Point p1, p2;
	p1 = this.location;
	p2 = this.nextPointFor(aDistance);
	p1.drawTo(p2, this.pen, this.getColor());
	this.location = p2;
}

boolean isAnimated() {
	return this.rest > 0;
}
There is just a little coding we need to do for SimpleTurtle
package model.turtle;

import java.awt.Graphics2D;

public class SimpleTurtle extends Turtle {
	
	public void drawOn(Graphics2D canvas) {
		this.getShape().drawOn(canvas);
	}

}
And also we do just a little coding for AnimatedTurtle
package model.turtle;

import java.awt.Graphics2D;

public class AnimatedTurtle extends Turtle {
	
	public void drawAnimationOn(Graphics2D canvas) {
		this.getShape().drawAnimationOn(canvas);
	}
	
	@Override
	public void forward(int aDistance) {
		//We are animated, so we want to pause between steps to animate
		sleep(this.getRest());
		super.forward(aDistance);
	}

}


Object Initialization


A good design provides user-friendly object initialization -- spoil are object users.

There are many approaches to initialization. We'll look at an example.

With this approach, the user will be able to call one method to initialize the desired shape. We will provide three methods shown below (in the Turtle class).

Add three convenience methods that initialize the Turtle to a given shape. This will be user-friendly for our object user.
/**
Set shape to circle with provided center (x, y)
and provided radius
*/
public void setAsCircular(int x, int y, int radius) {
	this.shape = Circle.fromXYRadius(x, y, radius);
}

/**
Set shape to rectangle with provided leftX, topY,
width and height
*/
public void setAsRectangular(int leftX, int topY,
                             int width, int height) {
	this.shape
		= Rectangle.fromLeftTopWidthHeight(leftX, topY, width, height);
}

/**
Set shape to ellipse with provided center (centerX, centerY)
and major axis and minor axis (a and b)
*/
public void setAsElliptical(int centerX, int centerY, int a, int b) {
	this.shape = Ellipse.fromCenterAB(400, 400, 100, 50);
}
Here we initialize turtles of various shapes and types (simple or animated).

We've made it user friendly so that we just need to call a 'set' method to set the desired shape.
SimpleTurtle simpleTurtle = new SimpleTurtle();
simpleTurtle.setAsCircular(200, 100, 5);
simpleTurtle.drawOn((Graphics2D)g);

simpleTurtle = new SimpleTurtle();
simpleTurtle.setAsRectangular(100, 50, 300, 200);
simpleTurtle.drawOn((Graphics2D)g);

AnimatedTurtle animatedTurtle = new AnimatedTurtle();
animatedTurtle.setAsElliptical(500, 300, 20, 10);
animatedTurtle.drawAnimationOn((Graphics2D)g);