CroftSoft / Library / Tutorials

Interface Mail

David Wallace Croft

2008 Jan 27 Sun


Java interface Mail is used as an intermediary to broadcast and retrieve messages passed between objects. Class FlipMail is an implementation of interface Mail which flips the outgoing and incoming messages lists when updated. FlipMail simplifies desktop application programming by reducing coupling between Model, View, and Controller (MVC) objects and controlling when state change request and event messages are processed.

This tutorial is a continuation of the message-oriented programming (MoP) tutorials Interface Slot and Interface Seq. Interface Mail is simply an extension Slot and Seq.

    package com.croftsoft.core.util.mail;

    import com.croftsoft.core.role.Slot;
    import com.croftsoft.core.util.seq.Seq;

    /**********************************************************************
    * An interface for sending and receiving messages.
    *
    * @since
    *   2008-01-27
    * @author
    *   <a href="https://www.croftsoft.com/">David Wallace Croft</a>
    **********************************************************************/

    public interface  Mail<Message>
      extends Seq<Message>, Slot<Message>
    ///////////////////////////////////////////////////////////////////////
    ///////////////////////////////////////////////////////////////////////
    {

    ///////////////////////////////////////////////////////////////////////
    ///////////////////////////////////////////////////////////////////////
    }

Interface Seq provides read-only access to a sequence of messages via its get() method. Interface Slot provides write-only access to send a message via its offer() method. With a reference to a Mail instance, an object can both broadcast and retrieve messages.

    public  ExemplarModelImp ( final Mail<ExemplarMessage>  mail )
    ///////////////////////////////////////////////////////////////////////
    {
      NullException.check ( this.mail = mail );
    }

Since this communication is indirect, an object can communicate with other objects without requiring references to those other objects. Instead of passing references to recipient objects as constructor method arguments or attaching them as listeners, simply provide each object with a reference to a Mail instance as a constructor argument. Since objects do not have references to each other, there is also no need to nullify references and remove listeners when an object is deleted.

    public void  update ( )
    ///////////////////////////////////////////////////////////////////////
    {
      final int  size = mail.size ( );

      for ( int  i = 0; i < size; i++ )
      {
        final ExemplarMessage  exemplarMessage = mail.get ( i );

        final ExemplarMessage.Type  type = exemplarMessage.getType ( );

        switch ( type )
        {
          case INCREMENT_CLICK_COUNT:

            clickCount++;

            mail.offer ( ExemplarMessage.CLICK_COUNT_CHANGED_INSTANCE );

            break;

          default:

            // ignore
        }
      }
    }

In the preceding code listing, an object both retrieves and broadcasts a message during its update phase. In this case the object retrieves a request to change its internal state and then broadcasts an event message upon doing so. Note that there is no setter method to call; change requests must be relayed via Mail. Note also that there are no methods to add and remove listeners; all events are posted to Mail. This zero coupling between communicating objects is a key benefit of message-oriented programming (MoP).

    package com.croftsoft.core.util.mail;

    import java.util.*;

    import com.croftsoft.core.lang.lifecycle.Updatable;

    /**********************************************************************
    * Replaces incoming messages with outgoing messages when updated.
    *
    * @since
    *   2008-01-27
    * @author
    *   <a href="https://www.croftsoft.com/">David Wallace Croft</a>
    **********************************************************************/

    public final class  FlipMail<Message>
      implements Mail<Message>, Updatable
    ///////////////////////////////////////////////////////////////////////
    ///////////////////////////////////////////////////////////////////////
    {

    private List<Message>
      incomingList,
      outgoingList,
      swappingList;

    ///////////////////////////////////////////////////////////////////////
    ///////////////////////////////////////////////////////////////////////

    public  FlipMail ( )
    ///////////////////////////////////////////////////////////////////////
    {
      incomingList = new LinkedList<Message> ( );

      outgoingList = new LinkedList<Message> ( );
    }

    ///////////////////////////////////////////////////////////////////////
    ///////////////////////////////////////////////////////////////////////

    public Message  get ( final int  index )
    ///////////////////////////////////////////////////////////////////////
    {
      return incomingList.get ( index );
    }

    public int  size ( )
    ///////////////////////////////////////////////////////////////////////
    {
      return incomingList.size ( );
    }

    public boolean  offer ( Message  message )
    ///////////////////////////////////////////////////////////////////////
    {
      return outgoingList.add ( message );
    }

    public void  update ( )
    ///////////////////////////////////////////////////////////////////////
    {
      swappingList = incomingList;

      incomingList = outgoingList;

      outgoingList = swappingList;

      outgoingList.clear ( );
    }

    ///////////////////////////////////////////////////////////////////////
    ///////////////////////////////////////////////////////////////////////
    }

Class FlipMail is an implementation of interface Mail which is backed by two LinkedList objects, incomingList and outgoingList. Between updates, objects read messages from the incomingList and post messages to the outgoingList. Note that the incomingList is strictly read-only and the outgoingList is write-only.

When the update() method is called, the references to the incomingList and outgoingList are swapped. The outgoingList is then cleared. The effect is that the previously read messages in the incomingList are discarded and the previously inaccessible messages in the outgoingList become available.

      final Updatable [ ]  updatables = new Updatable [ ] {
        flipMail,
        exemplarModel,
        exemplarView,
        exemplarController };

Once per loop, the update() method of each of your communicating objects are called so that they can retrieve and broadcast messages. The update() method of your FlipMail object is also called to replace the old messages with the new messages. I update FlipMail before the Model-View-Controller (MVC) objects so that any pending requests to initialize state become available during the first loop.

Because state change request messages and event messages posted to the outgoingList during the current loop are not processed until the next loop, it is much less likely that your program will have the problem of model state being changed while it is being read. Another problem that is avoided is having your program lock up in a runaway loop in which an event triggers a state change request which then triggers the same event again. It also makes it easier to debug your program by examining the messages stored in FlipMail at each loop transition.

If you find yourself passing references between MVC classes excessively or you find it difficult to debug a sequence of method calls between tightly coupled classes, I recommend that you consider moving to a message-oriented programming (MoP) style instead. If you can imagine objects without setter methods, you are on your way to the simplicity of zero coupling.

 
 
 
CroftSoft
 
 
About
Library
-Books
-Code
-Courses
-Links
-Media
-Software
-Tutorials
People
Portfolio
Update
 
 
Google
CroftSoft Web

 

Creative Commons License
© 2008 CroftSoft Inc.
You may copy this webpage under the terms of the
Creative Commons Attribution License.