A Name Data Class

     

A Name Data Class

Often in books, we see programs that learn us how to do things like calculate and draw and other action-verb-oriented things. In business, however, we often need to also represent things. Object-oriented programming has as one of its tenets that an object contains data and behavior. Sometimes, however, this behavior is either fairly limited, or is implemented fully in increasing usability. Take, for example, a simple thing like a person's name.

Many applications need to represent names , but they often are implemented poorly. On the one hand, a complete name gets represented as a single String. This makes it almost impossible to deal with in searches, comparisons. Other times, names are only slightly more conscientiously dealt with by offering separate Strings for each part of the name. This does make searching and comparison more accurate, but has the deleterious effect of decoupling related data, which is a maintenance nightmare. If your manager tells you that now your name collection form needs to include a middle name, for instance, you must update many different parts of the application. In a Stuts-based Web application, for instance, this would be a real drag.

If, however, you are dealing with a Name class , the organization of your data is shielded (encapsulated) behind it, so your maintenance is far easier. But you know that already. What are some other benefits to this approach? Well, for one thing, you gain total control over presentation. You can display this data exactly how you want, and offer ways for clients to include certain parts or omit others (such as the ever-questionable middle name). It also makes sure (well, encourages you, if you are being lazy) that you override equals and hashcode, and think hard about your application design and implementation.

The downside is that a Name is generally given to another entity, such as a Person. So you probably have a Person class, with a Name member, and maybe an Address member (which would be a complex object itself!), and so on, and all of a sudden you have proliferated classes and slowed down your application as it goes to the trouble of creating seven or eight objects when all you wanted was two lousy little Strings. Now, if you aren't going to use any of that additional information in a very sophisticated way, that might be overkill.

Obviously, you need to determine what your application is focused on, how many concurrent users it is likely to have, what the data will be used for, and what kinds of views you will need of the data before you go off the deep end like this. Sometimes a couple of Strings is just what the doctor ordered.

Hey! This class uses generics, in order to give you a taste for it. They are not explained in this book, and neither is the Collections API. Don't worry. The following ArrayList business simply says this: "Make a list (which is like an array that is resizable), and let it accept only objects of type Name ." Then we just call the static sort method to sort them according to our implementation of the Comparable interface.

Demonstrates

Overloaded methods, overriding methods , overloaded constructors, using generic types, using Lists, implementing interfaces, sorting Collections, using switch/case constructs, constants, JavaDoc, formatting, and usability considerations.

