139
Unit 8 Mediator Summary prepared by Kirk Scott 1

Unit 8 Mediator

  • Upload
    sorena

  • View
    75

  • Download
    0

Embed Size (px)

DESCRIPTION

Unit 8 Mediator. Summary prepared by Kirk Scott. Design Patterns in Java Chapter 10 Mediator. Summary prepared by Kirk Scott. Introduction. A mediator is something that stands between one base class and another - PowerPoint PPT Presentation

Citation preview

Page 1: Unit 8 Mediator

1

Unit 8Mediator

Summary prepared by Kirk Scott

Page 2: Unit 8 Mediator

2

Design Patterns in JavaChapter 10Mediator

Summary prepared by Kirk Scott

Page 3: Unit 8 Mediator

3

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 4: Unit 8 Mediator

4

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

• This means that it could also be represented by a variety of UML diagrams

Page 5: Unit 8 Mediator

5

• 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 6: Unit 8 Mediator

6

• 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 7: Unit 8 Mediator

7

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

• The mediator becomes responsible for the relationships between classes

Page 8: Unit 8 Mediator

8

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

• The 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 9: Unit 8 Mediator

9

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 10: Unit 8 Mediator

10

• 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 11: Unit 8 Mediator

11

• 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 12: Unit 8 Mediator

12

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 13: Unit 8 Mediator

13

• 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 14: Unit 8 Mediator

14

Modeling Relationships

• Keep in mind that code typically models some reality• In that reality, individual objects may be linked with

each other• However, the relationships themselves truly are a

separate concept• 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 15: Unit 8 Mediator

15

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 16: Unit 8 Mediator

16

• 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 17: Unit 8 Mediator

17

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 18: Unit 8 Mediator

18

• 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• 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

Page 19: Unit 8 Mediator

19

• There will be a mediator– This will implement listening—the functionality for

what happens when an action is taken in the GUI• There will be base classes for tub and machine

objects, plus 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)

Page 20: Unit 8 Mediator

20

• Inherently, a relationship between the data model and the graphical user interface representation of the state of the application has to be maintained

• In this example, the mediator, a listener which stands between the GUI/client and the data model classes is responsible for maintaining the relationship

Page 21: Unit 8 Mediator

21

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 22: Unit 8 Mediator

22

• 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 23: Unit 8 Mediator

23

Page 24: Unit 8 Mediator

24

• In the interface, if you select a source machine from the first column, the tubs belonging to it appear in the second column

• Then you pick a tub in the second column and a destination machine in the third column

• Once three things are highlighted, you can press the “Do it!” button in order to move the tub from the source machine to the destination

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

Page 25: Unit 8 Mediator

25

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 26: Unit 8 Mediator

26

• 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 27: Unit 8 Mediator

27

Page 28: Unit 8 Mediator

28

Refactoring the Design

• The book observes that the methods in the MoveATub class are a mixture

• 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 29: Unit 8 Mediator

29

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 30: Unit 8 Mediator

30

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

Page 31: Unit 8 Mediator

31

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 32: Unit 8 Mediator

32

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 33: Unit 8 Mediator

33

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

Page 34: Unit 8 Mediator

34

• 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 35: Unit 8 Mediator

35

Ways of Implementing Listening

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

• Think back to how listening was implemented in CS 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 36: Unit 8 Mediator

36

• 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 37: Unit 8 Mediator

37

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

• Eventually, at the end of this course, this will lead to a discussion of the model-view-controller design pattern and the use of observers as well as listeners.

Page 38: Unit 8 Mediator

38

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 39: Unit 8 Mediator

39

• 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 40: Unit 8 Mediator

40

Page 41: Unit 8 Mediator

41

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

Page 42: Unit 8 Mediator

42

Page 43: Unit 8 Mediator

43

• 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 oriented• It keeps track of the state of machines and their

tubs

Page 44: Unit 8 Mediator

44

• MoveATubMediator implements the ActionListener and ListSelectionListener interfaces

• 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 45: Unit 8 Mediator

45

• 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 46: Unit 8 Mediator

46

• 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 47: Unit 8 Mediator

47

• 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

• There is one last blip on this example, and then I’m moving on to the next example, which I actually find more informative

Page 48: Unit 8 Mediator

48

A Sequence Diagram for the Pattern

• You’ve seen the use of listeners already in CS 202.• What’s new is that you can now apply a pattern name

to (at least part of) the role the listener class plays in the overall design

• The following challenge gets at this idea 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 49: Unit 8 Mediator

49

• 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 50: Unit 8 Mediator

50

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

