chapter 10 mediator
Download
Skip this Video
Download Presentation
Chapter 10 Mediator

Loading in 2 Seconds...

play fullscreen
1 / 153

Chapter 10 Mediator - PowerPoint PPT Presentation


  • 66 Views
  • Uploaded on

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

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

PowerPoint Slideshow about ' Chapter 10 Mediator' - isi


An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
chapter 10 mediator

Chapter 10Mediator

Summary prepared by Kirk Scott

athena from wikipedia the free encyclopedia
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)
slide3

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 goddessidentified with Athena.[4]

slide4

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]

design patterns in java chapter 10 mediator

Design Patterns in JavaChapter 10Mediator

Summary prepared by Kirk Scott

introduction
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
slide10

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
slide11

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
slide12

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
slide13

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
slide14

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

  • They can be as meaningful as the bases classes themselves
  • They canhave 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
scenario
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
slide16

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
slide17

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
book definition of the pattern
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.
slide19

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
modeling relationships
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
slide21

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
concrete examples from the book
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
slide23

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
a classic example gui mediators
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.”
slide25

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
slide26

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
slide27

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
slide28

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
slide29

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
slide30

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
the scenario
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
slide32

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
slide34

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
slide35

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
extending the development scenario
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
slide37

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
refactoring the design
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
gui construction methods in the monolithic class
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
slide41

private JButtonassignButton()

  • {
  • if(assignButton == null)
  • {
  • assignButton = new JButton(“Do it!”);
  • assignButton.setEnabled(false);
  • assignButton.addActionListener(this);
  • }
  • return assignButton;
  • }
domain object construction in the monolithic class
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
listener implementation in the monolithic class
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
slide44

public void valueChanged(ListSelectionEvent e)

  • {
  • // …
  • assignButton().setEnabled(
  • !tubList().isSelectionEmpty()
  • && !machineList().isSelectionEmpty());
  • }
slide45

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
ways of implementing listening
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
slide47

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
slide48

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
redesigning the application using the pattern
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.
slide50

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
slide52

Solution 10.1

  • Figure B.11 shows a solution.
slide54

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
slide55

MoveATubMediator implements the ActionListener and ListSelectionListenerinterfaces, 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
slide56

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
slide57

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
slide58

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
a sequence diagram for the pattern
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
slide60

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.”
slide61

Solution 10.2

  • Figure B.12 shows one solution.
a last observation on the first example
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
slide64

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
slide65

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
example 2 mediators of relational integrity
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
slide67

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
slide68

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
slide69

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
slide71

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
slide72

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…
an undesirable solution to the problem
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
slide75

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
slide76

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?
slide77

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
slide78

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);
slide79

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.]
slide82

Solution 10.3

  • “Figure B.13 shows an updated object diagram.”
slide84

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.”
a table based implementation
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
slide86

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
slide88

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
slide89

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
code for a map based solution
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
slide91

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
slide92

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.)
slide93

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.
slide94

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
slide95

get

  • public Vget(Object key)
  • Returns the value to which the specified key is mapped in this hashtable.
  • Specified by: get in interface Map<K,V>
  • Specified by: get in class Dictionary<K,V>
  • Parameters: key - a key in the hashtable.
  • Returns: the value to which the key is mapped in this hashtable; null if the key is not mapped to any value in this hashtable.
  • Throws:NullPointerException - if the key is null.
  • See Also: put(Object, Object)
slide96

put

  • public Vput(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 hashtablekey.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)
slide97

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
slide98

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
slide99

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
slide100

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

  • They rely entirely on the get() and put() methods of the HashMapclass
  • 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
slide101

public class TubMediator

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

public Machine getMachine(Tub t)

  • {
  • return (Machine) tubToMachine.get(t);
  • }
  • public void set(Tub t, Machine m)
  • {
  • tubToMachine.put(t, m);
  • }
  • }
the tub class
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 tubwrap calls to the mediator object
  • It’s the mediator that’s responsible for maintaining relationships
