SDSU CS 535: Object-Oriented Programming & Design
Fall Semester, 1997
Doc 24, Missing Responsibilities and Menus

To Lecture Notes Index
San Diego State University -- This page last updated 24-Nov-97

Contents of Doc 24, Missing Responsibilities and Menus

  1. References
  2. Missing Classes Responsibilities
    1. Menu Class
    2. Menu Example with Counter
  3. Reducing the Intelligence of Main
    1. Callbacks for the Menu
    2. Now the Menu and Example Classes
      1. Sample Main Program
      2. MenuItem
      3. Menu
      4. Counter class
      5. ASCIICounterView

References


Java 1.1 JDK documentation


Doc 24, Missing Responsibilities and Menus Slide # 1

Missing Classes Responsibilities

Basic Scenario for Room Assignment

User starts program

Program displays main menu

User selects schedule new one time event

Program requests required information for the event

etc.
Who does the work ?

Which class displays the menu?

Which class requests required information for the event?

Doc 24, Missing Responsibilities and Menus Slide # 2
Common Answer
class Driver
   {
   public static void main( String args[] )
      {
      System.out.println( "Welcome to Room Scheduler");
      System.out.println( "-------------------------");
      System.out.println( "Please select one of the following:");
      System.out.println( "");
      System.out.println( "1. Find an event");
      System.out.println( "2. Schedule an event");
      System.out.println( "3. Quit");
      int request = Console.readInt( "Your Selection: " );
      
      // etc
      }
   }


Doc 24, Missing Responsibilities and Menus Slide # 3
Improved Version

class Driver
   {
   public static void main( String args[] )
      {
      int userSelection = showMainMenu();
      // etc
      }
   
   public static int showMainMenu()
      {
      Console.println( "Welcome to Room Scheduler");
      Console.println( "-------------------------");
      Console.println( "Please select one of the following:");
      Console.println( "");
      Console.println( "1. Find an event");
      Console.println( "2. Schedule an event");
      Console.println( "3. Quit");
      int request = Console.readInt( "Your Selection: " );

      while ( (request >3) || (request < 1 ))
         {
         Console.println( "Your selection must be 1, 2, 3");
         request = Console.readInt( "Your Selection: " );
         }
      return  request;
      }
   }


Doc 24, Missing Responsibilities and Menus Slide # 4
What is the Abstraction?
Where is the code reuse?


Doc 24, Missing Responsibilities and Menus Slide # 5

Menu Class

import java.util.Vector;
import sdsu.io.Console;

class Menu
   {
   Vector menuItems = new Vector();
   String menuMessage;
   
   public void add( String newMenuItem )
      {
      menuItems.addElement( newMenuItem );
      }
   
   public void remove( int menuItemIndex )
      {
      menuItems.removeElementAt( menuItemIndex );
      }
   
   public void setMessage( String message )
      {
      menuMessage = message;
      }

   private void displayMenuItems()
      {
      for ( int index = 1; index <= menuItems.size();index++)
         {
         Console.println( "" + index + ". " + 
               menuItems.elementAt( index - 1 ));
         }
      }
   

Doc 24, Missing Responsibilities and Menus Slide # 6
//Menu Class continued
   public int show()
      {
      Console.println( menuMessage );
      Console.println(  );
      
      displayMenuItems();

      int request = Console.readInt( "Your Selection: " );

      while ( (request > menuItems.size() ) || (request < 1 ))
         {
         Console.println( 
            "Your selection must be between 1 and " + 
            (menuItems.size() - 1) );

         request = Console.readInt( "Your Selection: " );
         }

      return  request;
      }

   }

Doc 24, Missing Responsibilities and Menus Slide # 7

Menu Example with Counter


See Doc 23 slide 9 for Counter code
class Test
   {
   public static void main( String args[] )
      {
      Menu counterMenu = new Menu();
      counterMenu.add( "Increase Counter" );
      counterMenu.add( "Decrease Counter" );
      counterMenu.add( "Display Counter" );
      counterMenu.add( "Quit" );
   
      Counter testCount = new Counter();
   
      int userSelection;
      do
         {
         userSelection = counterMenu.show();

         switch (userSelection)
            {
            case 1: 
               testCount.increase();
               break;
            case 2:
               testCount.decrease();
               break;
            case 3:
               Console.println( "Counter value = " + testCount);
               break;
            }
         }
      while (   userSelection != 4 );
      }   
   }

Doc 24, Missing Responsibilities and Menus Slide # 8

Reducing the Intelligence of Main


The main program still is in control of the order of execution of the program

Callbacks for the Menu


In many systems menus are implemented using callbacks

Each menu item is provided with a function, the callback

The callback function is called by the menu when ever the menu item is selected


Since Java does not have functions, need an object and method for a callback

Use java.lang.reflect classes to obtain an object-oriented callback

(Note: AWT does not use object-oriented callback it uses Listeners)

Object-oriented callbacks are slow in Java,
They are fine for user-interface components, but not other parts of code

I use object-oriented callbacks here just because I though they would take fewer slides to illustrate

(But there is one mysterious slide)

Doc 24, Missing Responsibilities and Menus Slide # 9
Class java.lang.reflect.Method

This class acts like a reference to a method of a class
import java.lang.reflect.Method;

class Foo
   {
   public void bar()
      {
      System.out.println( "Hi Mom" );
      }
   }

class TestMethod
   {
   public static void main( String[] arg) throws Exception
      {
      Foo test = new Foo();
      Class classOfTest = test.getClass();
      Class[] classOfBarsParameters = new Class[0];
      
      Method bar = 
         classOfTest.getMethod( "bar", classOfBarsParameters);
      
      bar.invoke( test, new Class[0]);
      }
   }

