⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lib0068.html

📁 java外企软件工程师就业班 J2EE方向 《J2EE架构师手册》 电子书
💻 HTML
📖 第 1 页 / 共 2 页
字号:
<html>
<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<head>
<title>Implementation Tips and Techniques</title>
<link rel="STYLESHEET" type="text/css" href="images/xpolecat.css">
<link rel="STYLESHEET" type="text/css" href="images/ie.content.css">
</head>
<body>
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr><td><div STYLE="MARGIN-LEFT: 0.15in;"><a href="toc.html"><img src="images/teamlib.gif" width="62" height="15" border="0" align="absmiddle"  alt="Team LiB"></a></div></td>
<td align="right"><div STYLE="MARGIN-LEFT: 0.15in;">
<a href="LiB0067.html"><img src="images/previous.gif" width="62" height="15" border="0" align="absmiddle" alt="Previous Section"></a>
<a href="LiB0069.html"><img src="images/next.gif" width="41" height="15" border="0" align="absmiddle" alt="Next Section"></a>
</div></td></tr></table>
<br>
<div class="chapter">
<a name="ch10"></a>
<div class="section">
<h2 class="first-section-title"><a name="306"></a><a name="ch10lev1sec1"></a>Implementation Tips and Techniques</h2><p class="first-para">
<b class="bold">Always implement </b><b class="bold"><span class="fixed">java.io.Serializable</span></b>. For a value object to be usable as an argument to any type of distributed object, such as enterprise beans or RMI services, it needs to implement <span class="fixed">Serializable</span>. There are no methods required by <span class="fixed">Serializable</span>, so implementation is easy. You're better off not putting anything in a value object that isn't serializable, such as a database connection. But if you must put a nonserializable object in a value object, declare it <span class="fixed">transient</span> so it's bypassed during any serialization attempts. <a class="internaljump" href="#ch10list01">Listing 10.1</a> is an extract of value object code.</p>
<div class="example">
<span class="example-title"><span class="example-titlelabel">Listing 10.1: </span>Sample Value Object Code</span><a name="307"></a><a name="ch10list01"></a>
<div class="formalbody">
<table class="BlueLine" border="0" cellspacing="0" cellpadding="0" width="100%">
<tr>
<td bgcolor="000080" class="bluecell"><font size="2" face="Arial" color="010100"><b><img src="_.gif" width="1" height="2" alt="Start example" border="0"></b></font></td>
</tr>
</table>
<pre class="literallayout">
   1:public class CustomerVO
   2: implements Serializable, Describable
   3:{
   4: public CustomerVO() {}
   5:
   6: public String           getCustomerId()
   7: {
   8: return _customerId;
   9: }
  10: public void             setCustomerId(String id)
  11: {
  12:   if (id == null)
  13:   {
  14: throw new IllegalArgumentException
  15:      ("Null customer Id not allowed.");
  16:   }
  17:   if (id.equals(""))
  18:   {
  19: throw new IllegalArgumentException
  20:         ("Blank customer Id not allowed.");
  21:   }
  22:   _customerId = id;
  23: }
  24:
  25: // Some code ommitted for brevity
  26: private String          _customerId = null;
  27:}
