Monday, October 12, 2009

Patterns - 036: Behavioral Patterns ( Mediator )



In general, object-oriented applications consist of a set of objects that interactwith each other for the purpose of providing a service.This interaction can be direct (point-to-point) as long as the number of objects referring to each other directly is very low.

As the number of objects increases, this type of direct interaction can lead to a complex maze of references among objects. which affects the maintainability of the application. Also, having an object directly referring to other objects greatly reduces the scope for reusing these objects because of higher coupling.

( Figure 31.2)

In such cases, the Mediator pattern can be used to design a controlled,coordinated communication model for a group of objects, eliminating the needfor objects to refer to each other directly


(Figure 31.3)
The Mediator pattern suggests abstracting all object interaction details into a separate class, referred to as a Mediator. with knowledge about the interacting group of objects.

Every object in the group is still responsible for offering the service it is designed for, but objects do not interact with each other directly for this purpose.

The interaction between any two different objects is routed through the Mediator class. All objects send their messages to the mediator. The mediator then sends messages to the appropriate objects as per the application’s requirements.

The resulting design has the following major advantages:

  • With all the object interaction behavior moved into a separate (mediator) object, it becomes easier to alter the behavior of object interrelationships, by replacing the mediator with one of its subclasses with extended or altered functionality.
  • Moving inter object dependencies out of individual objects results in enhanced object re usability.
  • Because objects do not need to refer to each other directly, objects can be unit tested more easily.
  • The resulting low degree of coupling allows individual classes to be modified without affecting other classes.


Example


Consider the The FTP client simulation application.

(Figure 30.4)

Consider following minor changes
  • When the UI is first displayed, all buttons except the Exit button should be disabled.
  • When a file name is selected from the JList control displaying the local
    file system:
  1. – The Upload and Delete buttons should be enabled.
  2. – Any selected item in the remote file system display should be deselected.
  3. – The Download button should be disabled.

shows the following object interaction.

(Figure 31.5 )

As more controls are added the direct communication between objects creates a complex maze of references among objects.

Applying the Mediator pattern, an abstraction for the object interaction details can be created. This abstraction can be designed as a separate Mediator class.

(Figure 31.6)

From the Mediator class implementation it can be seen that the Mediator offers methods for different UI objects to register themselves with the Mediator. The set of object interactions to be executed when each UI control is activated (or clicked) is designed as a separate method inside the Mediator.
Client Usage of the Mediator
The client creates an instance of the Mediator. Whenever a UI object is created, the client passes the Mediator instance to it. The UI object registers itself with this instance of the Mediator.
User Interface Objects:

Mediator Interaction Because all the object interaction details ar e removed from individual UI objects to the Mediator object, the processEvent method of each of these UI objects gets reduced to a simple call to an appropriate Mediator method.



class Mediator {
    private UploadButton btnUpload;
    private DownloadButton btnDownload;
    private DeleteButton btnDelete;
    private LocalList localList;
    private RemoteList remoteList;

    public void registerUploadButton(UploadButton inp_ib) {
        btnUpload = inp_ib;
    }

    public void registerDownloadButton(
            DownloadButton inp_dnb) {
        btnDownload = inp_dnb;
    }

    public void registerDeleteButton(DeleteButton inp_db) {
        btnDelete = inp_db;
    }

    public void registerLocalList(LocalList inp_arl) {
        localList = inp_arl;
    }

    public void registerRemoteList(RemoteList inp_drl) {
        remoteList = inp_drl;
    }

    public void UploadItem() {

        int index = localList.getSelectedIndex();
        String selectedItem =
                localList.getSelectedValue().toString();
        ((DefaultListModel) localList.getModel()).remove(
                index);

        ((DefaultListModel) remoteList.getModel()).addElement(
                selectedItem);

        btnUpload.setEnabled(false);
        btnDelete.setEnabled(false);
        btnDownload.setEnabled(false);
    }

    public void DownloadItem() {
        int index = remoteList.getSelectedIndex();
        String selectedItem =
                remoteList.getSelectedValue().toString();
        ((DefaultListModel) remoteList.getModel()).remove(
                index);

        ((DefaultListModel) localList.getModel()).addElement(
                selectedItem);

        btnUpload.setEnabled(false);
        btnDelete.setEnabled(false);
        btnDownload.setEnabled(false);
    }

    public void DeleteItem() {
        int index = localList.getSelectedIndex();
        if (index >= 0) {
            ((DefaultListModel) localList.getModel()).remove(
                    index);
        }

        index = remoteList.getSelectedIndex();
        if (index >= 0) {
            ((DefaultListModel) remoteList.getModel()).remove(
                    index);
        }
        btnUpload.setEnabled(false);
        btnDelete.setEnabled(false);
        btnDownload.setEnabled(false);

    }

    public void LocalListSelect() {
        remoteList.setSelectedIndex(-1);
        btnUpload.setEnabled(true);
        btnDelete.setEnabled(true);
        btnDownload.setEnabled(false);
    }

    public void RemoteListSelect() {
        localList.setSelectedIndex(-1);
        btnUpload.setEnabled(false);
        btnDelete.setEnabled(true);
        btnDownload.setEnabled(true);
    }
}

}// end of class

No comments:

Post a Comment