SE450: Lecture 3 (More OO and Java/Intro to Patterns)

Contents [0/22]

Overview of Today's Class [1/22]
Homework: Discussion [2/22]
UML: Interaction Diagrams [3/22]
UML: Sequence Diagrams [4/22]
UML: State Diagrams [5/22]
Patterns: Intro to Patterns [6/22]
Patterns: Classification and Organization [7/22]
Patterns: GoF principles [8/22]
Strategy: Definition [9/22]
Strategy: Example [10/22]
Strategy: Code [11/22]
Patterns: Another Strategy Example [12/22]
Java: Identifiers [13/22]
Java: coercion [14/22]
Java: Data [15/22]
Java: Reference Types [16/22]
Java: Call by ? [17/22]
Java: Classes [18/22]
Java: Class Declaration [19/22]
Java: Object Creation [20/22]
Java: Types of Storage [21/22]
Homework: Assignment #3 [22/22]

Overview of Today's Class [1/22]

Homework Discussion

UML object diagrams (sequence, collaboration, state)

Intro to patterns, The Strategy Pattern

More Java/00

Homework: Discussion [2/22]

Sample solution

UML: Interaction Diagrams [3/22]

Describes how a group of objects work together. Shows the objects and the messages passed between them. Models dynamic behavior.

Comes in two flavors:

These are very good at showing the collaborations between objects.

UML: Sequence Diagrams [4/22]

Shows:

Example: p 37

UML: State Diagrams [5/22]

State

Initial States

Final States

Transitions - moving from state to state based on events

event [guard]/actions

Example: p 39,40

The State design pattern represents this behavior

Patterns: Intro to Patterns [6/22]

What is a pattern?

"Each pattern describes a problem which occurs over and over again in our environment, and then describes the core of the solution to that problem, in such a way that you can use this solution a million times over, without ever doing it the same way twice"

History: Architecture background - Christopher Alexander discovered and cataloged patterns in architecture.

Purpose:

Goals

Patterns:

Used in:

The GoF book documents 23 of these patterns.

To define a pattern, need the following:

In practice, we will use the following template

Patterns: Classification and Organization [7/22]

Patterns are divided up several ways:

Class vs. Object

Creational vs. Structural vs. Behavioral

Purpose
Creational Structural Behavioral
Scope Class Factory Method (107) Adapter (class) (139) Interpreter (243)
Template Method (325)
Object Abstract Factory (87)
Builder (97)
Prototype (117)
Singleton (127)
Adapter (object) (139)
Bridge (151)
Composite (163)
Decorator (175)
Facade (185)
Flyweight (195)
Proxy (207)
Chain of Responsibility (223)
Command (233)
Iterator (257)
Mediator (273)
Memento (283)
Observer (293)
State (305)
Strategy (315)
Visitor (331)

Patterns: GoF principles [8/22]

In the GoF patterns book, we see a few principles repeated again and again. These principles shape the pattern design and intent in most of the patterns we will study. They are:

The last one is the opposite of focusing on the cause of redesign. Instead of focusing on what might force a change to a design, consider what you want to be able to change without redesign. The focus is on encapsulating the concept that varies, a theme of many design patterns [GoF p29]

Strategy: Definition [9/22]

Strategy: Example [10/22]

From chapter 14 of Design Patterns Explained, we have an example for a Tax calculation. The classes are as follows:

Context = SalesOrder

CalcTax = Strategy

USTax, CanTax = ConcreteStrategy

Others: Configuration, TaskController

Strategy: Code [11/22]

SalesOrder, the Context

package example.strategy;

public class SalesOrder {

    // makes a bogus sales order and returns the tax
    public double calcTax() {
	String item1 = "book";
	String item2 = "gum";
	double item1qty = 2;
	double item2qty = 4;
	double item1price = 14.32;
	double item2price = 0.34;
	double totalTax = 0.0;
	
	CalcTax taxer = Configuration.getTaxer();

	totalTax += taxer.taxAmount(item1, item1qty, item1price);
	totalTax += taxer.taxAmount(item2, item2qty, item2price);

	return totalTax;
    }
}
            

CalcTax, the Strategy