Name.java
 

 import java.io.Serializable; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** <p>  * Represents a person's name in numbing detail.  * Meant for use by another class (i.e, "Person").  * Implements the Comparable interface so that Name  * objects can be easily sorted alphabetically.  * Implements the Serializable interface, which is  * merely a marker interface, in order to indicate  * that it is safe to serialize objects of this type.  * This class will only compile under SDK 1.5.  * </p>  * @author eben hewitt  **/ public class Name implements Serializable, Comparable<Name> {     private String title=""; // ie, "Miss" or "Dr."     private String suffix=""; // ie, "junior" or "III"     private String given=""; //first     private String middle=""; //multiple middle     private String family=""; //last     public static final int FAMILY_GIVEN_MIDDLEINIT = 0;     public static final int FAMILY_GIVEN = 1;     public static final int GIVEN_FAMILY = 2;     public static final int GIVEN_MIDDLE_FAMILY = 3;     public static final int GIVEN_MIDDLEINIT_FAMILY = 4;     public static final int FULL_NAME_US = 5;     public static final int PREFIX_FULL_SUFFIX_US = 6;     //overloaded constructors     /**      * Constructs Name with first and last names.      */     public Name(String given, String family) {         this.given = given;         this.family = family;     }     /**      * Constructs Name with first, middle,      * and last names.      */     public Name(String given, String middle,                 String family) {         //re-use the constructor defined for just                 given + family         this(given, family);         this.middle = middle;     }     /**      * Constructs complete Name object. You can have      * multiple overloaded constructors. First calls      * the earlier constructorthat call must be      * first line of code here.      */     public Name(String title, String given,                       String middle,                       String family, String suffix) {         this(given, middle, family);         this.title = title;         this.suffix = suffix;     }     // helper methods     /**      * Gets initial character of first name as an      * initial (with an added ".").      * For example "Eben" returns "E.".      * @return The initial character of the first      * name.      */     public String getGivenInitial() {         return given.charAt(0) + ".";     }     /**      * Gets initial character of middle name as an      * initial (with an added ".").      * For example "Mann" returns "M.".      * @return The initial character of the middle      * name.      */     public String getMiddleInitial() {         return middle.charAt(0) + ".";     }     /**      * Gets initial character of first name as an      * initial (with an added ".").      * For example "Hewitt" returns "H.".      * @return The initial character of the last      * (family) name.      */     public String getFamilyInitial() {         return family.charAt(0) + ".";     }     /**      * Gets initial character of each of first,      * middle, and last names      * (with an added ".").      * For example "Eben Mann Hewitt"      * returns "E. M. H.".      * @return The initial characters of the first,      * middle, and last names.      */     public String getInitials() {         return getGivenInitial() + " " +                     getMiddleInitial() + " " +                     getFamilyInitial();     }     /**      * Returns the various parts of a name together      * in common representations.      * @param repType The manner in which you want      * the Name represented, useful      * for different purposes:      * <ul>      * <li>(default) FULL_NAME_US: Eben Mann Hewitt      * <li>FAMILY_GIVEN_MIDDLEINIT: Hewitt, Eben Mann      * <li>FAMILY_GIVEN: Hewitt, Eben      * <li>GIVEN_FAMILY: Eben Hewitt      * <li>GIVEN_MIDDLEINIT_FAMILY: Eben M. Hewitt      * <li>PREFIX_FULL_SUFFIX_US: Mr. Eben Mann      * Hewitt, Esq.      * @return The name, as represented by      * the parameter.      */     public String getName(int repType) {         switch (repType) {         case FAMILY_GIVEN_MIDDLEINIT:              return getFamily() + ", " + getGiven()                          + " " +                          getMiddleInitial();         case FAMILY_GIVEN:               return getFamily() + ", " + getGiven();         case GIVEN_FAMILY:               return getGiven() + " " + getFamily();         case GIVEN_MIDDLEINIT_FAMILY:               return getGiven() + " " +                     getMiddleInitial() +                     " " + getFamily();         case PREFIX_FULL_SUFFIX_US:         //ternary operators used to remove         //unnecessary whitespace         //in the event that title or suffix is blank               return (getTitle() != "" ? getTitle()                   + " " : "") + getGiven() +                   " " + getMiddle() + " " +                   getFamily() +                   (getSuffix() != "" ? (", " +                   getSuffix()) : "");         default :         case FULL_NAME_US:               return getGiven() + " " + getMiddle() +                      " " + getFamily();         }     }     /**      * Override of Object's toString method.      */     public String toString() {         return getName(GIVEN_FAMILY);     }     /**      * Override of Object's equals method.      * Determines object equality by testing family,      * middle, and given names as well as class.      *      */     public boolean equals(Object other){         //are they the same object?         if (this == other)               return true;         //are they of same type?         if (other != null && getClass() ==                      other.getClass()){               //since the classes are the same type,               //downcast and compare attributes                  Name n = (Name)other;                  if (n.getFamily().equals                        (this.getFamily()) &&                     n.getGiven().equals                        (this.getGiven()) &&                     n.getMiddle().equals                        (this.getMiddle()))               return true;         }               return false;     }     //overloaded getName() method:     public String getName(){         return getName(PREFIX_FULL_SUFFIX_US);     }     /**      * Required by the Comparable interface. Returns      * 0 if the objects have the same      * first-middle-last combination. Its purpose is      * to help us perform during a call to      * {@link java.util.Collections#sort}.      * Alphabetical order is preferable here.      * @return int indicating if the objects can be      * considered equivalent. A value of 0 indicates      * equivalency. A negative value indicates this      * Name comes earlier; a positive value indicates      * this Name comes later.      * @throws ClassCastException      * @see java.lang.Comparable#compareTo      * (java.lang.Object)      */     public int compareTo(Name anotherName) throws        ClassCastException {        if (! (anotherName instanceof Name))               throw new ClassCastException("Object                            must be instance " +                            "of Name to compare. ");        String thisFirstAndLast = this.toString();        String otherFirstAndLast =                   anotherName.toString();        return        thisFirstAndLast.compareTo(otherFirstAndLast);     }     //get and set methods     public void setGiven(String given) {this.given =              given; }     public String getGiven() { return given; }     public void setMiddle(String middle)             { this.middle = middle; }     public String getMiddle() { return middle; }     public void setFamily(String family)             { this.family = family; }     public String getFamily() { return family; }     public void setTitle(String title)             { this.title = title; }     public String getTitle() { return title; }     public void setSuffix(String suffix)             { this.suffix = suffix; }     public String getSuffix() { return suffix; }     //included just for testing     public static void main(String[] ar){         Name homer = new Name("Homer", "J.",                    "Simpson");         Name marge = new Name("Marge", "Simpson");         marge.setMiddle("B.");         System.out.println("Are they same? " +                     homer.equals(marge));         System.out.println(marge.getName (Name.FAMILY_GIVEN_MIDDLEINIT));         System.out.println("Implicit toString: " +                  homer);         System.out.println("Is Homer equal to Homer?                  " +                  homer.equals(new Name("Homer", "J.",                         "Simpson")));         //illustrate the sorting ability         List<Name> names = new ArrayList<Name>();         names.add(marge);         names.add(homer);         //sort and print         Collections.sort(names);         for (Name aName : names) {               System.out.println(aName);         }     } } 

Result

Are they same? false

Simpson, Marge B.

Implicit toString: Homer Simpson

Is Homer equal to Homer? true

Homer Simpson

Marge Simpson

If we had not sorted the previous list of names, then they would be returned in the order added ("marge" first, and "homer" second).

The previous Name class is useful for modeling data-type classes. Of course, classes in Java are meant to hold both data and the means of performing operations, but some classes offer a service and some classes represent simple nouns. Such as "Name." Cheers.

(source: AP, Rutgers University Study, Douglas L. Kruse)

graphics/35inf01.gif



Java Garage
Java Garage
ISBN: 0321246233
EAN: 2147483647
Year: 2006
Pages: 228
Authors: Eben Hewitt

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net