Java Reference
In-Depth Information
The fact that there are so many places where all exits are enumerated is symptomatic of poor
class design. When declaring the exit variables in the Room class, we need to list one variable
per exit; in the setExits method, there is one if statement per exit; in the goRoom method,
there is one if statement per exit; in the printLocationInfo method, there is one if statement
per exit; and so on. This design decision now creates work for us: when adding new exits, we
need to find all these places and add two new cases. Imagine the effect if we decided to use
directions such as northwest, southeast, etc.!
To improve the situation, we decide to use a HashMap to store the exits, rather than separate
variables. Doing this, we should be able to write code that can cope with any number of exits
and does not need so many modifications. The HashMap will contain a mapping from a named
direction (e.g., "north" ) to the room that lies in that direction (a Room object). Thus, each
entry has a String as the key and a Room object as the value.
This is a change in the way a room stores information internally about neighboring rooms.
Theoretically, this is a change that should affect only the implementation of the Room class ( how
the exit information is stored), not the interface ( what the room stores).
Ideally, when only the implementation of a class changes, other classes should not be affected.
This would be a case of loose coupling.
In our example, this does not work. If we remove the exit variables in the Room class and
replace them with a HashMap , the Game class will not compile any more. It makes numerous
references to the room's exit variables, which all would cause errors.
We see that we have a case here of tight coupling. In order to clean this up, we will decouple
these classes before we introduce the HashMap .
Using encapsulation to reduce coupling
One of the main problems in this example is the use of public fields. The exit fields in the
Room class have all been declared public . Clearly, the programmer of this class did not
follow the guidelines we have set out earlier in this topic (“Never make fields public!”). We
shall now see the result! The Game class in this example can make direct accesses to these
fields (and it makes extensive use of this fact). By making the fields public, the Room class
has exposed in its interface not only the fact that it has exits, but also exactly how the exit
information is stored. This breaks one of the fundamental principles of good class design:
encapsulation in
classes reduces
coupling and thus
leads to a better
The encapsulation guideline (hiding implementation information from view) suggests that only
information about what a class can do should be visible to the outside, not about how it does it.
This has a great advantage: if no other class knows how our information is stored, then we can
easily change how it is stored without breaking other classes.
We can enforce this separation of what and how by making the fields private and using an
accessor method to access them. The first stage of our modified Room class is shown in
Code 6.4.
Search WWH ::

Custom Search