Object Oriented Design

Today we’re getting back to the calculator controller and model we were working on last time:

package cs3500.lec08;

import java.io.InputStream;
import java.io.PrintStream;
import java.util.Scanner;

/**
 * Demonstrates a simple command-line-based calculator
 */
public class SimpleCalc1 {
  public static void main(String[] args) {
    Calculator model = new Calculator();
    CalcController controller = new CalcController(model);
    controller.go();
  }
}

class CalcController {
  private final Calculator model;
  private InputStream input;
  private PrintStream output;

  public CalcController(Calculator model) {
    this.model = model;
    this.input = System.in;
    this.output = System.out;
  }

  public CalcController(Calculator model, InputStream input, PrintStream output) {
    this.model = model;
    this.input = input;
    this.output = output;
  }

  public void go() {
    int num1, num2;
    Scanner scan = new Scanner(input);
    output.println("Enter a number: ");
    num1 = scan.nextInt();
    output.println("Enter another number: ");
    num2 = scan.nextInt();
    output.printf("The answer is: %d", model.add(num1, num2));
  }
}

class Calculator {
  public int add(int num1, int num2) {
    return num1 + num2;
  }
}

And the tests we wrote:

package cs3500.lec08;

import org.junit.Test;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;

import static org.junit.Assert.*;

/**
 * Created by jea on 1/31/17.
 */
public class CalcControllerTest {
  @Test
  public void go() throws Exception {
    Calculator model = new Calculator();
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    PrintStream printStream = new PrintStream(baos);
    ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream("6\n 8\n".getBytes());
    CalcController controller = new CalcController(model, byteArrayInputStream, printStream);
    controller.go();
    assertEquals(baos.toString(), "Enter a number: \n"
            + "Enter another number: \n"
            + "The answer is: 14");
  }
}

Now we have to change the Controller such that it uses the Appendable and Readable interfaces. This is a pretty simple change:

class CalcController {
  private Readable input;
  private Appendable output;

  public CalcController() {
    this.input = new InputStreamReader(System.in);
    this.output = System.out;
  }

  public CalcController(Readable input, Appendable output) {
    this.input = input;
    this.output = output;
  }

  public void go(Calculator model) throws IOException {
    int num1, num2;
    Scanner scan = new Scanner(input);
    this.output.append("Enter a number: \n");
    num1 = scan.nextInt();
    this.output.append("Enter another number: \n");
    num2 = scan.nextInt();
    this.output.append(String.format("The answer is: %d", model.add(num1, num2)));
  }
}

Now we have to change our test to match that:

public class CalcControllerTest {
  StringBuffer stringBuffer;
  StringReader stringreader;
  CalcController controller;

  @Before
  public void setup(){
    stringBuffer = new StringBuffer();
    stringreader = new StringReader("6\n 8\n");
    controller = new CalcController(stringreader, stringBuffer);
  }

  @Test
  public void go() throws Exception {
    controller.go(new Calculator());
    assertEquals(stringBuffer.toString(), "Enter a number: \n"
            + "Enter another number: \n"
            + "The answer is: 14");
  }

}

We also talked about the importance of using a general interface whenever you can I.E. using **List** instead of **ArrayList**. Luckily I designed my second assignment properly, so I won't have to do a big load of refactoring.

Next class we’re probably going over more about Views in MVC.