package example.strategy;

public interface CalcTax {

    public double taxAmount(String item, double qty, double price);

}
            

USTax, CanTax = ConcreteStrategies

package example.strategy;

public class USTax implements CalcTax {

    public double taxAmount(String item, double qty, double price) {

	// crude algorithm
	if("book".equals(item)) {
	    return qty * price * 0.04;
	} else {
	    return qty * price * 0.05;
	}
    }

}
package example.strategy;

public class CanTax implements CalcTax {

    public double taxAmount(String item, double qty, double price) {

	// crude algorithm, Canada much more expensive than US!
	if("book".equals(item)) {
	    return qty * price * 0.4;
	} else {
	    return qty * price * 0.5;
	}
    }

}

            

Others: Configuration

package example.strategy;

public class Configuration {

    // default to US
    private static CalcTax taxer = new USTax();

    public static CalcTax getTaxer() {
	return taxer;
    }

    public static void setTaxer(String name) {
	if("can".equals(name)) {
	    taxer = new CanTax();
	} else {
	    taxer = new USTax();
	}
    }

}
    

TaskController: the driver

package example.strategy;

package example.strategy;

public class TaskController {

    public static void main(String args[]) {

	SalesOrder order = new SalesOrder();

	Configuration.setTaxer("us");
	System.out.println("The tax for the U.S. is " + 
			   order.calcTax());

	Configuration.setTaxer("can");
	System.out.println("The tax for Canada is " + 
			   order.calcTax());
 
    }

}
           
            

Patterns: Another Strategy Example [12/22]

From the book, page 297-298

The Strategy: Function

interface Function {
   double apply(double x);
}

The Concrete Strategies: Sine, Cosine

public class Cosine implements Function {
  public double apply(double x) {
    return Math.cos(x);
  }
}
public class Sine implements Function {
  public double apply(double x) {
    return Math.sin(x);
  }
}

The Context: MultiPlotter

import java.awt.*;

public abstract class MultiPlotter extends Plotter {

  abstract public void initMultiPlotter();

  public void init() {
    super.init();
    initMultiPlotter();
  }

  final public void addFunction(Function f, Color c) {
    if (numOfFunctions < MAX_FUNCTIONS && f  !=  null) {
      functions[numOfFunctions] = f;
      colors[numOfFunctions++] = c;
    }
  }

  protected void plotFunction(Graphics g) {
    for (int i = 0; i < numOfFunctions; i++) {
       if (functions[i] != null) {
         Color c = colors[i];
         if (c != null)
           g.setColor(c);
         else
           g.setColor(Color.black);
           for (int px = 0; px < d.width; px++) {
              try {
                double x = (double) (px - xorigin) / (double) xratio;
                double y = functions[i].apply(x);
                int py = yorigin - (int) (y * yratio);
                g.fillOval(px - 1, py - 1, 3, 3);
              } catch (Exception  e) {}
           }
       }
    }
  }


  public double func(double x) {
    return 0.0;
  }

  protected static int MAX_FUNCTIONS = 5;
  protected int numOfFunctions = 0;
  protected Function functions[] = new Function[MAX_FUNCTIONS];
  protected Color colors[] = new Color[MAX_FUNCTIONS];
}

And the implementation of the MultiPlotter


import java.awt.Color; 

public class PlotSineCosine extends MultiPlotter {
  public void initMultiPlotter() {
    addFunction(new Sine(), Color.green); 
    addFunction(new Cosine(), Color.blue); 
  }
}

Java: Identifiers [13/22]

One of the major advantages of assembly language over machine language is the ability to refer to data memory using names, or identifiers.

Some important properties of identifiers:

References are sometimes referred to as boxed values.

Plain values are then called unboxed.

A declaration is a statement that, when executed, binds a name to a data-memory location.

The scope of a declaration is the text of the program in which the binding has effect.

Lifetime is a dynamic property. Scope is a static property.

Value/Reference is really part of the type, but it is worth discussing separately.

A variable of value type T (synonym: unboxed type) stores a value of type T.

A variable of reference type T (synonyms: pointer type, boxed, type) stores a pointer to a value of type T.