slide104

public class Tub

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

public Machine getLocation()

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

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
slide107

public inthashCode()

  • {
  • 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);
  • }
slide108

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 HashMapclass that was shown earlier
slide109

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);
slide110

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);
slide111

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
slide112

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
slide113

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
slide114

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
back to the general discussion
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
slide116

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
slide117

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
another example
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
slide119

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
slide122

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.
slide123

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
slide125
Code
  • The code for the application is given on the following overheads for reference.
  • It will probably not be covered in class.
slide126

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)
  • {
  • MoveOneSeedFramemyframe = new MoveOneSeedFrame();
  • myframe.setVisible(true);
  • }
  • }
slide127

class MoveOneSeedFrame extends JFrame

  • {
  • private CupsAndSeedsDBcupsAndSeeds;
  • private CupsAndSeedsMediator mediator;
  • private JTextFieldseedField;
  • private JTextFieldcupField;
  • private JButtonmoveSeedButton;
  • private MoveOneSeedPanelmyOutputPanel;
  • private JPanelmyInputPanel;
  • 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);
slide128

JPanelmyInputPanel = 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);
slide129

myOutputPanel = new MoveOneSeedPanel(cupsAndSeeds);

  • Container contentPane = getContentPane();
  • contentPane.add(myInputPanel, "North");
  • contentPane.add(myOutputPanel, "Center");
  • }
  • public JButtongetMoveSeedButton()
  • {
  • return moveSeedButton;
  • }
  • public JTextFieldgetSeedField()
  • {
  • return seedField;
  • }
  • public JTextFieldgetCupField()
  • {
  • return cupField;
  • }
  • }
slide130

class MoveOneSeedPanel extends JPanel

  • {
  • CupsAndSeedsDBshownDB;
  • public MoveOneSeedPanel(CupsAndSeedsDBdbIn)
  • {
  • shownDB = dbIn;
  • }
  • public void paintComponent(Graphics g)
  • {
  • inti;
  • intcupX = 180;
  • intcupY = 180;
  • intcupW = 40;
  • intcupH = 40;
  • intseedX;
  • intseedY;
  • Rectangle cupRectangle;
  • Ellipse2D.Double seedDot;
  • intseedDiam = 7;
  • ArrayList<Cup> cupList;
  • ArrayList<Seed> seedList;
  • Graphics2D g2 = (Graphics2D) g;
  • super.paintComponent(g2);
  • cupList = shownDB.getCupList();
  • System.out.println("Before loops");
slide131

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");
  • }
  • }
slide132

/* 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;
slide133

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);
  • }
slide134

public ArrayListgetCupList()

  • {
  • return cupList;
  • }
  • public Seed removeSeedOfThisColor(String colorNameIn)
  • {
  • IteratorcupIterator = cupList.iterator();
  • IteratorseedIterator;
  • 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;
  • }
slide135

public void addSeedToCup(intcupNumber, 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;
  • }
  • }
slide136

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;
  • }
  • }
slide137

class CupsAndSeedsMediator implements ActionListener

  • {
  • MoveOneSeedFrameframeRef;
  • CupsAndSeedsDBcupsAndSeedsRef;
  • public CupsAndSeedsMediator(CupsAndSeedsDBdbIn, MoveOneSeedFrameframeIn)
  • {
  • cupsAndSeedsRef = dbIn;
  • frameRef = frameIn;
  • }
  • public void actionPerformed(ActionEventbuttonClick)
  • {
  • String inputSeedString = frameRef.getSeedField().getText();
  • inputSeedString = inputSeedString.toUpperCase();
  • frameRef.getSeedField().setText("");
  • String inputCupString = frameRef.getCupField().getText();
  • intinputCupAsInteger = 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();
  • }
  • }
a uml diagram for the pattern from lasater
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
considering the uml for the pattern again
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
slide141

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
slide142

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
slide144

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

slide146

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
slide148

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
summary
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)
slide152

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
ad