Doc 24, Missing Responsibilities and Menus Slide # 10

Now the Menu and Example Classes

MenuItem

Represents a individual item in a menu
public MenuItem( String menuText, 
                        Object callBackObject, 
                        String callBackMethod) 

menuText - string shown on screen for this item in menu

callBackObject
callBackMethod
String representation of method that will be sent the object callBackObject when this menu item is selected by the user
Menu
Represents a menu
public void add( MenuItem newMenuItem )
Adds a new menu item to the menu
public void show()

Actives the menu, menu will prompt user for selections and perform selected actions until user selects "Quit" or another object sends "hide" to the menu


Doc 24, Missing Responsibilities and Menus Slide # 11
Counter (extends Observable)

A simple counter that extend Observable

Main methods besides Observable methods:
increase
decrease
reset
toString()
ASCIICounterView (implements Observer)

Main method:
update - prints out the current value of the counter that it observes


Doc 24, Missing Responsibilities and Menus Slide # 12

Sample Main Program

class SampleMainProgram
   {
   public static void main( String args[] ) throws Exception
      {
      Counter count = new Counter();
      count.addObserver( new ASCIICounterView( ) );

      Menu counterMenu = new Menu();

      // Note menu automatically adds a Quit Menu Item

      counterMenu.add( 
         new MenuItem("Increase Counter", count, "increase" ));

      counterMenu.add( 
         new MenuItem("Decrease Counter", count, "decrease" ));

      counterMenu.add( 
         new MenuItem("Reset Counter", count, "reset" ));

      counterMenu.show();
      }
   }


Doc 24, Missing Responsibilities and Menus Slide # 13
Sample Run of Program

---------------------------
1. Exit
2. Increase Counter
3. Decrease Counter
4. Reset Counter
Your Selection: 2

The current count is: 1

---------------------------
1. Exit
2. Increase Counter
3. Decrease Counter
4. Reset Counter
Your Selection: 2

The current count is: 2

---------------------------
1. Exit
2. Increase Counter
3. Decrease Counter
4. Reset Counter
Your Selection: 1

Doc 24, Missing Responsibilities and Menus Slide # 14

MenuItem

import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;

class MenuItem
   {
   String text;
   Object callBackObject;
   Method callBackMethod;
   
   public MenuItem( String menuText, 
                        Object callBackObject, 
                        String callBackMethod) 
         throws  NoSuchMethodException
      {
      text = menuText;
      this.callBackObject = callBackObject;
      
      Class callBackClass = callBackObject.getClass();
      Class[] parameters = new Class[0];
      this.callBackMethod = callBackClass.getMethod(    
                              callBackMethod, parameters); 
      }
   
   public String getText()
      {
      return text;
      }
   
   public String toString()
      {
      return text;
      }


Doc 24, Missing Responsibilities and Menus Slide # 15
//MenuItem continued

   public void invokeCallBack()
      {
      try
         {
         callBackMethod.invoke( callBackObject, new Class[0] ); 
         }
      catch ( IllegalAccessException violatedMethodProtection )
         {
         System.err.println( "MenuTime: " + 
               violatedMethodProtection );
         }
      catch ( InvocationTargetException callBackException )
         {
         System.err.println( "MenuTime: " + callBackException );
         }   
      }
   }

Doc 24, Missing Responsibilities and Menus Slide # 16

Menu

class Menu
   {
   Vector menuItems = new Vector();
   boolean repeatMenu = true;
   
   public Menu()
      {
      try
         {
         menuItems.addElement( "Null Object for 0'th index" );
         menuItems.addElement( 
               new MenuItem("Exit", this, "hide"));
         }
      catch ( NoSuchMethodException canNotHappen)
         {
         System.err.println( "Exception in Menu: " + 
                              canNotHappen);
         }
      }
      
   public void add( MenuItem newMenuItem )
      {
      menuItems.addElement( newMenuItem );
      }
   
   public void hide()
      {
      repeatMenu = false;
      }
      

Doc 24, Missing Responsibilities and Menus Slide # 17
// Menu Continued
   public void show()
      {
      do 
         {
         MenuItem selectedMenuItem =  
            getUsersMenuSelection();

         selectedMenuItem.invokeCallBack();
         }
      while ( repeatMenu );
      }
      
   private MenuItem getUsersMenuSelection()
      {
      Console.println( "\n\n---------------------------");   
      int request = displayMenuItems();

      while ( (request >= menuItems.size() ) || (request < 1 ))
         {
         Console.println( "Your selection must be between 1 and " 
                           + (menuItems.size() - 1));
         request = displayMenuItems();
         }
   
      return (MenuItem) menuItems.elementAt( request);
      }
   
   private int displayMenuItems()
      {
      for ( int index = 1; index < menuItems.size();index++)
         {
         Console.println( "" + index + ". " + 
                     menuItems.elementAt( index ));
         }
         return Console.readInt( "Your Selection: " );
      }
   }

Doc 24, Missing Responsibilities and Menus Slide # 18

Counter class

class Counter extends Observable {
   private int count = 0;
   
   protected void changeNotify() {
      setChanged();
      notifyObservers( );
   }

   public void increase()  { 
      count++;
      changeNotify();
   }

   public void decrease()  { 
      count--;
      changeNotify();
   }

   public void reset()  { 
      count = 0;
      changeNotify();
   }
      
   public int value() { 
      return count; 
   }

   public String toString()  { 
      return String.valueOf( count ); 
   }
}



Doc 24, Missing Responsibilities and Menus Slide # 19

ASCIICounterView

class ASCIICounterView implements Observer  
   {
   public void update( Observable sender, Object message ) 
      {
      System.out.println( "\nThe current count is: " + 
                              ((Counter) sender) );
      }
   
   }



visitors since 24-Nov-97