In java, all base-type identifiers hold values; all object-type identifiers hold references.

int x = 0;         // value type (unboxed)
String s = "dog";  // reference type (boxed)

primitive types are

Java has wrapper classes in the java.lang package that wrap all the primitive types.

String in Java is not a primitive type, but a class. However it behaves like a special class, allowing string concatination using primitive operators.

In Java, objects are always boxed (ie, identified by reference).

In C++, objects of any class may be boxed or unboxed. For example:

string* sp = new string("dog"); // boxed (requires delete)
string  s  = string("cat");     // unboxed (no delete needed)

Java: coercion [14/22]

There are many types of conversions that take place in Java:

These will show up in

Widening and narrowing of references is done via casting (later).


public class Coercion {

    final static int X = 33;

    public static void main(String args[]) {
	int x = 5;
	double y = 4.5;
	System.out.println("x + y = " + (x + y)); // widening
	
	//int z = y; (narrowing - not allowed)
	int z = (int)y; // lossy
	short xx = X; // not lossy, java will do this for you
	// short xy = z; // lossy - not allowed

    }

}

Java: Data [15/22]

Data is stored in memory at runtime.

Some important properties of data:

The type of data indicates the meaning of the bits in memory.

The lifetime of data begins when memory is allocated; the lifetime ends when memory is de-allocated.

Data that may change is called mutable.

Data that may not change is called immutable (some synonyms are constant and final).

Java: Reference Types [16/22]

References in Java are 32-bit pointers. They hold indirect references to Object or Array instances

Java treats an Array of any type as an Object

Reference types (objects) are created on the heap. Unlike C++, there are no ways to manipulate this reference to point to different places in memory, or perform pointer arithmetic on it.

Items created on the heap are garbage collected. Since Java 1.2, you have been able to have some control over when things are GC'd using the Reference Object API. But even with some control over GC, Java far from a Real Time environment.

Primitive types are created on the stack

Java: Call by ? [17/22]

What happens here?

            public class C1 {
                public void inc(int i) { i++; }
            }
            
            C1 c1 = new C1();
            int k = 1;
            c1.inc(k);
            System.out.println(k);
            
        

vs.

            public class C2 {
                public void inc(Point p) {p.x++; p.y++; }
            }
            
            C2 c2 = new C2();
            Point p = new Point(10.0,10.0);
            c2.inc(p);
            System.out.println(p);
            
        

So what is going on?

Call by reference vs Call by value vs "Call by sharing" (from Kim Bruce)

Java: Classes [18/22]

What is a class?

What is the relation between classes and objects?

Which of an object's properties are fixed by its class?

An object is an instance of a class.

The class fixes: the name and type of fields and methods, and the value of methods. Fields are data, methods are code used to manipulate the data.

The only thing that varies for each instance are the field values.

Java: Class Declaration [19/22]

For classes:

[ClassModifiers] class ClassName [extends SuperClass]
                [implements Interface1, Interface2, ...] {
                    ClassMember Declarations
                }

Modifiers can be

For methods:

[MethodModifiers] ReturnType MethodName([ParameterList]) {
                Statements
                }

Modifiers can be

For fields only

Note that final has completely different meanings in different contexts. Remember, a final parameter is not like const in C++

Java: Object Creation [20/22]

How are objects specified and created?

Prototype-based languages allow the static description of objects (as literal values). To create new objects at runtime, they use cloning. JavaScript is an example of a prototype-based language. It doesn't distinguish between classes and instances. Any object can be used to create a new object by cloning it.

In JavaScript, an object can go from String to Integer to String without being re-instantiated.

Class-based language allow the static description of classes. To create objects at runtime, use a constructor.

When a reference type is created, only a storage location for the reference is made, not the objects themselves.

        Point p;            // reference variable of type Point
        p = new Point();    // new Instance of point
        int[] ia;           // reference variable of array of integers
        ia = new int[3];    // an array of size 3
        Point[] pArray;     // reference variable of array of Points
        pArray = new Point[3];  // an array of Points.  They are all null!
        // can use an array initializer
        ia = {1,2,3};
        pArray = { new Point(), new Point() } ;
        
        

