CS680 hw5 MVC TrainSet, Factory Methods, DI

Due Sunday, Oct. 26,  files by midnight in UNIX cs680/hw5 directory.

Study the supplied trainset project, from the solution to hw2 (zip). As you know, it now has model and presentation packages, but still has some non-MVC properties we can fix.

1. In hw2, we fixed the unwanted reference from TrainSet (model) to TrainSystemGUI (GUI). However, as some noted, there was also a reference from Train (model) to Accelerator (GUI), and it is still there. First fix this. We want the Accelerator to set the train's speed (in the model) at the appropriate time, when the user has finished sliding the slider. Note the unused stateChanged method in Accelerator: find out about this starting from the Sun Javadoc, and then put it to use.

2. After 1., the only remaining interclass reference from model to GUI involves the Animator. Fix this up following hw3's solution for Pong, or your own observer treatment if you want.

3. Use cases. By playing with trainset, list its use cases, in memo.txt.You can ignore the file commands. Then for each use case, determine the code that executes on each initial user action. Define a ControllerInterface, following the general form of F&F, p. 542, but include a one-line comment on each action. List your interface in memo.txt. Implement it in your project. Use it for actions in TrainsetApp too.

4. In one case, the listener class is an inner class.  Does it need to be an inner class, or could it just as well be a nested class (static inner class)?: explain the difference and the needs of this class, in memo.txt.

5. Now we have separated out the controller code, so the rest of the presentation code should be the view. The view should call no mutators in the model. Is this true? Note that the startup code is not pure view.
a. List the mutators (methods) for the model. Note that now the model is all in its own package, so a search for public methods (including static methods other than main) finds the model API.You can use the eclipse class display in Package Explorer.
b. For each mutator, find its callers (list the classes that call it), and determine any cases of view code calling a mutator.
c. Public constructors can change the state of things, although if the constructed object is not connected to anything else, it's normally harmless (or it's just confusing). In this system, what model objects can be constructed by code outside the model package? Are any actually constructed other than TrainSet?
d. Some getters allow the caller to change the model. For example, List<TrainOnTrack> getAllTrains sounds dangerous: can't the caller add a train to the list and change the TrainSet? Explain. TrainSet.getTimer() returns a mutable object that is part of the model state. Are there any other getters like this?
e. Based on these observations, do you have any suggestions for ways to tighten up this model?

6. Finally, for real purity, we would like to get rid of the paint methods, and the train color. Do this at least for the Train/TrainOnTrack classes. Define a TrainDisplay class that represents the GUI for an individual train-on-track, including its color and a reference to its TrainOnTrack. There should be a list of these TrainDisplay objects that the GUI uses for painting. Now we have claim to pure MVC, right? Discuss any further deviations from MVC that you see in memo.txt.

7. Factory methods. Refactor the current factory method for Layout into a separate class LayoutFactory. Refactor it further so that LayoutFactory is "closed" in the open/close sense, so that we could add another type of Layout without editing LayoutFactory. Provide this LayoutFactory to its using class, as you see in F&F, p. 116 for PizzaFactory. This is an example of DI, dependency injection. In memo.txt, explain why we don't want to absorb this LayoutFactory into its using class, as the PizzaFactory was absorbed into PizzaStore in F&F, p. 116-120. In other words, if we did so, what restriction would ensue on Layouts for a particular TrainSet? What restriction is there on PizzaStore of p. 120, for example, can a PizzaStore sell both NYStyleCheesePizza and ChicagoStyleCheesePizza?

8. DI. We have seen how Pizza1 is built up from its components, bottom up, using DI (dependency injection). Consider DI for TrainSet. Problem 7 has already set up DI for the LayoutFactory for TrainSet. What other subcomponent of TrainSet is easily handled by DI? Discuss how to do it in memo.txt. What about TrainOnTracks--discuss possible DI approaches.

Deliverables

We will collect your work electronically from a hw4 subdirectory of the cs680 directory.

Your memo should be pure ascii text, with no markup (no html, no MS Word). When printed on the Department printers no text should be lost at the ends of lines. If you want to submit some hard copy of diagrams, you may bring them to class the day the assignment is due.

We will look in your cs680/hw4 directory. It should contain

Some useful info on public methods in model, in supplied project
C:\cs\cs680\trainset.soln\src\trainset\model>grep public *.java|grep -v main|grep -v class|grep -v final|grep  -v toString

Note that some of the indented methods are in an inner class, so they may not be really public

Animator.java:  public void actionPerformed(ActionEvent event) {
Animator.java:  public void setView(TrainSystemGUI view) {
CannotAttachException.java:     public String getMessage() {
CircularSegment.java:   public void paint(Graphics g) {
Curvature.java: public int getSign() {
Curvature.java: public boolean equals(Object obj) {
Curvature.java: public int hashCode() {
DerailException.java:   public String getMessage() {
Direction.java: public static Direction[] allDirections = { Direction.N, Direction.NW,
Direction.java: public int getKey() {
Direction.java: public Direction next() {
Direction.java: public Direction previous() {
Direction.java: public Direction reverse() {
Direction.java: public Direction rotate() {
Direction.java: public Direction rotate(int count) {
Layout.java:    public static Layout create(String layoutName, int width, int height, int radius) {
Layout.java:    public List<Segment> getAllSegments() {
Layout.java:    public int getRadius() {
LayoutPoint.java:       public boolean closeEnough(LayoutPoint p) {
Segment.java:   public abstract void paint(Graphics g);
Segment.java:           public EndPoint() {
Segment.java:           public void setAttachedToA() {
Segment.java:           public void setAttachedToB() {
Segment.java:           public boolean isAttachedToA() {
Segment.java:           public boolean isAttachedToB() {
Segment.java:           public LayoutPoint getPoint() {
Segment.java:           public void setPoint(LayoutPoint point) {
Segment.java:           public Direction getDirection() {
Segment.java:           public void setDirection(Direction direction) {
Segment.java:           public Segment getNext() {
Segment.java:           public void setNext(Segment next) {
StraightSegment.java:   public void paint(Graphics g) {
Train.java:     public Train(Color color, int radius, int maxSpeed, int accelerationRate) {
Train.java:     public Color getColor() {
Train.java:     public Accelerator getAccelerator() {
Train.java:     public void paint(Graphics g, int x, int y) {
TrainOnTrack.java:      public Train getTrain() {
TrainOnTrack.java:      public void paint(java.awt.Graphics g) {
TrainSet.java:  public TrainSet(int radius) {
TrainSet.java:  public void installLayout(Layout layout) {
TrainSet.java:  public List<TrainOnTrack> getAllTrains() {
TrainSet.java:  public void start() {
TrainSet.java:  public javax.swing.Timer getTimer() {
TrainSet.java:  public Animator getAnimator() {