Chapter 10 Mediator

153
Chapter 10 Mediator Summary prepared by Kirk Scott 1

description

Chapter 10 Mediator. Summary prepared by Kirk Scott. Athena From Wikipedia, the free encyclopedia. - PowerPoint PPT Presentation

Transcript of Chapter 10 Mediator

Page 1: Chapter 10 Mediator

1

Chapter 10Mediator

Summary prepared by Kirk Scott

Page 2: Chapter 10 Mediator

2

AthenaFrom Wikipedia, the free encyclopedia

• :"Athene", "Athina", and "Pallas Athena" all redirect here. For other uses, see Athena (disambiguation), Athene (disambiguation), Athina (disambiguation) and Pallas Athena (disambiguation)

Page 3: Chapter 10 Mediator

3

• In Greek religion and mythology, Athena or Athene (pron.: /əˈθiːnə/ or /əˈθiːniː/; Attic: Ἀθηνᾶ, Athēnā or Ἀθηναία, Athēnaia; Epic: Ἀθηναίη, Athēnaiē; Ionic: Ἀθήνη, Athēnē; Doric: Ἀθάνα, Athānā), also referred to as Pallas Athena/Athene (pron.: /ˈpæləs/; Παλλὰς Ἀθηνᾶ; Παλλὰς Ἀθήνη), is the goddess of wisdom, courage, inspiration, civilization, law and justice, just warfare, mathematics, strength, strategy, the arts, crafts, and skill. Minerva is the Roman goddess identified with Athena.[4]

Page 4: Chapter 10 Mediator

4

• Athena is also a shrewd companion of heroes and is the goddess of heroic endeavour. She is the virgin patroness of Athens. The Athenians founded the Parthenon on the Acropolis of her namesake city, Athens (Athena Parthenos), in her honour.[4]

Page 5: Chapter 10 Mediator

5

Page 6: Chapter 10 Mediator

6

Page 7: Chapter 10 Mediator

7

Athena in the art of Gandhara.

Page 8: Chapter 10 Mediator

8

Design Patterns in JavaChapter 10Mediator

Summary prepared by Kirk Scott

Page 9: Chapter 10 Mediator

9

Introduction

• A mediator is something that stands between one base class and another

• In object terms, the mediator object stands between one or more instances of one or more base classes

• Instances of the base classes interact with the mediator class rather than interacting with each other directly

Page 10: Chapter 10 Mediator

10

• The implementation of mediators can differ depending on what the relationships between instances of the base classes are

• This means that the mediator pattern could be represented by a variety of UML diagrams

Page 11: Chapter 10 Mediator

11

• The background for mediators can be expressed in terms of responsibility

• The general rule is that objects are responsible for themselves

• In other words, classes should contain some well-defined, limited, and coherent data set, along with the methods needed to work with the data

• Classes, in general, should not be heavily reliant on objects of other classes to implement needed functionality

Page 12: Chapter 10 Mediator

12

• On the other hand, recall the Builder pattern• It illustrated offloading construction

responsibility/functionality into another class• Also recall the Proxy pattern• In it, the client dealt with the proxy (stand-in)

rather than dealing directly with the base class

Page 13: Chapter 10 Mediator

13

• The Mediator pattern can be viewed as offloading/concentrating responsibility/functionality into a separate class

• The mediator becomes responsible for the relationship between classes or the relationships between instances of those classes

Page 14: Chapter 10 Mediator

14

• Although conceptual in nature, the relationships are real aspects of the design

• They can be as meaningful as the bases classes themselves

• They can have a life of their own• It turns out to make good design sense to have

a separate class that is devoted to storing and maintaining the relationships

Page 15: Chapter 10 Mediator

15

Scenario

• Consider this scenario: • In a group of objects, each one “is aware of”

or has a reference to every other member of the group

• First of all, note that this can be complex

Page 16: Chapter 10 Mediator

16

• Also note that the set of relationships itself becomes an abstraction that might be implemented as a separate class

• Introducing a new class factors the relationship functionality out of the base classes

• The new class concentrates responsibility for the relationships among objects and reduces their responsibility for themselves

Page 17: Chapter 10 Mediator

17

• The individual objects become dependent on the class that maintains the relationships

• In the code, the individual objects relate only to the class in the middle, not with each other

• This new class in the middle is a mediator class• The base objects are no longer tightly coupled

with each other, but they are tightly coupled with the mediator

Page 18: Chapter 10 Mediator

18

Book Definition of the Pattern

• Book definition: • The intent of the Mediator pattern is to define

an object that encapsulates how a set of objects interact; this promotes loose coupling, keeping the objects from referring to one another explicitly, and lets you vary their interactions independently.

Page 19: Chapter 10 Mediator

19

• Comment mode on:• The pattern makes the base classes more loosely

coupled with each other.• In a sense, it does this by coupling them to a

common class in the middle.• They are coupled to the class in the middle by

virtue of the fact that the class in the middle concentrates the responsibility for maintaining the relationships

Page 20: Chapter 10 Mediator

20

Modeling Relationships

• Keep in mind that code typically models some reality

• In that reality, individual objects may be linked with each other

• In the problem domain, the relationships may be as important as the objects, and exist as a truly separate concept

Page 21: Chapter 10 Mediator

21

• How you represent the relationships in code is a design choice

• Correctly implementing the relationships in a separate class abstracts out the responsibility for maintaining relationships

Page 22: Chapter 10 Mediator

22

Concrete Examples from the Book

• The book pursues two examples to illustrate the use of the Mediator design pattern

• 1. The pattern can become apparent/be used when developing GUI’s with multiple parts in increasingly complex relationships

• 2. The pattern can also become apparent when modeling the real world where objects have relationships with each other and the code needs to reflect those relationships

Page 23: Chapter 10 Mediator

23

• The book will claim that the first example is the more common one

• Before the dust has settled it should become apparent that the second example, even if less common, makes the logic of the pattern clearer

Page 24: Chapter 10 Mediator

24

A Classic Example: GUI Mediators

• The book’s first example applies the mediator pattern to a program with a graphical user interface

• The book shows a GUI, shows some code, and shows a refactoring using the pattern

• At the end of the book’s example, it basically comes down to this:

• “Voila—and now you see how these things don’t interact directly with each other anymore—they interact through this other class in the design.”

Page 25: Chapter 10 Mediator

25

• In order to reduce the “voila” factor, it is helpful to give a preview of how it will fit together:

• The example is based on tubs and machines

Page 26: Chapter 10 Mediator

26

• There will be base classes for tub and machine objects

• There will also be a base class which keeps track of these objects in the data model

• In this case, the class which takes care of the objects will be known as a “mock database” (stay tuned)

• You can recognize that this as equivalent to the model in an MVC design

Page 27: Chapter 10 Mediator

27

• There will be a class that is responsible for the GUI components

• This is the client• It graphically represents the objects in the

application• It also has buttons, etc., so actions can be taken• You can recognize that this as equivalent to the

view in an MVC design

Page 28: Chapter 10 Mediator

28

• There will be a mediator• This will implement listening• This is the functionality for what happens

when an action is taken in the GUI• You can recognize that this as equivalent to

the controller in an MVC design

Page 29: Chapter 10 Mediator

29

• In other words, analytically speaking, in an MVC design, the controller serves as a mediator between the model and the view

• On the other hand, this example illustrates mediation without including the observer part of MVC

• Why observing is extraneous will be pointed out later

Page 30: Chapter 10 Mediator

30

• Overall in this example a relationship between the data model and the graphical user interface representation of the state of the application has to be maintained

• The mediator implements listening functionality• It stands between the GUI/client/view and the

data model• It is responsible for maintaining the relationship

Page 31: Chapter 10 Mediator

31

The Scenario

• The graphical user interface for the example is shown on the overhead following the next one

• A factory has machines in it, and the machines at any given time have a set of tubs of materials that belong to them

• The interaction of interest is the moving of tubs from one machine to another

Page 32: Chapter 10 Mediator

32

• It is important to understand that at this point the book is interested in mediation between the graphical user interface and the data model in the application

• It is apparent that there is another basic relationship in the application:

• Which tubs are located at which machines• Applying mediation to that relationship will be

covered in the next example

Page 33: Chapter 10 Mediator

33

Page 34: Chapter 10 Mediator

34

• This is the sequence of events:• In the interface, pick a source machine from the

first column• The tubs belonging to it appear in the second

column• Destination machines appear in the third column• Pick a tub in the second column and a

destination machine in the third column

Page 35: Chapter 10 Mediator

35

• Once three things are highlighted in the interface, you can press the “Do it!” button

• This moves the tub from the source machine to the destination machine

• Both the GUI representation and the underlying data model in the software should be updated

Page 36: Chapter 10 Mediator

36

Extending the Development Scenario

• The authors paint out the scenario further in this way

• An interface like this can be developed using a wizard

• However, the wizard produces cookie-cutter code that doesn’t necessarily fit a nice design pattern

Page 37: Chapter 10 Mediator

37

• Using a wizard might produce a class named MoveATub that is basically a monolithic application

• The UML for this class is given on the next overhead

Page 38: Chapter 10 Mediator

38

Page 39: Chapter 10 Mediator

39

Refactoring the Design

• The book observes that the methods in the MoveATub class are a mixture of component building, event handling, and “mock database” operations

• The desire is to refactor this design so that it is better• In other words, the desire is to break it into parts

where the responsibilities are clearly divided• In the long run this will make the code easier to

maintain and modify

Page 40: Chapter 10 Mediator

40

GUI Construction Methods in the Monolithic Class

• There are methods in MoveATub that construct GUI components

• For example, there is a method assignButton(), which is the method which constructs the “Do it!” button

• Its code is given on the next overhead for reference

• Notice that it is implemented with lazy initialization

Page 41: Chapter 10 Mediator

41

• private JButton assignButton()• {• if(assignButton == null)• {• assignButton = new JButton(“Do it!”);• assignButton.setEnabled(false);• assignButton.addActionListener(this);• }• return assignButton;• }

Page 42: Chapter 10 Mediator

42

Domain Object Construction in the Monolithic Class

• There are also methods in MoveATub that construct domain objects like lists of machines and tubs, and so on

• In other words, the elements of the problem domain are mixed with GUI elements

Page 43: Chapter 10 Mediator

43

Listener Implementation in the Monolithic Class

• MoveATub also implements the ActionListener and ListSelectionListener interfaces

• In it you find methods that are related to actions, like valueChanged() and updateTubList()

• The authors give the code for the valueChanged() method for reference

• It is shown on the following overhead

Page 44: Chapter 10 Mediator

44

• public void valueChanged(ListSelectionEvent e)• {• // …• assignButton().setEnabled(• !tubList().isSelectionEmpty()• && !machineList().isSelectionEmpty());• }

Page 45: Chapter 10 Mediator

45

• The book observes that at the very least you might consider moving the event handling methods into a different class

• That would be a step towards applying the mediator pattern

Page 46: Chapter 10 Mediator

46

Ways of Implementing Listening

• How listening is implemented opens out into a somewhat broader topic

• Think back to how listening was implemented in CSCE 202

• The orange book’s plan was this:• Implement listening in a separate listener class,

but make it an inner class so that it had direct access to the instance variables of the outer class

Page 47: Chapter 10 Mediator

47

• What we’ve just seen in the monolithic MoveATub class is that the class itself can implement the listening interface

• Among the points this book is making is that the monolithic class has too many different kinds of things in it

• Classes should be coherent, single-purpose, and self-contained

Page 48: Chapter 10 Mediator

48

• Where to put listening and how to make sure listeners have access to the things they need are important topics in Java GUI programming

• Essentially, these topics were covered in the MVC units

• Having a model in one or more classes and separating listening and observing into one or more classes each is the most general solution

Page 49: Chapter 10 Mediator

49

Redesigning the Application Using the Pattern

• Challenge 10.1• Complete the diagram in Figure 10.3 to show a

refactoring of MoveATub, introducing a separate mock database class and a mediator class to receive the events of the MoveATub GUI.

Page 50: Chapter 10 Mediator

50

• Comment mode on:• As usual, doing this on your own verges on the

impossible• What, for example, does the book mean by a

mock database?• As usual, the only practical approach is to just

look at the book’s solution and try and figure out what it means

Page 51: Chapter 10 Mediator

51

Page 52: Chapter 10 Mediator

52

• Solution 10.1• Figure B.11 shows a solution.

Page 53: Chapter 10 Mediator

53

Page 54: Chapter 10 Mediator

54

• What is to be gleaned from the UML diagram of the solution?

• MoveATub2 now is pretty much limited to the graphical components of the application

• NameBase is the so-called mock database• This is the part of the application that is problem-

domain, or model oriented• It keeps track of the state of machines and their

tubs

Page 55: Chapter 10 Mediator

55

• MoveATubMediator implements the ActionListener and ListSelectionListener interfaces, suggesting it’s a controller

• It contains the actionPerformed(), valueChanged(), and updateTubList() methods

• As its name indicates, this is the (GUI) mediator• When things happen in the GUI, actions are

taken indirectly on the NameBase, through the mediator

Page 56: Chapter 10 Mediator

56

• It is also possible for the mediator to take actions on the GUI, like enabling or disabling a button

• The authors say that the most common example of mediation is this use in GUI development

• The mediator, in this example, stands between and implements the interaction between the GUI class/object and the NameBase class/object

Page 57: Chapter 10 Mediator

57

• A simplified, generic UML diagram of the pattern would show the button and the NameBase, with the MoveATubMediator between them.

• This is almost the end of the presentation of this example

• I will not show additional code

Page 58: Chapter 10 Mediator

58

• Just looking at the book’s UML diagram, some of the relationships and arrows are not completely clear

• Also, as mentioned earlier, making sure the listeners have access to what they need is important, but unresolved

Page 59: Chapter 10 Mediator

59

A Sequence Diagram for the Pattern

• The following challenge tries to illustrate the pattern by means of a sequence diagram rather than a static structure diagram

• It shows a sequence of calls and returns from the GUI component, to the listener, to the underlying data structure

Page 60: Chapter 10 Mediator

60

• Challenge 10.2• “Draw a diagram that shows what happens

when the user clicks the Do it! Button. • Show whichever objects you think are most

important, and show the messages that pass between these objects.”

Page 61: Chapter 10 Mediator

61

• Solution 10.2• Figure B.12 shows one solution.

Page 62: Chapter 10 Mediator

62

Page 63: Chapter 10 Mediator

63

A Last Observation on the First Example

• In general, why is it possible to do this example without observing?

• In what way is this, at least in part, illustrated by the sequence diagram?

• Think back to the MVC example:• There was a slider for input• There were two graphics panels and a label for

output

Page 64: Chapter 10 Mediator

64

• The output side observed changes in the slider• In this example, each of the graphical

components is essentially something that has a listener

• You pick items from the lists• It’s true that the list of tubs depends on which

source machine is chosen, but still, each GUI component listens, because you can then select a tub out of that list

Page 65: Chapter 10 Mediator

65

• It may or may not be good that the authors haven’t done a full MVC design

• However, it is useful to note how the difference in the functionality between the MVC example GUI and this GUI support different implementation approaches

Page 66: Chapter 10 Mediator

66

Example 2: Mediators of Relational Integrity

• The most common use of the mediator pattern may be in GUI’s, but there are others

• In general, in any case where there are numerous or complicated relationships between objects, it may be desirable to abstract the relationships out

• This reduces the coupling between the base objects, encapsulating the complexity inside the mediator class that implements the relationships

Page 67: Chapter 10 Mediator

67

• It also has this advantage, as noted earlier:• The relationships really do have an existence in

a design and may be no less important than the objects

• By abstracting the relationships out, the rules for them can be standardized and you assure yourself that all objects that participate in relationships rely on the same implementation logic

Page 68: Chapter 10 Mediator

68

• The book is going to pursue the idea of relationships using the machines and tubs of Oozinoz

• In the GUI example, the Mediator design pattern was illustrated by the listener, which mediated between the GUI and the so-called mock database, which represented the state of machines and tubs

Page 69: Chapter 10 Mediator

69

• For the purposes of that example, the machines and tubs, or lists of machines and tubs, were simply relegated to that part of the design having to do with the business model

• Now it is the relationships between the machines and tubs themselves that are of interest and which will be used to illustrate mediation

• Consider the table shown on the next overhead

Page 70: Chapter 10 Mediator

70

Page 71: Chapter 10 Mediator

71

• The table shows a one-to-many relationship between machines and tubs

• Each machine can have more than one tub• A tub can only belong to one machine at a given time• As long as the tub entries in the table are unique, the

table represents this reality• Multiple entries for the same machine in the second

column allow a given machine to have more than one tub at a time

Page 72: Chapter 10 Mediator

72

• The book has a grey section on the topic of relational integrity

• The topic is not as difficult or theoretical as the section makes it

• It will not be covered in these overheads• If you want the whole nine yards on relational

integrity, take CSCE 360…

Page 73: Chapter 10 Mediator

73

An Undesirable Solution to the Problem

• On the following overhead a UML diagram is given which shows one-to-many relationships between machine and tub objects

• It is important to note that nothing in this diagram suggests a mechanism for enforcing the one-to-many relationship

Page 74: Chapter 10 Mediator

74

Page 75: Chapter 10 Mediator

75

• There is no automatic support in programming languages like Java for concepts like enforcing a one-to-many relationship

• That means that the application developer has to enforce this if it’s desired

Page 76: Chapter 10 Mediator

76

• This is the design question:• Do you want to try and write code in the

classes of the participating objects so that correct relationships are maintained?

• Or would you prefer to write a separate class that implements all of the rules necessary in order to enforce correct relationships?

Page 77: Chapter 10 Mediator

77

• Notice that in the UML diagram, the arrows are double-headed

• This means that machines know which tubs are theirs and tubs know which machine they belong to

• In other words, there are references in the code for the objects going both ways

Page 78: Chapter 10 Mediator

78

• The book illustrates the pitfalls of trying to maintain relationships with an example

• Suppose a developer wrote these lines of code to change which machine a tub belonged to

• // Tell tub about machine, and machine about tub

• t.setMachine(m);• m.addTub(t);

Page 79: Chapter 10 Mediator

79

• Challenge 10.3• “Assume that the objects begin as shown in Figure

10.4. Suppose that the object t represents tub T308 and that the object m represents the machine Fuser-2101. Complete the object diagram in Figure 10.5, showing the effects of the code that updates the tub’s location. What defect does this reveal?”

• [Figures 10.4 and 10.5 are shown on the next overheads.]

Page 80: Chapter 10 Mediator

80

Page 81: Chapter 10 Mediator

81

Page 82: Chapter 10 Mediator

82

• Solution 10.3• “Figure B.13 shows an updated object

diagram.”

Page 83: Chapter 10 Mediator

83

Page 84: Chapter 10 Mediator

84

• Solution 10.3, cont’d.• “The problem that the developer’s code introduces is

that StarPress2402 still thinks that it has tub T308. In a relational table, changing the machine attribute of a row automatically removes the tub from the prior machine. This automated removal does not occur when the relation is dispersed across a distributed object model. The proper modeling of the tub/machine relation requires special logic that you can remove to a separate mediator object.”

Page 85: Chapter 10 Mediator

85

A Table Based Implementation

• The book suggests that the simplest way to maintain relational integrity like this is to actually rely on a table

• The table concept can be implemented in the separate mediator class

• Then the objects won’t refer to each other directly

Page 86: Chapter 10 Mediator

86

• They will have their relationships captured in the mediator/table

• The establishment of relationships will be done through the mediator class’s interface

• The book illustrates the idea in the following UML diagram

Page 87: Chapter 10 Mediator

87

Page 88: Chapter 10 Mediator

88

• Tubs and machines have a reference to the (one) mediator

• The TubMediator class has an instance variable of Java type Map

• The Map implements the logic of the relational table

Page 89: Chapter 10 Mediator

89

• The Tub and Machine classes have methods for adding a tub to a machine, assigning a machine to a tub, etc.

• The tub and machine methods would be implemented by wrapping calls to the mediator class’s methods

• Inside the mediator the relationships would be captured in the map

Page 90: Chapter 10 Mediator

90

Code for a Map Based Solution

• The book next starts presenting code, partial code, and code based challenges

• It starts with the Tub class• It then explains the TubMediator class• I think it makes more sense to look at the

mediator class first

Page 91: Chapter 10 Mediator

91

• The TubMediator class has a Map instance variable

• That variable is an instance of the Java class HashMap

• On the following overhead is a snippet from the Java API documentation for the HashMap

Page 92: Chapter 10 Mediator

92

• HashMap• Hash table based implementation of the Map

interface. • This implementation provides all of the optional

map operations, and permits null values and the null key.

• (The HashMap class is roughly equivalent to Hashtable, except that it is unsynchronized and permits nulls.)

Page 93: Chapter 10 Mediator

93

• Here is a snippet from the Java API documentation for Hashtable:

• This class implements a hashtable, which maps keys to values.

• Any non-null object can be used as a key or as a value.

• To successfully store and retrieve objects from a hashtable, the objects used as keys must implement the hashCode method and the equals method.

Page 94: Chapter 10 Mediator

94

• On the following two overheads is detailed material from the Java API on the hash table get() and put() methods

• The mediator will rely on these

Page 96: Chapter 10 Mediator

96

• put• public V put(K key, V value)• Maps the specified key to the specified value in this hashtable.

Neither the key nor the value can be null. The value can be retrieved by calling the get method with a key that is equal to the original key.

• Specified by: put in interface Map<K,V>• Specified by: put in class Dictionary<K,V>• Parameters: key - the hashtable key.value - the value.• Returns: the previous value of the specified key in this hashtable, or

null if it did not have one.• Throws: NullPointerException - if the key or value is null.• See Also: Object.equals(Object), get(Object)

Page 97: Chapter 10 Mediator

97

• The way to envision the use of the hash table with tubs and machines is this:

• The hash table is like a two column table• The left column consists of look-up values,

known as keys—the tubs• The right column consists of values, namely

those values that match with the keys—the machines where the tubs are located

Page 98: Chapter 10 Mediator

98

• In the tub/machine scenario, a tub exists in the table once

• The hash code of a tub serves as its unique identifier

• This is the hash table key• Then the identifier for the machine that the

tub is assigned to serves as the value in the hash table

Page 99: Chapter 10 Mediator

99

• I have gotten rid of Challenge 10.4• Complete code for the TubMediator class is

given on the overhead following the next one• There is a method to assign a tub to a machine• There is a method to find the machine a tub is

assigned to• And there is a method which allows you to get

the set of all tubs located at a machine

Page 100: Chapter 10 Mediator

100

• Note that the implementations of the getTubs() and set() methods are quite simple

• They rely entirely on the get() and put() methods of the HashMap class

• This is the secret of the use of the Java collection in the implementation of the mediator design pattern

• Essentially, the mediator just wraps the collection and passes through to its methods

Page 101: Chapter 10 Mediator

101

• public class TubMediator• {• protected Map tubToMachine = new HashMap();• public Set getTubs(Machine m)• {• Set set = new HashSet();• Iterator i = tubToMachine.entrySet().iterator();• while(i.hasNext())• {• Map.Entry e = (May.Entry) i.next();• if(e.getValue().equals(m))• set.add(e.getKey());• }• return set;• }

Page 102: Chapter 10 Mediator

102

• public Machine getMachine(Tub t)• {• return (Machine) tubToMachine.get(t);• }• • public void set(Tub t, Machine m)• {• tubToMachine.put(t, m);• }• }

Page 103: Chapter 10 Mediator

103

The Tub Class

• A tub has an id and a reference to the mediator• It has set and get methods for location, where

location refers to the machine it’s associated with• Just as the mediator wrapped a hashmap

collection, the set and get methods for the tub wrap calls to the mediator object

• It’s the mediator that’s responsible for maintaining relationships

Page 104: Chapter 10 Mediator

104

• public class Tub• {• private String id;• private TubMediator mediator = null;• public Tub(String id, Tubmediator mediator)• {• this.id = id;• this.mediator = mediator;• }

Page 105: Chapter 10 Mediator

105

• public Machine getLocation()• {• return mediator.getMachine(this);• }• public void setLocation(Machine value)• {• mediator.set(this, value);• }• public String toString()• {• return id;• }

Page 106: Chapter 10 Mediator

106

• This is not the end of the book’s code, just a brief interruption

• It turns out that the Tub class also needs a hashCode() and an equals() method in order to serve as the key of a hashmap

• Code for these methods will be given next• They will be discussed at length after the code

Page 107: Chapter 10 Mediator

107

• public int hashCode()• {• return id.hashCode();• }• public boolean equals(Object obj)• {• if(obj == this) return true;• if(obj.getClass() != Tub.class)• return false;• Tub that = (Tub) obj;• return id.equals(that.id);• }

Page 108: Chapter 10 Mediator

108

• The Tub class needs hashCode() and equals() methods for the following reason:

• In order for instances of a class to serve as the keys of a hash table (HashMap), they have to implement these methods

• This information was given in the API documentation for the HashMap class that was shown earlier

Page 109: Chapter 10 Mediator

109

• Functionally, the setLocation() and getLocation() methods of the Tub class wrap calls of this kind on the mediator:

• mediator.set(this, value);• mediator.getMachine(this);

Page 110: Chapter 10 Mediator

110

• Functionally, the set() and getMachine() methods of the TubMediator class wrap calls of this kind on the hash table, where the parameter t is the tub (this) of the wrapping call:

• tubToMachine.put(t, m);• return (Machine) tubToMachine.get(t);

Page 111: Chapter 10 Mediator

111

• In short, the tubs are being passed in as the key values for the hash table

• From the requirement that the key class have a hashCode() method and an equals() method, you can deduce the following:

• Internal to the hash table get() and put() methods, there must be calls to hashCode() and equals() on the tub parameters

Page 112: Chapter 10 Mediator

112

• This makes perfect sense• The keys of a hash table have to be unique• The hashCode() and equals() methods are

used internally to verify that tubs are unique before they can be used as keys

Page 113: Chapter 10 Mediator

113

• The only lingering question is why the authors chose to implement hashCode() and equals() on the basis of a tub’s id rather that on the basis of the tub object itself

• As far as I can see in the text, the authors don’t explain this decision

• I can see no syntactical reason for not basing hashCode() and equals() on the Tub object rather than its id

Page 114: Chapter 10 Mediator

114

• The one concrete consequence of the decision that I can see is that it will ultimately force the user to make sure that tub id’s are unique

• On the other hand, if the programmer has introduced user level tub id’s into the application, then it’s up to the user to make sure that they are unique anyway

Page 115: Chapter 10 Mediator

115

Back to the General Discussion

• The book returns to the general theme of whether or not it’s a good idea to include a mediator in a design

• You could code the logic for machines and tubs into those classes themselves

• The thing to remember is that such code is error prone

• You could also argue that the details of relationships are not intrinsically part of the logic of the classes themselves

Page 116: Chapter 10 Mediator

116

• You might also argue that the relationships possible between classes are intrinsic parts of the definitions of the classes

• Regardless of your position, there is clearly a convenience in unifying the logic for relationships in one place

• The relationships are an abstraction of their own, and the logic for maintaining them can be centralized

Page 117: Chapter 10 Mediator

117

• The example illustrates the following:• If you do decide to craft a mediator, tools like

Java hash tables are available to enforce requirements like relational integrity

Page 118: Chapter 10 Mediator

118

Another Example

• Another example, based on cups and seeds, will be given next

• This example has this similarity with the book’s first example:

• A listener in a graphical application may be viewed as a mediator

• It also has this similarity with the book’s second example:

• How you capture the relationships between base objects in the application is important as well

Page 119: Chapter 10 Mediator

119

• In this example there are 3 cups and 9 seeds• A cup can contain from 0 to 9 seeds• A given seed can only be contained in one cup

at a time• The graphical user interface allows the user to

pick a seed and a cup and cause the seed to be moved to that cup by pressing a button

Page 120: Chapter 10 Mediator

120

• A screenshot of the application is shown on the next overhead

Page 121: Chapter 10 Mediator

121

Page 122: Chapter 10 Mediator

122

• A UML diagram for the application is given on the overhead following the next one.

• The diagram shows that CupsAndSeedsMediator occupies a position between the input GUI elements, and the underlying DB model, which is displayed on output.

• The mediator implements the ActionListener interface, but it isn’t an inner class.

• It’s passed a reference to the frame class that contains it at construction time.

Page 123: Chapter 10 Mediator

123

• Not a lot of care is taken in the implementation of CupsAndSeedsDB, so it isn’t a full scale example of a mediator

• However, in spite of where it appears relative to the Cup and Seed classes in the diagram, it has mediator like qualities

• The CupsAndSeedsDB class contains the code that captures the relationships, telling which seeds belong to which cups, and making sure that a seed doesn’t belong to two cups at once

Page 124: Chapter 10 Mediator

124

Page 125: Chapter 10 Mediator

125

Code

• The code for the application is given on the following overheads for reference.

• It will probably not be covered in class.

Page 126: Chapter 10 Mediator

126

• import java.awt.*;• import java.awt.event.*;• import javax.swing.*;• import java.awt.Graphics2D;• import java.awt.Rectangle;• import java.awt.geom.Ellipse2D;• import java.lang.*;• import java.util.*;

• public class MoveOneSeedOneFile• {• public static void main(String[] args)• {• MoveOneSeedFrame myframe = new MoveOneSeedFrame();• myframe.setVisible(true);• }• }

Page 127: Chapter 10 Mediator

127

• class MoveOneSeedFrame extends JFrame• {• private CupsAndSeedsDB cupsAndSeeds;• private CupsAndSeedsMediator mediator;• private JTextField seedField;• private JTextField cupField;• private JButton moveSeedButton;• private MoveOneSeedPanel myOutputPanel;• private JPanel myInputPanel;• private final int FRAMEW = 1000;• private final int FRAMEH = 500;• public MoveOneSeedFrame()• {• setTitle("MoveOneSeed Frame");• setSize(FRAMEW, FRAMEH);• setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

• cupsAndSeeds = new CupsAndSeedsDB();• mediator = new CupsAndSeedsMediator(cupsAndSeeds, this);

Page 128: Chapter 10 Mediator

128

• JPanel myInputPanel = new JPanel();• JLabel label1 = new JLabel("Color of seed to move: white, pink, red,

orange, yellow, green, cyan, blue, magenta:");• seedField = new JTextField("", 12);• JLabel label2 = new JLabel("Number of destination cup: 1, 2, 3:");• cupField = new JTextField("", 12);• moveSeedButton = new JButton("Move Seed");• moveSeedButton.addActionListener(mediator);• JPanel subPanel1 = new JPanel();• JPanel subPanel2 = new JPanel();• JPanel subPanel3 = new JPanel();• JPanel subPanel4 = new JPanel();• JPanel subPanel5 = new JPanel();• subPanel1.add(label1);• subPanel2.add(seedField);• subPanel3.add(label2);• subPanel4.add(cupField);• subPanel5.add(moveSeedButton);• myInputPanel.setLayout(new GridLayout(3, 2));• myInputPanel.add(subPanel1);• myInputPanel.add(subPanel2);• myInputPanel.add(subPanel3);• myInputPanel.add(subPanel4);• myInputPanel.add(subPanel5);

Page 129: Chapter 10 Mediator

129

• myOutputPanel = new MoveOneSeedPanel(cupsAndSeeds);

• Container contentPane = getContentPane();• contentPane.add(myInputPanel, "North");• contentPane.add(myOutputPanel, "Center");• }• public JButton getMoveSeedButton()• {• return moveSeedButton;• }

• public JTextField getSeedField()• {• return seedField;• }

• public JTextField getCupField()• {• return cupField;• }• }

Page 130: Chapter 10 Mediator

130

• class MoveOneSeedPanel extends JPanel• {• CupsAndSeedsDB shownDB;

• public MoveOneSeedPanel(CupsAndSeedsDB dbIn)• {• shownDB = dbIn;• }• public void paintComponent(Graphics g)• {• int i;• int cupX = 180;• int cupY = 180;• int cupW = 40;• int cupH = 40;• int seedX;• int seedY;• Rectangle cupRectangle;• Ellipse2D.Double seedDot;• int seedDiam = 7;• ArrayList<Cup> cupList;• ArrayList<Seed> seedList;

• Graphics2D g2 = (Graphics2D) g;• super.paintComponent(g2);

• cupList = shownDB.getCupList();

• System.out.println("Before loops");

Page 131: Chapter 10 Mediator

131

• for(Cup aCup : cupList)• {• System.out.println("In cup loop");• cupRectangle = new Rectangle(cupX, cupY, cupW, cupH);• g2.draw(cupRectangle);

• Random generator = new Random();

• seedList = aCup.getSeedList();

• for(Seed aSeed : seedList)• {• System.out.println("In seed loop top");• seedX = (int) cupX + generator.nextInt((int) cupW - seedDiam);• seedY = (int) cupY + generator.nextInt((int) cupH - seedDiam);

• seedDot = new Ellipse2D.Double(seedX, seedY, seedDiam, seedDiam);

• System.out.println("Before printing seedIterator.next()");• System.out.println(aSeed);• System.out.println("Before printing color of seedIterator.next()");• System.out.println(aSeed.getSeedColor());

• g2.setColor(aSeed.getSeedColor());• g2.fill(seedDot);• g2.setColor(Color.BLACK);• System.out.println("At bottom of seed loop");• }

• cupX = cupX + 50;• System.out.println("At bottom of cup loop");• }• System.out.println("After loops");• }• }

Page 132: Chapter 10 Mediator

132

• /* The idea behind this class is that each seed will be of a different color.

• The seeds can then be identified by their colors. Nothing in the code as written

• would cause more than one seed of the same color to exist. On the other hand,

• there are no particular protections in the code to prevent this. */

• class CupsAndSeedsDB• {• private ArrayList<Cup> cupList;

Page 133: Chapter 10 Mediator

133

• public CupsAndSeedsDB()• {• cupList = new ArrayList<Cup>();

• Seed seed1 = new Seed(Color.WHITE, "WHITE");• Seed seed2 = new Seed(Color.PINK, "PINK");• Seed seed3 = new Seed(Color.RED, "RED");• Cup cup1 = new Cup();• cup1.addSeed(seed1);• cup1.addSeed(seed2);• cup1.addSeed(seed3);• cupList.add(cup1);

• Seed seed4 = new Seed(Color.ORANGE, "ORANGE");• Seed seed5 = new Seed(Color.YELLOW, "YELLOW");• Seed seed6 = new Seed(Color.GREEN, "GREEN");• Cup cup2 = new Cup();• cup2.addSeed(seed4);• cup2.addSeed(seed5);• cup2.addSeed(seed6);• cupList.add(cup2);

• Seed seed7 = new Seed(Color.CYAN, "CYAN");• Seed seed8 = new Seed(Color.BLUE, "BLUE");• Seed seed9 = new Seed(Color.MAGENTA, "MAGENTA");• Cup cup3 = new Cup();• cup3.addSeed(seed7);• cup3.addSeed(seed8);• cup3.addSeed(seed9);• cupList.add(cup3);• }

Page 134: Chapter 10 Mediator

134

• public ArrayList getCupList()• {• return cupList;• }

• public Seed removeSeedOfThisColor(String colorNameIn)• {• Iterator cupIterator = cupList.iterator();• Iterator seedIterator;• Seed latestSeed = null;

• boolean found = false;

• while(cupIterator.hasNext() && !found)• {• seedIterator = ((Cup) cupIterator.next()).getSeedList().iterator();• while(seedIterator.hasNext() && !found)• {• latestSeed = (Seed) seedIterator.next();• if(latestSeed.getSeedColorName().equals(colorNameIn))• {• found = true;• seedIterator.remove();• }• }• }

• if(found)• return latestSeed;• else• return null;• }

Page 135: Chapter 10 Mediator

135

• public void addSeedToCup(int cupNumber, Seed seedIn)• {• Cup cupRef = (Cup) cupList.get(cupNumber);• cupRef.addSeed(seedIn);• }• }• class Cup• {• private ArrayList<Seed> seedList;

• public Cup()• {• seedList = new ArrayList<Seed>();• }

• public void addSeed(Seed seedIn)• {• seedList.add(seedIn);• }

• public ArrayList<Seed> getSeedList()• {• return seedList;• }• }

Page 136: Chapter 10 Mediator

136

• class Seed• {• private Color seedColor;• private String seedColorName;

• public Seed(Color colorIn, String seedColorNameIn)• {• seedColor = colorIn;• seedColorName = seedColorNameIn;• }

• public Color getSeedColor()• {• return seedColor;• }

• public String getSeedColorName()• {• return seedColorName;• }• }

Page 137: Chapter 10 Mediator

137

• class CupsAndSeedsMediator implements ActionListener• {• MoveOneSeedFrame frameRef;• CupsAndSeedsDB cupsAndSeedsRef;

• public CupsAndSeedsMediator(CupsAndSeedsDB dbIn, MoveOneSeedFrame frameIn)• {• cupsAndSeedsRef = dbIn;• frameRef = frameIn;• }

• public void actionPerformed(ActionEvent buttonClick)• {• String inputSeedString = frameRef.getSeedField().getText();• inputSeedString = inputSeedString.toUpperCase();• frameRef.getSeedField().setText("");• String inputCupString = frameRef.getCupField().getText();• int inputCupAsInteger = Integer.parseInt(inputCupString) - 1;• frameRef.getCupField().setText("");

• Seed seedToGet = cupsAndSeedsRef.removeSeedOfThisColor(inputSeedString);

• if(seedToGet == null)• System.out.println("XXXXXXX Didn't find seed of this color in the db.");• else• cupsAndSeedsRef.addSeedToCup(inputCupAsInteger, seedToGet);

• frameRef.repaint();• }• }

Page 138: Chapter 10 Mediator

138

A UML Diagram for the Pattern from Lasater

• Lasater’s UML diagram is given on the next overhead.

• Using that author’s terminology, the relationship between concrete colleagues is captured by a concrete mediator

• The mediator superclass is shown as having a reference to instances of the colleague superclass

• The individual concrete colleagues are also shown as having references to the concrete mediator

Page 139: Chapter 10 Mediator

139

Page 140: Chapter 10 Mediator

140

Considering the UML for the Pattern Again

• Looking at Lasater’s UML diagram raises a question:

• What is the correct diagram/correct structure for the pattern?

• In the UML diagram for the textbook’s first example, with the GUI, you see this:

• The UI and the mediator have references to each other

• They both also have references to the mediator

Page 141: Chapter 10 Mediator

141

• In the UML diagram for the textbook’s second example, with the namebase, you see this:

• The Tub and Machine (base) classes have references to the mediator

• Lasater, by contrast, shows the mediator having references to the base classes

Page 142: Chapter 10 Mediator

142

• Which of these options is correct—which things in the design should have references to which other things?

• 1. The following overhead summarizes the book’s second example, with references from the base class objects to the mediator

Page 143: Chapter 10 Mediator

143

Page 144: Chapter 10 Mediator

144

• 2. The following overhead summarizes Lasater’s example, with references from the mediator to the base class objects

Page 145: Chapter 10 Mediator

145

Page 146: Chapter 10 Mediator

146

• 3. The following overhead shows an example with references in both directions

• The book’s first example had this• Also, when you consider the reference

between the superclasses of Lasater’s example, you also have this

Page 147: Chapter 10 Mediator

147

Page 148: Chapter 10 Mediator

148

• Depending on how the code is structured, it may be necessary for the base class objects to have references to their mediator

• This would not be absolutely necessary• However, you would certainly expect the mediator to

have references to the objects that it maintains the relationships for

• 4. The following overhead shows my simplistic view of the pattern using “has-a” relationships from the mediator to the base classes

Page 149: Chapter 10 Mediator

149

Page 150: Chapter 10 Mediator

150

Page 151: Chapter 10 Mediator

151

Summary

• The Mediator pattern supports loose coupling between base class objects

• Related objects don’t refer to each other directly• Instead, they are related through the mediator• The Mediator pattern shows up in GUI

development where communication among components by means of an observer/observable structure (listeners)

Page 152: Chapter 10 Mediator

152

• Whenever it may be desirable to implement the interactions between objects in a separate class, the Mediator pattern applies

• The tub/machine example illustrated this generic (non-GUI) application of the pattern

Page 153: Chapter 10 Mediator

153

The End