Java: Types of Storage [21/22]

What are class fields, object fields and method variables?

In java, a class field is also called static field.

Object fields are also called instance fields.

When one discusses a field, one is usually referring to an instance field.

Class fields are stored once for the class. Lifetime is life of the class in memory. All instances (if any) share the same data.

Class fields are stored statically. For our purposes they are immortal.

Instance fields are stored once for the object. Lifetime is life of the object. All instances have separate data.

Instance fields are stored in an object record on the heap. Heap allocation is indicated by the use of new, which returns a reference to the heap. Java objects are garbage collected: an object dies when the last reference to that object dies. (The memory is reclaimed when the garbage collection thread removes the object that the reference referred to).

Class fields and methods are referred to in java by ClassName.classMethod(Parameters) or ClassName.classField, or by an object reference: objectReference.classMethod(Parameters) or objectReference.classField. Instance fields and methods have to be referred to by objectReference.instanceMethod(Parameters) or objectReference.instanceField. You should use the ClassName, not an objectRefrence to access class fields and methods.

Class fields can be initialized with default values, in an initializer in its declaration, or in a static initialization block (like a class initialization block, but it is run once for all classes). Do not use the constructor.

Method variables (local variables and parameters) are stored once for each method invocation. Lifetime is life of the method invocation.

Method variables are stored in an activation record (or frame) on the stack.

In practice, the stack runs out of space when the OS runs out of space. The heap runs out of space when the heap size is reached. You can control this with -Xms and -Xmx options on the java command line.

Homework: Assignment #3 [22/22]

Read Jia chapter 6.

Skim this article on junit.

And read this tutorial of junit.


Goal - to implement the Strategy pattern.

Update your homework #2 solution (using any parts that you would like) to use the Strategy pattern. Put it in the package se450.studentid.hw3 where studentid is your DePaul ID.

Assume that you have a file of flight records, like last week. It is a text file in which each line contains a single record, and each record consists of the following colon-delimited fields:

Airline Code: Airplane Type: Flight Number : Departing Airport : Arriving Airport: Time: # of passengers

A sample line is as follows:

ASA:B73Q:144:ORD:SFA:13:230

Assume that the time is just a whole hour in 24HH format, as an integer. The passenger count is also an integer. All other records are strings

You are going to implement three different pricing models for an airline, and calculate the revenue generated by each strategy (model) for the total of the airline's flights in the file.

The Strategy pattern is a good example of Subtyping. In other words, we are programming to an interface, not Subclassing, in which case we would be using an abstract class. So create a generic Strategy interace that is part of the hw3 package, in my case it would be se450.mwright1.hw3.Model. It will have one method, long getRevenue(List flights) which takes a List of flights as its only parameter and returns a long of whole dollars.

Then create 3 different concrete strategies, SinglePrice, TwoClasses, and MultiClass. These will all implement the Model interface. The Model interface should define a constant for the base ticket price ($300), and the fixed cost to fly a plane ($50,000). For now, we'll ignore distance and different plane sizes.

The three models will behave as follows:

Treat the Main program as the Context. In other words, it will have to switch between the ConcreteStrategies as needed.

Use the Airline and Flight classes from last week. The Main class's main() method should take two command line arguments, the filename and the airline code to be processed and return results for all parts of the program. The program should return the total revenue for the day's flights for the airline code passed in. Proper error handling is expected for conditions like no file found, no flights for an airline, etc. Include a good usage statement if the program is invoked with no arguments.

Grading is as follows:

Continue to ask questions on the discussion list

Submit a zip file that contains all your source code and grader.txt. As always, make sure that your source is in the correct package for your code. The grader will take off points if you have extra or incorrect directories included.

To test your homework, take the zip file, move it to a new directory, unzip it, and then run

javac -classpath . se450\studentid\hw3\Main.java
java -classpath . se450.studentid.hw3.Main

On Unix, you will need to change your \ to /. If this doesn't work, your homework submission isn't correct! (and you will miss the correct submission points on your homework)

You can use the grader.txt file from the previous homework.

Due next Monday(1/27) at 5:30 PM


Revised: 1/19/2003