Newsletter sign-up
View all newsletters

Enterprise Java Newsletter
Stay up to date on the latest tutorials and Java community news posted on JavaWorld

Sponsored Links

Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs

More on getters and setters

Build user interfaces without getters and setters

  • Print
  • Feedback

Page 5 of 6

EmployeeUI ui = new EmployeeUI();   
wilma.export( ui );                 // Export state to the user interface
//...
someContainer.add( ui );


Listing 3. A JComponent-based Builder

   1  import javax.swing.*;
   2  import java.awt.*;
   3  import java.awt.event.*;
   4
   5  class EmployeeUI extends JPanel implements Employee.Exporter
   6  {   private JLabel nameWidget   = new JLabel("");
   7      private JLabel idWidget     = new JLabel("");
   8      private JLabel salaryWidget = new JLabel("");
   9
  10      public void addName  ( String name   ) { nameWidget.setText(name);   }
  11      public void addID    ( String id     ) { idWidget.setText(id);   }
  12      public void addSalary( String salary ) { salaryWidget.setText(salary); }
  13
  14      public EmployeeUI()
  15      {   setLayout( new GridLayout(3,2) );
  16          add( new JLabel("Name:  ") );
  17          add( nameWidget );
  18          add( new JLabel("Employee ID:  ") );
  19          add( idWidget );
  20          add( new JLabel("Salary:  ") );
  21          add( salaryWidget );
  22      }
  23  }


What about the server side? A third implementation of Employee.Exporter (HTMLExporter in Listing 4) builds the following HTML representation of an Employee (Figure 2 shows the resulting UI):

<table border="0">
<tr><td>Name:</td><td><input type="text" name="name" value="Fred"></td></tr>
<tr><td>Employee ID:</td><td><input type="text" name="id" value="1"></td></tr>
<tr><td>Salary:</td><td><input type="text" name="salary" value="100.00"></td></tr>
</table>


Use it like this:

Employee fred = //...
HTMLExporter htmlBuilder = new HTMLExporter();
fred.export( htmlBuilder );
String htmlRepresentation = htmlBuilder.extractHTML();


You can add additional representations (XML, SQL, etc.) simply by providing your own Employee.Exporter implementations, all without modifying the Employee.

Figure 2. An HTML representation of an Employee

Listing 4. Building an HTML representation

   1  /** This particular importer creates only that part of the
   2   *  HTML page that represents attributes of the Employee.
   3   *  The surrounding context (the &lt;html&gt; tags, etc.) is
   4   *  created elsewhere.
   5   */
   6
   7  class HTMLExporter implements Employee.Exporter
   8  {
   9      private final String       HEADER = "<table border=\"0\">\n";
  10      private final StringBuffer out = new StringBuffer(HEADER);
  11
  12      public void addName( String name )
  13      {   out.append( "\t<tr><td>" );
  14          out.append( "Name:");
  15          out.append( "</td><td>" );
  16          out.append( "<input type=\"text\" name=\"name\" value=\"" );
  17          out.append( name );
  18          out.append( "\">");
  19          out.append( "</td></tr>\n" );
  20      }
  21      public void addID( String id     )
  22      {   out.append( "\t<tr><td>" );
  23          out.append( "Employee ID:");
  24          out.append( "</td><td>" );
  25          out.append( "<input type=\"text\" name=\"id\" value=\"" );
  26          out.append( id );
  27          out.append( "\">");
  28          out.append( "</td></tr>\n" );
  29      }
  30      public void addSalary( String salary )
  31      {   out.append( "\t<tr><td>" );
  32          out.append( "Salary:");
  33          out.append( "</td><td>" );
  34          out.append( "<input type=\"text\" name=\"salary\" value=\"" );
  35          out.append( salary );
  36          out.append( "\">");
  37          out.append( "</td></tr>\n" );
  38      }
  39      String extractHTML()
  40      {   out.append("</table>");
  41          String toReturn = out.toString();
  42          out.setLength(0);                   // erase the buffer
  43          out.append(HEADER);
  44          return toReturn;
  45      }
  46  }


Now let's look at the input side. The Employee constructor takes as its argument a class that I think of as a "reverse builder." This class, the Employee.Importer, really follows the same philosophy as the Gang of Four Builder, but it initializes the current object by providing default values rather than creating (and initializing) some external object. Like the output-side builder, the Importer serves to isolate the external representation of the object from the business object itself. It's not an accident, by the way, that the constructor takes an Importer argument and no import() method exists. It's a potential runtime error to create an uninitialized object and initialize it later with an "import" or "set" operation. You don't want to run the risk of using uninitialized objects.

  • Print
  • Feedback

Resources