</pre>
<table class="BlueLine" border="0" cellspacing="0" cellpadding="0" width="100%">
<tr>
<td bgcolor="000080" class="bluecell"><font size="2" face="Arial" color="010100"><b><img src="_.gif" width="1" height="2" alt="End example" border="0"></b></font></td>
</tr>
</table>
<table class="BlankSpace" border="0" cellspacing="0" cellpadding="0" width="100%">
<tr>
<td height="16"></td>
</tr>
</table>
</div>
</div>
<p class="para">
<i class="emphasis">Source</i>: /src/book/sample/vo/ CustomerVO.java</p>
<a name="308"></a><a name="IDX-124"></a>
<p class="para">
<b class="bold">Always populate all fields of a value object.</b> Some programmers, for the sake of convenience, don't take the trouble to populate all fields of a value object if they only need a subset of the fields in it. In my experience, this practice saves time during construction, but it inevitably causes bugs that show up as <span class="fixed">NullPointerException</span> exceptions when something attempts to use a field that is not populated. I recommend either populating all fields of a value object or creating a new value object with the new field set.</p>
<p class="para">
<b class="bold">Always type fields accurately.</b> I've often seen programmers implement dates and numbers as strings, usually to save time when initially coding a value object. But as the application gets larger, this practice can cause confusion and inevitably results in additional conversion code where the field is used. It also leads to confusion for maintenance and causes bugs because someone will format the strings inappropriately.</p>
<p class="para">
<b class="bold">Check dependence on third-party classes in value objects.</b> Value objects are used as arguments for distributed objects, such as enterprise beans, Web services, and RMI services. If your value objects rely on third-party classes, your callers will have to include them in their classpath to call you. This can be an inconvenience for your callers and make your distributed objects harder to use.</p>
<p class="para">
<b class="bold">Make value objects self-descriptive.</b> Value objects should have the capability of providing a textual description of themselves for error-logging purposes. One technique that I use to accomplish this is to implement <span class="fixed">Describable</span>.</p>
<p class="para">
<span class="fixed">Describable</span> is an interface that specifies how a value object can provide a textual description of itself. Provided with CementJ (package <span class="fixed">org.cementj.common</span>), <span class="fixed">Describable</span> is used in error handling and logging. If you don't provide an easy way to dump the contents of a value object to a log when an exception occurs, it's tedious and time consuming to provide enough detail in the log to be able to reproduce the problem. An example of how tedious exception processing can be without <span class="fixed">Describable</span> is shown in <a class="internaljump" href="#ch10list2a">listing 10.2a</a>.</p>
<div class="example">
<span class="example-title"><span class="example-titlelabel">Listing 10.2a: </span>Exception Processing Without Describable</span><a name="309"></a><a name="ch10list2a"></a>
<div class="formalbody">
<table class="BlueLine" border="0" cellspacing="0" cellpadding="0" width="100%">
<tr>
<td bgcolor="000080" class="bluecell"><font size="2" face="Arial" color="010100"><b><img src="_.gif" width="1" height="2" alt="Start example" border="0"></b></font></td>
</tr>
</table>
<pre class="literallayout">
   1:<span class="unicode">&#8230;&#8230;&#8230;&#8230;&#8230;</span> // try block
   2:catch (Exception e)
   3:{
   4:  Logger.logError(<a name="310"></a><a name="IDX-125"></a>
   5:    "Error updating customer information: "+
   6:    "fname= "+ customerVO.getFirstName() +
   7:    "lname= "+ customerVO.getLastName() +
   8:    "addr= "+ customerVO.getAddress() +
   9:    "city= "+ customerVO.getCity() +
  10:    "state= "+ customerVO.getState() +
  11:    "zip= "+ customerVO.getZipCode())
  12:    ;
  13:}
</pre>
<table class="BlueLine" border="0" cellspacing="0" cellpadding="0" width="100%">
<tr>
<td bgcolor="000080" class="bluecell"><font size="2" face="Arial" color="010100"><b><img src="_.gif" width="1" height="2" alt="End example" border="0"></b></font></td>
</tr>
</table>
<table class="BlankSpace" border="0" cellspacing="0" cellpadding="0" width="100%">
<tr>
<td height="16"></td>
</tr>
</table>
</div>
</div>
<p class="para">Had <span class="fixed">CustomerVO</span> implemented <span class="fixed">Describable</span>, the exception-handling code would have been much shorter, as illustrated in <a class="internaljump" href="#ch10list2b">listing 10.2b</a>.</p>
<div class="example">
<span class="example-title"><span class="example-titlelabel">Listing 10.2b: </span>Exception Processing with Describable</span><a name="311"></a><a name="ch10list2b"></a>
<div class="formalbody">
<table class="BlueLine" border="0" cellspacing="0" cellpadding="0" width="100%">
<tr>
<td bgcolor="000080" class="bluecell"><font size="2" face="Arial" color="010100"><b><img src="_.gif" width="1" height="2" alt="Start example" border="0"></b></font></td>
</tr>
</table>
<pre class="literallayout">
   1:<span class="unicode">&#8230;&#8230;&#8230;&#8230;&#8230;</span> // try block
   2:catch (Exception e)
   3:{
   4:  Logger.logError (
   5:        "Error updating customer information: "+
   6:        customerVO.describe());
   7:}
</pre>
<table class="BlueLine" border="0" cellspacing="0" cellpadding="0" width="100%">
<tr>
<td bgcolor="000080" class="bluecell"><font size="2" face="Arial" color="010100"><b><img src="_.gif" width="1" height="2" alt="End example" border="0"></b></font></td>
</tr>
</table>
<table class="BlankSpace" border="0" cellspacing="0" cellpadding="0" width="100%">
<tr>
<td height="16"></td>
</tr>
</table>
</div>
</div>
<p class="para">In some cases, the string value returned by <span class="fixed">describe()</span> could be identical to the results of <span class="fixed">toString()</span>. The difference is that <span class="fixed">describe()</span> results are meant for human eyes. All too often, <span class="fixed">toString()</span> results are programmatically interpreted and not easy for humans to read and interpret. The source code to <span class="fixed">Describable</span> appears in <a class="internaljump" href="#ch10list03">listing 10.3</a>.</p>
<div class="example">
<span class="example-title"><span class="example-titlelabel">Listing 10.3: </span>Describable Interface Definition</span><a name="312"></a><a name="ch10list03"></a>
<div class="formalbody">
<table class="BlueLine" border="0" cellspacing="0" cellpadding="0" width="100%">
<tr>
<td bgcolor="000080" class="bluecell"><font size="2" face="Arial" color="010100"><b><img src="_.gif" width="1" height="2" alt="Start example" border="0"></b></font></td>
</tr>
</table>
<pre class="literallayout">
package org.cementj.common;

