This is a sample assignment solution, not the only possible solution set to the questions. Your answers and code might differ from these. This solution is being given as a study guide. |
This part of the assignment was not tricky, but it understanding composition (has-a), inheritance (is-a), and delegation was crucial. Any trickiness resided primarily in the trickiness of these concepts. A secondary issue is the coupling of objects.The question issue was the fact that
TempController
was itself tightly coupled toTempModel
sinceAll these things could be decoupled from
- it knew that it was changing a
TempModel
- it knew it should change the model through
setTemperature()
, and- it knew that it was to randomize the setting.
TempController
so that it was not as dependent uponTempModel
. In other words, if either of your assignment solutions had these dependencies, you would lose marks.There was two main ways of increasing the separation of
TempModel
andTempController
: through inheritance and through delegation.
- (a) Inheritance
- In the inheritance method, a subclass of
TempController
was created and it was to know whichTempModel
to change and how to change it. A sample solution is here. (Note the second hint (inner class) was used but not needed.)
- (b) Delegation
- Delegation is accomplished by making use of a delegate object. Remember the controller is supposed to respond to external (i.e. interface) events by sending off an event to the model it is controlling---or to another object that can handle the event. That is, the
TempController
, being a controller, should delegate another object to respond to the interface events, and furthermore, this object should be passed in to theTempController
. An example is located here.Why must the delegate be passed in? In the original, the delegate object is created by
TempController
in anew ActionListener()
expression. In the new code, this is done by someone else who knows what the delegate object should do, notTempController
. The whole point was to have another class make the delegate that knows what model to control and how. IfTempController
made the delegate, no separation was being accomplished.Note that the sample code used might be considered a kind of a "cheat" since it lets the AWT component do the delegate collection and firing. Why might it be considered a cheat? Mainly it is because the delegate object might not want to know how to "speak AWT". The point of separating out the model in MVC is to ensure that the model code does not need to know UI code. So perhaps your delegate object does not want to know about
java.awt.event.ActionListener
s, for example, in case it wants to be connected to a different UI toolkit. Of course, in Java, it is unlikely that someone would not use AWT since it is supposed to be the universal toolkit (the abstract toolkit). However this is not necessarily so, and is certainly not true in other programming languages you might encounter, so I wanted to make this point in this sample solution. This will be brought up in question #2.
- Comparison:
- One can make many different arguments about the two implementations, but arguing to hard for either of them usually amounts to dogmatism. The main advantage to the delegation method is the runtime flexibility: multiple listeners can be specified at runtime (an
addActionListener()
would need to be in thetempController()
interface, of course). The connections between controller and the things it controls need not be specified until runtime. This is probably the best answer to this question.The delegation method also has a secondary advantage. The subclassing method requires knowledge of a non-standard protocol (
doAction()
as an analogue to event-firing) rather than a standard naming such as AWT's event naming system (xxxEvent/xxxListener, etc.) or theObservable/Observer
standard naming for delegation.
- (c)
ThermometerMVC318
achieves better separation.- First of all, UI code is well separated from application code in both: the model has absolutely no UI code in it, and the same TempModel is used for both. However that does not mean the reverse is true: the application code is not equally separated from the UI.
There are two telling lines in
ThermometerMVC1
:
tempController.addObserver ( tempView )
inThermometerMVC1.init()
tempModel = new TemperatureModel()
inTemperatureController1.TemperatureController1()
.This first tells us that Controller and Model are not correctly separated (that is, application code is not correctly separated from UI code). Why is a View listening to events from a Controller? The Controller should be controlling a Model. Clearly, the Controller knows too much about the application code. What if you wanted several controllers on the model? You'd have to call
TempController.getModel()
to find out model to control. This is not only a flaw in the MVC separation, it fails to properly separate application code from model code.The second line demonstrates that the controller is dependent upon the model class since it constructs the model in addition to updating it directly.
ThermometerMVC318
fixes these problems by moving theTempModel
construction out from the controller. The changes to part (a) and (b) merely clean up the MVC architecture, but do not fundamentally add any separation between interface code and application code.
The sample solution is quite self-explanatory. It contains 5 main objects and 4 connector objects to hook up those 5 main objects. It also has 2 additional internal event adapter objects.See the javadoc for a formatted description.
Note #1: in the above I mentioned that one might wish to erect a barrier between UI code and non-UI code so that the MVC components communicate without using UI code (such as
java.awt.Event
objects). The example solution uses theObserver
class to accomplish this. This is likely overkill and unnecessary but I wanted to give you an idea of how this could be accomplished. It is left as an exercise to the reader to remove the adapter classes and have the model updated by a delegate object responding to AWT events directly instead of an AWT-event to Observer-event adapter.Note #2: The solution separates the two types of controllers. This is the preferred solution for this assignment, where the objective was to apply the MVC concept to the program solution. As mentioned in all the MVC references, the purpose of the MVC architecture is to allow and promote multiple separate controllers (and views). If your solution merged both controller actions into a single controller, look over this solution. You may not have lost marks if you made this solution, but unless you gave a good reason for merging the controllers together, you probably should have.
Updated: Feb 14, 1998