Page 51: Unit 8 Mediator

51

Page 52: Unit 8 Mediator

52

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 53: Unit 8 Mediator

53

• 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 54: Unit 8 Mediator

54

• 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 55: Unit 8 Mediator

55

• 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 56: Unit 8 Mediator

56

Page 57: Unit 8 Mediator

57

• 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 58: Unit 8 Mediator

58

• 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 CS 360…

Page 59: Unit 8 Mediator

59

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 60: Unit 8 Mediator

60

Page 61: Unit 8 Mediator

61

• 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 62: Unit 8 Mediator

62

• 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 63: Unit 8 Mediator

63

• 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 64: Unit 8 Mediator

64

• 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 65: Unit 8 Mediator

65

• 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 66: Unit 8 Mediator

66

Page 67: Unit 8 Mediator

67

Page 68: Unit 8 Mediator

68

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

diagram.”

Page 69: Unit 8 Mediator

69

Page 70: Unit 8 Mediator

70

• 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 71: Unit 8 Mediator

71

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 72: Unit 8 Mediator

72

• 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 73: Unit 8 Mediator

73

Page 74: Unit 8 Mediator

74

• 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 75: Unit 8 Mediator

75

• 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 76: Unit 8 Mediator

76

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 77: Unit 8 Mediator

77

• 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 78: Unit 8 Mediator

78

• 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 79: Unit 8 Mediator

79

• 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 80: Unit 8 Mediator

80

• 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 82: Unit 8 Mediator

82

• 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 83: Unit 8 Mediator

83

• 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 right column consists of values, namely

those values that match with the keys

Page 84: Unit 8 Mediator

84

• 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 85: Unit 8 Mediator

85

• Code for the TubMediator class follows• I have gotten rid of Challenge 10.4 and just

presented the complete code

Page 86: Unit 8 Mediator

86

• 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 87: Unit 8 Mediator

87

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

Page 88: Unit 8 Mediator

88

• 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

Page 89: Unit 8 Mediator

89

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

• These methods wrap calls to the mediator object

Page 90: Unit 8 Mediator

90

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

Page 91: Unit 8 Mediator

91

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

Page 92: Unit 8 Mediator

92

• 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

• They will be discussed at length after their code is shown

Page 93: Unit 8 Mediator

93

• 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 94: Unit 8 Mediator

94

• 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 is given in the API documentation for the HashMap class

Page 95: Unit 8 Mediator

95

• 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 96: Unit 8 Mediator

96

• 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 97: Unit 8 Mediator

97

• 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 98: Unit 8 Mediator

98

• 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 99: Unit 8 Mediator

99

• 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 100: Unit 8 Mediator

100

• 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 101: Unit 8 Mediator

101

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 102: Unit 8 Mediator

102

• 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 103: Unit 8 Mediator

103

• 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 104: Unit 8 Mediator

104

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 is also has this similarity with the book’s second example:

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

Page 105: Unit 8 Mediator

105

• 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 106: Unit 8 Mediator

106

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

Page 107: Unit 8 Mediator

107

Page 108: Unit 8 Mediator

108

• 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 109: Unit 8 Mediator

109

• 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 110: Unit 8 Mediator

110

Page 111: Unit 8 Mediator

111

Code

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

• It will probably not be covered in class.

Page 112: Unit 8 Mediator

112

• 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 113: Unit 8 Mediator

113

• 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 114: Unit 8 Mediator

114

• 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 115: Unit 8 Mediator

115

• 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 116: Unit 8 Mediator

116

• 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 117: Unit 8 Mediator

117

• 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 118: Unit 8 Mediator

118

• /* 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 119: Unit 8 Mediator

119

• 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 120: Unit 8 Mediator

120

• 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 121: Unit 8 Mediator

121

• 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 122: Unit 8 Mediator

122

• 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 123: Unit 8 Mediator

123

• 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 124: Unit 8 Mediator

124

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 125: Unit 8 Mediator

125

Page 126: Unit 8 Mediator

126

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 127: Unit 8 Mediator

127

• 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 128: Unit 8 Mediator

128

• 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 129: Unit 8 Mediator

129

Page 130: Unit 8 Mediator

130

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

Page 131: Unit 8 Mediator

131

Page 132: Unit 8 Mediator

132

• 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 133: Unit 8 Mediator

133

Page 134: Unit 8 Mediator

134

• 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 135: Unit 8 Mediator

135

Page 136: Unit 8 Mediator

136

Page 137: Unit 8 Mediator

137

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 138: Unit 8 Mediator

138

• 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 139: Unit 8 Mediator

139

The End