public interface Describable
{
  /**
   * Provides a textual version of description and state.
   */
  public String describe();
}
</pre>
<table class="BlueLine" border="0" cellspacing="0" cellpadding="0" width="100%">
<tr>
<td bgcolor="000080" class="bluecell"><font size="2" face="Arial" color="010100"><b><img src="_.gif" width="1" height="2" alt="End example" border="0"></b></font></td>
</tr>
</table>
<table class="BlankSpace" border="0" cellspacing="0" cellpadding="0" width="100%">
<tr>
<td height="16"></td>
</tr>
</table>
</div>
</div>
<p class="para">
<i class="emphasis">Source</i>: src/org/cementj/common/Describable.java</p>
<p class="para">If you prefer not to tie value objects to an outside product such as CementJ, you might consider creating a counterpart to <span class="fixed">Describable</span> in your applications.</p>
<p class="para">
<b class="bold">Always override method </b><b class="bold"><span class="fixed">toString()</span></b>. If you don't override <span class="fixed">toString()</span>, <a name="313"></a><a name="IDX-126"></a>the resulting text is not meaningful. An example from the default implementation of <span class="fixed">toString()</span> is</p>
<div class="informalexample">
<pre class="literallayout">
com.myapp.Test@3179c3
</pre>
</div>
<p class="para">There are enough classes in the JDK that accept <span class="fixed">Object</span> arguments and expect to be able to <span class="fixed">toString()</span> it that you should provide an implementation (e.g., <span class="fixed">StringBuffer</span>). The implementation of <span class="fixed">toString()</span> inherited from <span class="fixed">Object</span> isn't all that useful.</p>
<p class="para">
<b class="bold">Consider overriding methods </b><b class="bold"><span class="fixed">equals()</span></b> <b class="bold">and </b><b class="bold"><span class="fixed">hashcode()</span></b>. If a value object is ever used as a key in a <span class="fixed">HashMap</span>, <span class="fixed">Hashtable,</span> or <span class="fixed">HashSet</span>, <span class="fixed">equals()</span> and <span class="fixed">hashcode()</span> are used for key identification. The definition of these methods, inherited from <span class="fixed">Object</span>, dictates that for two value objects to be equal, they must literally be the same class instance. For example, consider a <span class="fixed">CustomerVO</span> with <span class="fixed">firstName</span> and <span class="fixed">lastName</span> fields. You could have two instances of "John Doe" that will look unequal using the <span class="fixed">equals()</span> inherited from <span class="fixed">Object</span> . You will have to override both <span class="fixed">equals()</span> and <span class="fixed">hashcode()</span> for a value object if you want it usable in any type or <span class="fixed">Map</span> object, such as <span class="fixed">Hashtable</span>, <span class="fixed">HashMap</span>, or <span class="fixed">TreeMap</span>.</p>
<p class="para">The behavior differences between a meaningful implementation of <span class="fixed">equals()</span> and the implementation inherited from <span class="fixed">Object</span> confuses many developers. The example in <a class="internaljump" href="#ch10list4a">Listing 10.4a</a> should help alleviate any confusion.</p>
<div class="example">
<span class="example-title"><span class="example-titlelabel">Listing 10.4a: </span>Sample Object.equals() Implementation</span><a name="314"></a><a name="ch10list4a"></a>
<div class="formalbody">
<table class="BlueLine" border="0" cellspacing="0" cellpadding="0" width="100%">
<tr>
<td bgcolor="000080" class="bluecell"><font size="2" face="Arial" color="010100"><b><img src="_.gif" width="1" height="2" alt="Start example" border="0"></b></font></td>
</tr>
</table>
<pre class="literallayout">
   1:    public void showObjectEqualImplementation()
   2:    {
   3:      ObjectWithoutEqualsImpl fiveAsObject =
   4:            new ObjectWithoutEqualsImpl("5");
   5:      ObjectWithoutEqualsImpl anotherFiveAsObject =
   6:            new ObjectWithoutEqualsImpl("5");
   7:      ObjectWithoutEqualsImpl sevenAsObject =
   8:            new ObjectWithoutEqualsImpl("7");
   9:
  10:     System.out.println("Object equals() demo:");
  11:     System.out.println(
  12:       "\tfiveAsObject.equals(anotherFiveAsObject): "+
  13:     fiveAsObject.equals(anotherFiveAsObject));
  14:     System.out.println(
  15:        "\tfiveAsObject.equals(sevenAsObject): "+
  16:       fiveAsObject.equals(sevenAsObject));
  17:    }
</pre>
<table class="BlueLine" border="0" cellspacing="0" cellpadding="0" width="100%">
<tr>
<td bgcolor="000080" class="bluecell"><font size="2" face="Arial" color="010100"><b><img src="_.gif" width="1" height="2" alt="End example" border="0"></b></font></td>
</tr>
</table>
<table class="BlankSpace" border="0" cellspacing="0" cellpadding="0" width="100%">
<tr>
<td height="16"></td>
</tr>
</table>
</div>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -