<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
  <channel>
    <title>polygoncell</title>
    <description>我的Blog
http://spaces.msn.com/members/polygoncell/
http://polygoncell.blogspot.com/</description>
    <link>http://polygoncell.javaeye.com</link>
    <language>UTF-8</language>
    <copyright>Copyright 2003-2008, JavaEye.com</copyright>
    <docs>http://blogs.law.harvard.edu/tech/rss</docs>
    <generator>JavaEye - 做最棒的软件开发交流社区</generator>
          <item>
        <title>I18N DateFormat, 巧用int干掉if else</title>
        <author>polygoncell</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://polygoncell.javaeye.com">polygoncell</a>&nbsp;
                    链接：<a href="http://polygoncell.javaeye.com/blog/240688" style="color:red;">http://polygoncell.javaeye.com/blog/240688</a>&nbsp;
          发表时间: 2008年09月11日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          DateFormat大家应该都知道，用起来挺麻烦的，要考虑如下问题：<br /><br />1.	I18N<br />2.	带不带time<br />3.	如何支持多种不同的Patterns<br /><br />单单考虑I18N，问题很好好解决，直接调用<br /><br /><pre name="code" class="java">public final static DateFormat getDateInstance(int style)</pre><br /><br />即可获得几个常见的DateFormats。但是怎么添加自己需要的Pattern呢？例如希望英文版的软件支持：“MM/dd/yy”，“MM/dd/yyyy”以及带时间的“MM/dd/yy hh:mm”，“MM/dd/yyyy hh:mm”。直接硬编码当然简单，但是修改起来麻烦，考虑使用Resource Bundles，将日期和时间分开写，各种希望支持的日期Format用分号隔开，例如：<br /><br /><pre name="code" class="java">
dateformat.date.support = MM/dd/yy;MM/dd/yyyy
dateFormat.time.show = hh:mm
</pre><br /><br />然后在程序里面写循环组合一下。例如：<br /><br /><pre name="code" class="java">
List&lt;DateFormat> getSupportedFormats(boolean withTime) {
ResourceMap rm = context.getResourceMap(getClass());
		String timeFormat = rm.getString("dateFormat.time.show");
		List&lt;DateFormat> formats = new ArrayList&lt;DateFormat>();
		for (String format : rm.getString("dateformat.date.support").split(";")) {
			formats.add(new SimpleDateFormat(format));
			formats.add(new SimpleDateFormat(format + " "
					+ timeFormat));
		}
		formats.add(DateFormat.getInstance());
		return formats;
}
</pre><br /><br />注意返回的formats中第一个DateFormat会被作为默认的显示Format的使用，这段代码并没用考虑是否显示时间。加上时间判断后，通常使用if else来写：<br /><br /><pre name="code" class="java">
List&lt;DateFormat> getSupportedFormats(boolean withTime) {
ResourceMap rm = context.getResourceMap(getClass());
		String timeFormat = rm.getString("dateFormat.time.show");
		List&lt;DateFormat> formats = new ArrayList&lt;DateFormat>();
		for (String format : rm.getString("dateformat.date.support").split(";")) {
		  if (withTime) {
                     formats.add(new SimpleDateFormat(format + " "
					+ timeFormat));
                     formats.add(new SimpleDateFormat(format));

                } else {
                     formats.add(new SimpleDateFormat(format));
		     formats.add(new SimpleDateFormat(format + " "
					+ timeFormat));
                  }
		}
		formats.add(DateFormat.getInstance());
		return formats;
}
</pre><br /><br />代码看起来挺痛苦的，有重复，还有我很讨厌的if else，就算是重构一个方法出来也没好到哪里去。考虑用一个int变量踢掉if else，先把resource Bundles里面的dateformat.date.support掉个个，默认显示用的那个Format的放在最后：<br /><br /><pre name="code" class="java">
dateformat.date.support = MM/dd/yyyy;MM/dd/yy
dateFormat.time.show = hh:mm
</pre><br /><br />代码这么写：<br /><br /><pre name="code" class="java">
List&lt;DateFormat> getSupportedFormats(boolean withTime) {
		ResourceMap rm = context.getResourceMap(getClass());
		String timeFormat = rm.getString("dateFormat.time.show");
		List&lt;DateFormat> formats = new ArrayList&lt;DateFormat>();
		// withTime = true -> date with time format will be added first. Otherwise 
		// the date format first
		int i = withTime ? 1 : 0;
		formats.add(DateFormat.getInstance());
		for (String format : rm.getString("dateformat.date.support").split(";")) {
			formats.add(i % 2 , new SimpleDateFormat(format));
			formats.add((i + 1) % 2, new SimpleDateFormat(format + " "
					+ timeFormat));
		}
		return formats;
	}
</pre><br /><br />这里利用了对int i 取余以及List集合的add()方法会将老的对象全部向右推的功能，这样处理就可以解决所有问题。根据withTime这个开关，期望的DateFormat会被设定为默认显示的Format。<br /><br />至此，这个方法：<br /><br />1.	支持I18N<br />2.	支持自定义多种Patterns，需要支持新的patterns时，直接在resource bundles里面添加，代码不用改动<br />3.	支持切换是否显示时间<br /><br />测试代码如下：<br /><br /><pre name="code" class="java">
public class FormattedTextFieldFactoryTest {

	private static DateFormatHelper helper;

	@BeforeClass
	public static void init() {
		Locale.setDefault(Locale.US);
		helper = new DateFormatHelper();
	}

	public void addSupportedFormats() {
		List&lt;DateFormat> list = helper.getSupportedFormats(false);
		assertEquals(list.size(), 5);
		assertEquals(list.get(0).format(createDate(2008, 10, 16)),
				"10/16/08");

		list = helper.getSupportedFormats(true);
		assertEquals(list.size(), 5);
		assertEquals(list.get(0).format(createDate(2008, 10, 16)),
				"10/16/08 12:00");
	}

	private Date createDate(int year, int month, int date) {
		GregorianCalendar cal = new GregorianCalendar();
		cal.clear();
		cal.set(Calendar.YEAR, year);
		cal.set(Calendar.MONTH, month - 1);
		cal.set(Calendar.DATE, date);
		return cal.getTime();
	}
}
</pre>
          <br/><br/>
          <span style="color:red;">
            <a href="http://polygoncell.javaeye.com/blog/240688#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">Windows7在微软WinHEC 2008上揭开神秘面纱</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 11 Sep 2008 16:41:58 +0800</pubDate>
        <link>http://polygoncell.javaeye.com/blog/240688</link>
        <guid>http://polygoncell.javaeye.com/blog/240688</guid>
      </item>
          <item>
        <title>Weblogic是不是快要SQQ了？</title>
        <author>polygoncell</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://polygoncell.javaeye.com">polygoncell</a>&nbsp;
                    链接：<a href="http://polygoncell.javaeye.com/blog/234594" style="color:red;">http://polygoncell.javaeye.com/blog/234594</a>&nbsp;
          发表时间: 2008年08月29日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          先表明身份，我是JBoss用户，项目中使用EJB3，对于使用其他的Application Server并不排斥。<br /><br />今天无聊，上Amazon看看有什么新书，心血来潮，找了找关于三大AS的书，结果发现关于Weblogic的书基本上从2004开始就再也没有出过新的。唯独有一本2007年出的书:Affinity: Managing Java Application Servers涉及到weblogic，但是并不是单独针对weblogic的。<br /><br />看看websphere，06，07，08都一直有新书在出版。<br /><br />关于JBoss的书在06， 07年也沉寂了好长一段时间，不过JBoss本身的开发进度也不是很快，AS 5 RC1才发布了2个多月。 我目前一直在用4.2.x，盼星星盼月亮地盼着JBoss AS 5 GA发布，到现在还是未知数。 说道书，最新的JBoss in Action已经基本完稿，发布在即，必入。<br /><br />哦对了，还有个新秀Glassfish，目前还是初期阶段，amazon上有两本相关书籍，未来情况不明，观望。 <br />至于Geronimo，目前还没听说哪位朋友在项目中真正采用的，Amazon上有两本相关书籍，均是2006年出版的，观望。<br /><br />个人认为，使用JBoss的人看重它开源，有活跃的社区，有丰富的书籍和文档，开发过程中出现问题话，有足够多的途径来解决：或者看书看文档，或者到社区提问，再不济也可以读代码。<br /><br />单从相关技术书籍出版现状来看，Weblogic似乎快不行了，至少已经淡出了技术书籍作者的视线。<br /><br />我没有使用过weblogic，所以不太清楚大家是怎么开发的，从哪里获得必要的开发资源的，oracle提供的技术支持作用大么？大家在项目中使用weblogica的多么？
          <br/><br/>
          <span style="color:red;">
            <a href="http://polygoncell.javaeye.com/blog/234594#comments" style="color:red;">已有 <strong>59</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">Windows7在微软WinHEC 2008上揭开神秘面纱</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 29 Aug 2008 20:18:57 +0800</pubDate>
        <link>http://polygoncell.javaeye.com/blog/234594</link>
        <guid>http://polygoncell.javaeye.com/blog/234594</guid>
      </item>
          <item>
        <title>ubuntu vs. windows for java development</title>
        <author>polygoncell</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://polygoncell.javaeye.com">polygoncell</a>&nbsp;
                    链接：<a href="http://polygoncell.javaeye.com/blog/219673" style="color:red;">http://polygoncell.javaeye.com/blog/219673</a>&nbsp;
          发表时间: 2008年07月25日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          我在讨论开发Swing通用数据模块的帖子（<a href="http://www.javaeye.com/topic/216556" target="_blank">http://www.javaeye.com/topic/216556</a>）里提到了ubuntu，<br />刚才有朋友发短信过来问我为什么ubuntu比windows好。当时我正在上班，就写下了9条优势回复给他了。后来想想 ，这个问题可能对大家都有用，就发个帖子过来，欢迎大家各抒己见。<br /><br />请注意比较的前提是针对Java开发的，9条优势如下：<br /><br />1. ubuntu 免费<br />2. ubuntu易于安装， live cd -> install<br />3. 机器配置不需要太高<br />4. get-app用起来太爽了<br />5. less + vim 搞定一些配置，远程调控很方便（putty）<br />6. 对于Java开发而言，windows能干的，ubuntu全能<br />7. 服务器一般运行在Linux上，直接在Ubuntu下开发节省了迁移的工作<br />8. 体验一下ubuntu吧，它很酷<br />9. better performance，看这里：<a href="http://mssaleh.wordpress.com/2008/05/19/ubuntu-804-lts- vs-windows-xp-sp3-application-performance-benchmark/" target="_blank">http://mssaleh.wordpress.com/2008/05/19/ubuntu-804-lts- vs-windows-xp-sp3-application-performance-benchmark/</a><br />尤其是multi tasks那一项<br /><br />还有很多，暂时还没想起来，喜欢ubuntu的朋友快来补充。 <br /><br />BTW： 64位的ubuntu最好现在不要装，好多程序运行不起来，尤其是用在你的私人电脑上。工作之余要是想要看个rmvb什么的挺费劲的。
          <br/><br/>
          <span style="color:red;">
            <a href="http://polygoncell.javaeye.com/blog/219673#comments" style="color:red;">已有 <strong>99</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">Windows7在微软WinHEC 2008上揭开神秘面纱</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 25 Jul 2008 21:55:11 +0800</pubDate>
        <link>http://polygoncell.javaeye.com/blog/219673</link>
        <guid>http://polygoncell.javaeye.com/blog/219673</guid>
      </item>
          <item>
        <title>connect to the matrix</title>
        <author>polygoncell</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://polygoncell.javaeye.com">polygoncell</a>&nbsp;
                    链接：<a href="http://polygoncell.javaeye.com/blog/216995" style="color:red;">http://polygoncell.javaeye.com/blog/216995</a>&nbsp;
          发表时间: 2008年07月21日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          呵呵，今天好事不断啊。<br /><br />首先，大师级的人物Kirill Grouchnikov在他的swing links中加入了我关于通用验证模块博文的链接：<br /><br />Alex himself continues writing about the JXLayer project and talks about the internal painting implementation in his latest entry. <strong>Jing Ge</strong> has a follow up entry in which he builds a complete validation module using BeansBinding, JXLayer and Hibernate Validator.<br /><br />原文见这里： <a href="http://www.pushing-pixels.org/?p=373" target="_blank">http://www.pushing-pixels.org/?p=373</a><br /><br />其次，Alex接手Swing Application Framework了！
          <br/><br/>
          <span style="color:red;">
            <a href="http://polygoncell.javaeye.com/blog/216995#comments" style="color:red;">已有 <strong>1</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">Windows7在微软WinHEC 2008上揭开神秘面纱</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 21 Jul 2008 16:04:49 +0800</pubDate>
        <link>http://polygoncell.javaeye.com/blog/216995</link>
        <guid>http://polygoncell.javaeye.com/blog/216995</guid>
      </item>
          <item>
        <title>适用于各类Swing应用的通用数据验证模块</title>
        <author>polygoncell</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://polygoncell.javaeye.com">polygoncell</a>&nbsp;
                    链接：<a href="http://polygoncell.javaeye.com/blog/216556" style="color:red;">http://polygoncell.javaeye.com/blog/216556</a>&nbsp;
          发表时间: 2008年07月19日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p><span style="color: red;"><strong>请注意：本文的版权归作者所有，如转载请注明出处。</strong>
</span>
<br />
<br />
这段时间真是忙得要死，一方面要开发公司项目的系统框架，要将项目分成不同的子项目，编写核心代码；另一方面要将极限编程（XP）引入团队开发，部署各类XP需要的服务例如subversion啦，ant+ivy啦，Hudson啦等等。顺便说句题外话，ubuntu还真是不是一般的好用，建议有能力的全部转到ubuntu上去开发。<br />
<br />
我目前开发的这个框架的客户端是具肥的客户端，也就是Swing客户端了。Swing应用相对于Web应用有很多优势，因为它更肥。数据验证就是其中一个。当然现在的Web应用通过使用Ajax也要比以前强很多了，但是还是避免不了在验证数据时向服务段发出请求，至少你无法避免验证结果从Web服务器传输到用户浏览器上这段过程。而Swing这类肥客户端可以实现完全在本地对数据进行验证，甚至可以断网继续工作（这也是Web应用目前在研发的一个重要课题）。<br />
<br />
前段时间开发出了一个可以应用于所有Swing应用的通用数据验证模块，发现它在项目中使用后，对于普通的数据验证,程序员几乎不需要编码，效率提高了不少，就写了一篇博文拿出来和大家分享。原文是用英文写的，在这里：<a href="http://polygoncell.blogspot.com/2008/07/validation-module-for-swing-application.html" target="_blank">http://polygoncell.blogspot.com/2008/07/validation-module-for-swing-application.html</a>
。英文好的朋友可以直接去那里看。<br />
<br />
编写这个模块使用了很多不同的开源框架和类库，其中很重要的一个就是JXLayer。文章写完后，我就跑去邀请JXLayer的作者Alexp来指点一下，然后就在我的文章后面开始了一段讨论，挺有意思的，他不愧为是Swing team里面的牛人啊！厉害啊！呵呵。<br />
<br />
ok，回到今天这篇文章的正题。今天的主要目的是将我的英文博文翻译成中文（自己的文章，我就不逐字逐句翻译了，意思到了就行了，可能还会随兴展开一番讨论）在这里展示给大家，与大家分享开发经验，希望大家能够从中获益，也希望能够以文会友，广交朋友。废话少说，切入正题。<br />
<br />
数据验证（Validation）一直是软件开发中非常重要的一环，有了它，你的系统会让客户感到更加友善，同时你的系统也得到了一定程度的保护。一般来说，数据验证既可以在客户端也可以在服务端。默认的JSF数据验证就是在服务端，数据只能在被提交以后才能够被验证，然后把错误信息传递回用户的浏览器。后来大规模使用Ajax后，基本可以实现对修改的数据&ldquo;即时&rdquo;验证，注意这里是个打了引号的即时，数据事实上还是要在浏览器和服务端之间进行传递的，只不过Ajax将这种传递改为隐式了而已，理论上并没有真正实现（断网）即时验证。而在Swing应用上就能够达成这种愿望。<br />
<br />
事实上，开发Swing应用时，数据验证一直比较棘手，需要手工编码的地方太多，效率不高。后来出了JGoodies Validation 结合JGoodies binding后，好了一些。这个JGoodies Validation既可以实现model层面的验证，也可以实现Bean层面的验证，但是多年使用下来，发现其实它比较适用于中小项目，而且要编写的代码其实一点不比自己手动编写的少。<br />
<br />
JGoodies流行了一段时间后，sun开始推出自己的bean绑定方案：beansbinding（JSR 295），我个人感觉要比JGoodies binding好用（JGoodies的作者Karsten也在专家组里，这个人我以前和他一起共事过，我的msn space里面还有跟他的合影，绝对是Swing界的牛人）。这个beansbinding也提供数据验证，但是它的这个数据验证只是在target被改动后，数据被同步回source之前才会起作用，使用起来局限性比较大，而且编码量也不小。<br />
<br />
由于目前绝大部分项目是基于POJO的，Hibernate validator已经提供了一个很好的数据验证框架，我们完全没必要再重复发明轮子，我们应该努力站在巨人的肩膀上，这样我们才能站得更高，看得更远。于是我考虑结合beansbinding和Hibernate Validator开发数据验证。还有一个重要的问题，那就是数据错误的时候，需要在用户界面上展示相应的信息，例如Error icon和错误提示，这部分我考虑使用JXLayer。<br />
<br />
你可以在如下链接中找到相关框架的具体信息： <br />
<br />
1. Hibernate Validator： <a href="http://www.hibernate.org/hib_docs/validator/reference/en/html_single/" target="_blank">http://www.hibernate.org/hib_docs/validator/reference/en/html_single/</a>
<br />
2. Beansbinding: <a href="https://beansbinding.dev.java.net/" target="_blank">https://beansbinding.dev.java.net/</a>
<br />
3. JXlayer: <a href="http://weblogs.java.net/blog/alexfromsun/" target="_blank">http://weblogs.java.net/blog/alexfromsun/</a>
<br />
<br />
阅读这篇文章，不需要你熟悉这些类库，不过了解这些类库能够帮助你更好地理解这篇文章。<br />
<br />
我的这个通用模块是参考JXLayer里面的一个demo类TextValidationDemo的，这个JXlayer是由Alexander Potochkin开发的，我很喜欢，使用起来很顺手，强烈推荐使用。<br />
<br />
下面开始介绍代码。首先是建立一个java项目，对于这个小项目，我使用netbeans。这里说句题外话，中型和大型的Swing应用，建议最好还是不要使用netbeans的GUI Builder，一方面它生成的代码超级烂，另一方面很难测试。目前市面上有很多好用的layout的框架，例如 JGoodies form和MigLayout，开发效率绝对不比netbeans的GUI builder差，你还不需要面对令人头疼的机器成的代码。<br />
<br />
项目创建好后，加入类库：<br />
<br />
<img src="http://bp2.blogger.com/_kE1wl-BJf90/SIBqgMo4shI/AAAAAAAAAAM/SMNf6l7bfw8/s320/image002.jpg" alt="" />
<br />
<br />
然后写一个persistence bean:<br /></p>
<pre name="code" class="java">package de.jingge.domain;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import org.hibernate.validator.Length;
import org.hibernate.validator.NotEmpty;

@Entity
public class Country extends AbstractBean {

private static final long serialVersionUID = 5341382564159667599L;
public static final String PROPERTYNAME_NAME = &quot;name&quot;;
public static final String PROPERTYNAME_CODE = &quot;code&quot;;
private String name;
private String code;
private Long id;

public Country() {
}

public Country(String code, String name) {
    super();
    setCode(code);
    setName(name);
}

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() {
    return id;
}

public void setId(Long id) {
    this.id = id;
}

@NotEmpty
public String getName() {
    return name;
}

public void setName(String name) {
    firePropertyChange(PROPERTYNAME_NAME, this.name, this.name = name);
}

@Length(min=2, max= 2, message=&quot;Code length must be 2&quot;)
@NotEmpty
public String getCode() {
    return code;
}

public void setCode(String code) {
    firePropertyChange(PROPERTYNAME_CODE, this.code, this.code = code);
}
}
</pre>
<p>
<br />
<br />
这里我为了强调可以在Swing客户端直接使用和验证persistence bean，故意写了一个persistence bean，实际应用中，这个类只需要是一个pojo就行了。<br />
<br />
这个Country类代表一个国家，它有两个属性，code和name，我给他们分别加上个各自的验证限制。code不能为空，且必须正好是两个字符，例如CN，DE，US。name不能为空。这些annotaion均出自Hibernate Validator。那个父类AbstractBean出自SwingX类库，我们的Country类继承了它之后就可以支持property change event了。<br />
<br />
ok, 下面可以开始编写这个模块的核心代码了。前面说过，我会使用JXlayer。使用它的好处是：所有JXlayer的painting event都会被转到UI类来，我们只需要编写一个集成Hibernate Validator的UI类就可以了，我称这个类为HibernateValidationUI，代码如下：<br /></p>
<pre name="code" class="java">package de.jingge.view;

import java.awt.Graphics2D;
import java.awt.image.BufferedImage;

import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.text.JTextComponent;

import org.hibernate.validator.ClassValidator;
import org.hibernate.validator.InvalidValue;
import org.jdesktop.beansbinding.ELProperty;
import org.jdesktop.beansbinding.PropertyStateEvent;
import org.jdesktop.beansbinding.PropertyStateListener;
import org.jdesktop.jxlayer.JXLayer;
import org.jdesktop.jxlayer.plaf.AbstractLayerUI;

/**
* Header:
* Description: A layerUI which will validate the referenced property value of
* the object each time when the paint(...) method is called.

* The value of the given object property will be observed.
* Note: This UI works only with {@link JXLayer}. Any change of the property
* will force repainting the UI. The work process looks like: property changed -&gt;
* jxlayer will be repainted -&gt; the paint(...) method of this UI will be called.
* The logic of validation will be handled by the Hibernate validator
* framework.
*
*/
public class HibernateValidationUI extends AbstractLayerUI&lt;jTextComponent&gt; {

private Object object;
private String propertyName;
private ClassValidator validator;
private ELProperty elProperty;
private PropertyStateListener propertyChangeHandler;

public HibernateValidationUI(Object obj, String propertyName) {
    this.object = obj;
    this.propertyName = propertyName;
    propertyChangeHandler = new PropertyChangeHandler();
    validator = new ClassValidator(obj.getClass());

    elProperty = ELProperty.create(&quot;${&quot; + propertyName + &quot;}&quot;);
}

public void installUI(JComponent c) {
    super.installUI(c);
    elProperty.addPropertyStateListener(object, propertyChangeHandler);
}

public void uninstallUI(JComponent c) {
    super.uninstallUI(c);
    elProperty.removePropertyStateListener(object, propertyChangeHandler);
}

protected void paintLayer(Graphics2D g2, JXLayer&lt;jTextComponent&gt; l) {
    super.paintLayer(g2, l);
    InvalidValue[] validationMessages = validator.getInvalidValues(object,
            propertyName);
    if (validationMessages.length &gt; 0) {
        BufferedImage image = Java2DIconFactory.createErrorIcon();
        g2.drawImage(image, l.getWidth() - image.getWidth() - 1,
                l.getHeight() - 8, null);
        l.getView().setToolTipText(validationMessages[0].getMessage());

        return;
    }
    l.getView().setToolTipText(null);
}

boolean isValid() {
    return validator.getInvalidValues(object, propertyName).length == 0;
}

class PropertyChangeHandler implements PropertyStateListener {

    @Override
    public void propertyStateChanged(PropertyStateEvent pse) {
        setDirty(true);
    }
}
}
</pre>
<p>
<br />
<br />
这个HibernateValidationUI类只有一个构建器，它接收两个参数，一个是source object，也就是我们要修改的那个Bean类的实例，另外一个是这个bean的一个属性，这个HibernateValidationUI就负责验证这个属性。<br />
<br />
在installUI()方法中，我们启动对属性变化的观察类，而在uninstallUI()方法里面，我们需要卸载这个观察类。<br />
<br />
当给定对象的属性值发生变化时，PropertyChangeHandler的propertyStateChanged（）方法就会被调用，这个功能是通过elProperty和PropertzChangeHandler相结合来实现的。在propertyStateChangeed()方法里UI类的方法setDirty()会被调用，该方法的调用会导致UI类的状态变化，进而引发(re)painting，之后经过一系列的方法调用传递，paintLayer(Graphics2D g2, JXLayer&lt;jTextComponent&gt; l)这个方法将会被调用，这个方法要做的就是我们这个数据验证模块的核心功能：<br />
<br />
1. 调用Hibernate Validator验证该属性。<br />
2. 如果数据不正确，则在GUI上显示一个error icon，并且将错误信息作为tooltip展示给用户。<br />
<br />
在第二点里面产生了一个问题，谢谢Alexp对我的指点。Swing team里面有一些规定，其中之一就是，在paint()方法里面最好不要改变Component的状态，而setTooltip()方法将会改变component的状态，因此需要在paint()方法之外调用。我目前使用下来，还没有发现什么严重的错误，决定暂时不改了，回头有时间在将这个代码翻新一下。<br />
<br />
类中用到的Java2DIconFactory代码如下：<br /></p>
<pre name="code" class="java">package de.jingge.view;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;

public class Java2DIconFactory {

public static BufferedImage createErrorIcon() {
    return createErrorIcon(7, 8);
}



public static BufferedImage createErrorIcon(int width, int height) {
    BufferedImage icon = new BufferedImage(width, height,
            BufferedImage.TYPE_INT_ARGB);
    Graphics2D g2 = (Graphics2D) icon.getGraphics();
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);
    g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,
            RenderingHints.VALUE_STROKE_PURE);
    g2.setColor(Color.RED);
    g2.fillRect(0, 0, width, height);
    g2.setColor(Color.WHITE);
    g2.drawLine(0, 0, width, height);
    g2.drawLine(0, height, width, 0);
    g2.dispose();
    return icon;
}
}
</pre>
<p>
<br />
<br />
没什么太多好解释的，就是使用Java 2D画一个Error icon。<br />
<br />
接着，我们需要编写一个Factory类，构建一个JTextField，尽量把复杂技术封装起来，这样程序员开发起来可以提高效率，代码如下：<br /></p>
<pre name="code" class="java">package de.jingge.view;

import javax.swing.JTextField;
import javax.swing.text.JTextComponent;
import org.jdesktop.beansbinding.AutoBinding;
import org.jdesktop.beansbinding.BeanProperty;
import org.jdesktop.beansbinding.BindingGroup;
import org.jdesktop.beansbinding.Bindings;
import org.jdesktop.beansbinding.ELProperty;
import org.jdesktop.jxlayer.JXLayer;
import static org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.*;

public class GuiComponentFactory {

public static JXLayer&lt;jTextComponent&gt; createTextField(
        BindingGroup bindingGroup, Object sourceObject,
        String sourceProperty) {
    JTextField field = new JTextField();
    AutoBinding binding = Bindings.createAutoBinding(READ_WRITE,
            sourceObject, ELProperty.create(&quot;${&quot; + sourceProperty + &quot;}&quot;),
            field, BeanProperty.create(&quot;text&quot;));
    bindingGroup.addBinding(binding);
    bindingGroup.bind();
    return new JXLayer&lt;jTextComponent&gt;(field, new HibernateValidationUI(
            sourceObject, sourceProperty));
}
}
</pre>
<p>
<br />
<br />
createTextField()方法主要将给定对象属性的值与JTextField的text绑定，然后将JTextField纳入到JXLayer的管理之下。这样一来，一旦用户在JTextField里面修改数据，这个改变就会同步到该对象属性上，然后就引发了前面描述的一系列逻辑，最终改变的数据就会被Hiberante Validator加以验证。<br />
<br />
最后，我们可以编写一个Demo application来看看效果如何，代码如下：<br /></p>
<pre name="code" class="java">package de.jingge.main;

import de.jingge.domain.Country;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Toolkit;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.text.JTextComponent;
import net.miginfocom.swing.MigLayout;
import org.jdesktop.beansbinding.BindingGroup;
import org.jdesktop.jxlayer.JXLayer;
import static de.jingge.view.GuiComponentFactory.*;

public class ValidationApplicaton {

private BindingGroup bg;
private Country country;
private JXLayer&lt;jTextComponent&gt; codeField;
private JXLayer&lt;jTextComponent&gt; nameField;

/**
 * @param args the command line arguments
 */
public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel(
                &quot;com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel&quot;);
    } catch (UnsupportedLookAndFeelException ex) {
        System.err.println(
                &quot;Nimbus L&amp;F does not support. Default L&amp;F will be used.&quot;);
    } catch (ClassNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (InstantiationException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    ValidationApplicaton app = new ValidationApplicaton();
    JFrame frame = new JFrame(&quot;Demo Validation Application&quot;);
    frame.setPreferredSize(new Dimension(360, 150));
    frame.getContentPane().add(app.buildPanel(), BorderLayout.CENTER);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setCenter(frame);
    frame.setVisible(true);
    frame.pack();

}

private static void setCenter(JFrame frame) {
    Toolkit toolkit = Toolkit.getDefaultToolkit();
    Dimension screenSize = toolkit.getScreenSize();

    // Calculate the frame location
    int x = (screenSize.width - (int) frame.getPreferredSize().getWidth()) / 2;
    int y = (screenSize.height - (int) frame.getPreferredSize().getHeight()) / 2;

    // Set the new frame location
    frame.setLocation(x, y);
}

public ValidationApplicaton() {
    country = new Country();
    bg = new BindingGroup();
}

private JPanel buildPanel() {

    codeField = createTextField(bg, country, Country.PROPERTYNAME_CODE);
    nameField = createTextField(bg, country, Country.PROPERTYNAME_NAME);
    JPanel panel = new JPanel(new MigLayout(&quot;&quot;,
            &quot;[50px, right]10[200px:250px:300px]&quot;, &quot;[center]&quot;));
    panel.add(new JLabel(&quot;Code:&quot;), &quot;cell 0 0&quot;);
    panel.add(codeField, &quot;cell 1 0, w 200px:250px:300px&quot;);
    panel.add(new JLabel(&quot;Name:&quot;), &quot;cell 0 1&quot;);
    panel.add(nameField, &quot;cell 1 1, w 200px:250px:300px&quot;);
    return panel;
}
}

</pre>
<p>
<br />
<br />
这个类比较简单了，我简单解释一下：<br />
<br />
在main()方法里面，我们创建了一个JFrame，然后放入一个JPanel<br />
<br />
setCenter()方法负责将窗口至于屏幕的正中间。<br />
<br />
在构建器里面，我们创建了Country和BindingGroup的对象实例。<br />
<br />
在buildPanel()方法里面，我们使用MigLayout构建了一个Panel，其中codeField和nameField对应各自的对象属性。更多关于MigLayout的信息看这里：<a href="http://www.miglayout.com/" target="_blank">http://www.miglayout.com/</a>
。这也是一个例子，大家可以看到使用MigLayout开发Swing真的是非常方便。<br />
<br />
从这个Demo里面也可以看出，编写好pojo后，程序员只需要调用createTextField(bg, country, Country.PROPERTYNAME_CODE); 就可以创建一个支持数据验证的JTextField，编码量已经可以说是最大限度的降低了。<br />
<br />
运行程序，你会看到：<br />
<br />
<img src="http://bp3.blogger.com/_kE1wl-BJf90/SIBsALelM7I/AAAAAAAAAAU/LTR5E4GXK5k/s320/image003.png" alt="" />
<br />
<br />
这个code和name的数据都不合法，用户看到了error icon。<br />
<br />
将鼠标移到Text field上，你会看到：<br />
<br />
<img src="http://bp1.blogger.com/_kE1wl-BJf90/SIBsNdzmsxI/AAAAAAAAAAc/Wr1c-XSws8E/s320/image006.jpg" alt="" />
<br />
<br />
填好合法数据后，Error icon就不见了：<br />
<br />
<img src="http://bp3.blogger.com/_kE1wl-BJf90/SIBsYfl8BwI/AAAAAAAAAAk/9GjuWe16qvc/s320/image007.png" alt="" />
<br />
<br />
总结：<br />
<br />
使用这个通用数据验证模块有很多好处：<br />
<br />
1. 如果项目使用ORM，例如Hibernate，这个方案应该是解决数据验证的最好方案之一。<br />
2. 对于普通的数据验证，例如非空，email，长度等等，程序员根本不需要编码，只要在POJO上使用相应的Hibernate Validator annotation就可以了。<br />
3. 对于复杂的数据验证，Hibernate Validator提供了很好的扩展机制，只要写一个annotation外加一个Validator就可以了。Swing应用这边仍然不需要编写任何代码。<br />
<br />
综上所述，可以看出通过使用这个通用数据验证模块，开发效率会提高很多。<br />
<br />
对这个项目感兴趣的朋友可以给我留言，人数够多的话，我会考虑将整个netbeans项目上传到javaeye上来。</p>
<p>&nbsp;</p>
          <br/><br/>
          <span style="color:red;">
            <a href="http://polygoncell.javaeye.com/blog/216556#comments" style="color:red;">已有 <strong>29</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">Windows7在微软WinHEC 2008上揭开神秘面纱</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sat, 19 Jul 2008 18:24:10 +0800</pubDate>
        <link>http://polygoncell.javaeye.com/blog/216556</link>
        <guid>http://polygoncell.javaeye.com/blog/216556</guid>
      </item>
          <item>
        <title>构建开发Swing应用的通用validation模块</title>
        <author>polygoncell</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://polygoncell.javaeye.com">polygoncell</a>&nbsp;
                    链接：<a href="http://polygoncell.javaeye.com/blog/216358" style="color:red;">http://polygoncell.javaeye.com/blog/216358</a>&nbsp;
          发表时间: 2008年07月18日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          最近一直在开发桌面应用框架，目前开发了一个通用的Validation模块，感觉比较实用，就写了一篇博客拿出来和大家分享， 这篇博客是用英文写的， 原文在这里： <a href="http://polygoncell.blogspot.com/2008/07/validation-module-for-swing-application.html" target="_blank">http://polygoncell.blogspot.com/2008/07/validation-module-for-swing-application.html</a><br /><br /><br />计划抽时间换成中文在这里再写一便，英文好的朋友可以先去那里看看。
          <br/><br/>
          <span style="color:red;">
            <a href="http://polygoncell.javaeye.com/blog/216358#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">Windows7在微软WinHEC 2008上揭开神秘面纱</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 18 Jul 2008 21:53:15 +0800</pubDate>
        <link>http://polygoncell.javaeye.com/blog/216358</link>
        <guid>http://polygoncell.javaeye.com/blog/216358</guid>
      </item>
          <item>
        <title>书评： Refactoring to Pattern</title>
        <author>polygoncell</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://polygoncell.javaeye.com">polygoncell</a>&nbsp;
                    链接：<a href="http://polygoncell.javaeye.com/blog/214415" style="color:red;">http://polygoncell.javaeye.com/blog/214415</a>&nbsp;
          发表时间: 2008年07月13日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <span style="color: red"><strong>请注意：本文的版权归作者所有，如转载请注明出处。</strong></span><br /><br />陆陆续续又看了一些技术书，加上最近工作任务繁重，实在没时间写技术类的博文，计划断断续续写一些书的阅读评论。今天先写一本，<br /><br />最近阅读的书并不都是最新的，因为些书的确是需要花时间反复研读，仔细思考的，例如关于设计模式的书。<br /><br />Refactoring to Patterns就是这样一本书，一本相对来说不算太新的书，一本关于设计模式的书，一本让人从新开始思考模式的书。我本人强烈推举大家阅读。<br /><br />这本书刚出来的时候，我就一直想好好静下心来读一读，无奈工作忙碌，一直没有找到机会。而且说实话，自己对设计模式也已经浸淫数载，大部分模式都已经在实<br />际项目中历练过，不说炉火纯青，也算得上是熟能生巧。虽然知道这是一本好书，但是心里依然会泛起阵阵涟漪：just another design<br />pattern<br />book，给我一天时间，我就能把它拿下。没想到从开始读到现在已经2个多月了，现在依然会抽时间出来翻看某个章节，然后结合实际问题仔细思考一番。说实<br />话，设计模式真的是个好东西，是前辈经验的积累，但是当我们熟练掌握了各种模式之后，就会遇到两个瓶颈性质的问题：<br /><br />1. 如何将各类模式融汇贯通。感觉就像是武侠里面的如何将任督二脉打通，功夫再好，任督二脉不通也非高手，不同的模式相互作用会产生不同的结果，不同的模式组合会产生不同的结构，或相互补充相互促进，或互相影响互相抵制。如何选择，是个难题。<br /><br />2. 如何避免过度设计。模式用熟的朋友可能会有这种感觉，编程的时候会不知不觉中使用模式进行开发，模式再好，泛滥使用，过犹不及。好像武功一般，招式繁多，固然耍起来好看，但是高手最后的境界往往是无招胜有招，只要能目的达到就行了。<br /><br />第一个问题由于模式之间的组合千变万化，而且很多需要结合实际问题进行考虑，大家只能是在实际项目开发中慢慢体会，慢慢积累经验。或许再过几年会有某个人或者某些人把这些经验收集整理，编排出书。<br /><br />今天主要想说说第二个问题：过度设计。 Refactoring to Patterns这本书就是帮助我们尽量避免过度设计的，这也是我推荐大家看这本书的初衷。<br /><br />事实上，这本书完全可以看成是极限编程系列里面的一部巨头著作，其他的重要著作包括TDD，Refactoring，和continuous integration，合起来应该称为XP四大金刚。<br /><br />使用XP开发强调keep it<br />simple，在编码的时候首先用最简单的办法实现功能(当然最好是测试驱动,我会在评论下面一本书是继续谈测试驱动），然后在测试代码的保护下对初级代<br />码进行大刀阔斧地重构，这时候这些代码自然最好能够重构成设计模式，因为针对某些特定的问题，模式基本上是最佳解决方案。这个时候就大家就需要了解如何将<br />现有的代码重构成为标准的设计模式代码，说的严重点，这一步关系到整个代码的质量，直至引申到真个项目的质量。这本书就针对这个关键步骤进行了讲解，是所<br />有采用XP方法的开发团队的必修课之一。<br /><br />至于书的内容我就尽量简单概括一下：本书基本上覆盖了重构项目中会遇到的大部分问题，并且针对这些问题提供了实例讲解和具体的解决方案。这些方案不单单适<br />用于使用TDD开发的项目，它们更适用于那些希望通过重构改善现有代码质量的项目。当然，重构前，千万别尝试避开编写测试代码，要牢记，没有测试代码保<br />护，最好不要对代码做大手术。书中的很多例子都值得大家读完以后结合自己的实际项目仔细思考一番。我个人很喜欢第7章，已经在项目中采用了书中提到的很多<br />解决方案，并且对于某些实际例子，开始尝试优化书中的方案，希望以后能够抽出时间来写一篇详细的博文。
          <br/><br/>
          <span style="color:red;">
            <a href="http://polygoncell.javaeye.com/blog/214415#comments" style="color:red;">已有 <strong>1</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">Windows7在微软WinHEC 2008上揭开神秘面纱</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sun, 13 Jul 2008 22:58:28 +0800</pubDate>
        <link>http://polygoncell.javaeye.com/blog/214415</link>
        <guid>http://polygoncell.javaeye.com/blog/214415</guid>
      </item>
          <item>
        <title>关于Factory, Abstract Factory, Factory Method, 和Buil</title>
        <author>polygoncell</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://polygoncell.javaeye.com">polygoncell</a>&nbsp;
                    链接：<a href="http://polygoncell.javaeye.com/blog/214190" style="color:red;">http://polygoncell.javaeye.com/blog/214190</a>&nbsp;
          发表时间: 2008年07月12日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p><span id="ctl00_MainContentPlaceholder_ctl01_ctl00_lblEntry">
<p><span style="font-family: 宋体;">选这</span>
<span lang="EN-US">4</span>
<span style="font-family: 宋体;">个模式在一起讨论首先是因为她们的功能比较类似，都是用来制造对象实例的，从归类来说，他们都属于制造类模式</span>
<span lang="EN-US">(creational patterns)</span>
<span style="font-family: 宋体;">，其次她们们在工作中比较常用，由于功能太过相似，往往导致在某个实际问题上让人举棋不定，似乎选哪个都可以解决问题，可是真的选择某个模式后，又会发现不是完全合适。今天我们就来讨论讨论在什么情况下选择什么模式来解决问题比较合适。</span>
 </p>
<p><span style="font-family: 宋体;">考虑到不是所有的朋友都对以上提到的</span>
<span lang="EN-US">4</span>
<span style="font-family: 宋体;">种模式都了如指掌，在开始讨论之前先简单的介绍一下这</span>
<span lang="EN-US">4</span>
<span style="font-family: 宋体;">个模式，对这</span>
<span lang="EN-US">4</span>
<span style="font-family: 宋体;">种模式熟悉的朋友也可以顺便回顾一下。请注意，这里我只会做简短的介绍，如果要比较深入地了解她们的话，还请去看模式相关的书籍，比较浅显易懂的我推荐</span>
<span> <span lang="EN-US">&ldquo;Head First Design Patterns&rdquo;</span>
</span>
<span style="font-family: 宋体;">。如果要在工作中反复参考的我推荐</span>
<span> </span>
<span style="font-family: 宋体;">&ldquo;</span>
<span lang="EN-US">Applied Java Patterns</span>
<span style="font-family: 宋体;">&rdquo;。那本经典的</span>
<span lang="EN-US">GOF Design Patterns</span>
<span style="font-family: 宋体;">由于写的时间比较早，举的例子不太适合现在的软件开发，我个人认为初学者或者是没有太多时间的朋友没有必要去读那本书，尽管她的确是经典。<br />
 </span>
 </p>
<p>&nbsp;</p>
<h3><span lang="EN-US">Factory Pattern</span>
</h3>
<p><span style="font-family: 宋体;">中文叫工厂模式</span>
<span lang="EN-US">, </span>
<span style="font-family: 宋体;">这个是我们在面向对象编程中最常用的模式之一了，她的主要功能就是制造对象，也正是这个原因才叫她为工厂模式，工厂干什么？生产产品。通常情况而言某个工厂所生产的产品总是一个系列的不同种类，大体上相同，细节上有差异。</span>
 </p>
<p><span style="font-family: 宋体;">图</span>
<span lang="EN-US">1 </span>
<span style="font-family: 宋体;">展示了一个非常简单的例子，通常</span>
<span lang="EN-US">CarFactory</span>
<span style="font-family: 宋体;">类会提供下列方法来生产车辆</span>
<span lang="EN-US">, </span>
<span style="font-family: 宋体;">如代码片断</span>
<span lang="EN-US">1</span>
<span style="font-family: 宋体;">所示：</span>
 </p>
<p style="font-family: geneva,arial,sans-serif;"><span lang="EN-US">public class CarFactory {</span>
 </p>
<p style="font-family: geneva,arial,sans-serif;"><span lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
public Car createBusinessCar() {&hellip;.}</span>
 </p>
<p style="font-family: geneva,arial,sans-serif;"><span lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
public Car createSportCar() {&hellip;}</span>
 </p>
<p><span lang="EN-US"><span style="font-family: geneva,arial,sans-serif;">}<br />
 </span>
</span>
 </p>
<p>&nbsp;</p>
<p align="center" style="text-align: center;"><span style="font-family: 宋体;">代码片断</span>
<span lang="DE"> 1</span>
 </p>
<div style="text-align: center;"><img src="http://storage.msn.com/x1pBG_wmiiVq4fKhMkEoTbjopPcKCE3u0uJjfqcYoYvgBeu5PDT5UndtcNdt48rY80PV_fd8Ce5pLpHavAj520cgRoVa4EmOhjE5VNS7GnBHl126UUuSSCrcM8YMFLVb3mp_UsivKRLJ1HKESriM5FDQA" border="0" align="middle" alt="" />
<br />
 </div>
<p align="center" style="text-align: center;"><span style="font-family: 宋体;">图</span>
<span lang="DE">1 Factory Pattern<br />
 </span>
 </p>
<p style="text-align: left;">&nbsp;</p>
<h3><span lang="DE">Abstract Factory Pattern</span>
</h3>
<p><span style="font-family: 宋体;">中文叫抽象工厂模式，顾名思义，就是把工厂模式在进一步抽象化，进一步细化。我们继续沿用上面的例子，不过这次增加产品的种类，如图</span>
<span lang="EN-US">2</span>
<span style="font-family: 宋体;">所示。由于我们增加了一层分类，当我们要生产某种车的时候就需要询问要哪种车</span>
<span lang="EN-US">, </span>
<span style="font-family: 宋体;">商用还是跑车？不然的话就要增加</span>
<span lang="EN-US">create</span>
<span style="font-family: 宋体;">方法，如果分类多了，</span>
<span lang="EN-US">create</span>
<span style="font-family: 宋体;">方法就会成几何数量增长。</span>
 </p>
<p style="text-align: left;">&nbsp;</p>
<p style="font-family: geneva,arial,sans-serif;"><span lang="EN-US">public class CarFactory {</span>
 </p>
<p style="font-family: geneva,arial,sans-serif;"><span lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
public Car createBusinessBMWCar() {&hellip;.}</span>
 </p>
<p style="font-family: geneva,arial,sans-serif;"><span lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
public Car createBusinessBenzCar() {&hellip;}</span>
 </p>
<p style="font-family: geneva,arial,sans-serif;"><span lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
public Car createSportBMWCar() {&hellip;.}</span>
 </p>
<p style="font-family: geneva,arial,sans-serif;"><span lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
public Car createSportBenzCar() {&hellip;}</span>
 </p>
<p><span lang="EN-US"><span style="font-family: geneva,arial,sans-serif;">}</span>
</span>
 </p>
<p align="center" style="text-align: center;"><span style="font-family: 宋体;">代码片断</span>
<span lang="DE"> 2</span>
 </p>
<p style="text-align: left;"><br /></p>
<div style="text-align: center;"><img src="http://storage.msn.com/x1pBG_wmiiVq4fKhMkEoTbjopPcKCE3u0uJjfqcYoYvgBee-TnpMzZc_ZqwZC1doT-cIW-U3P8N2-bwjC3VP-_6SlTcY5iXrrcpDcnU4l-WG2ExsjQnc-bZyr1hx0TfiXjK3YQEsA8ZnsrSglQaBWXZQQ" border="0" align="middle" alt="" style="width: 391px; height: 356px;" />
<br />
 </div>
<p align="center" style="text-align: center;"><span style="font-family: 宋体;">图</span>
<span lang="DE">2 bad Factory Pattern</span>
 </p>
<p><span style="font-family: 宋体;">从面向对象的角度来讲，不是很好的解决方法，需要进一步抽象。结果就是把</span>
<span lang="EN-US">CarFactory</span>
<span style="font-family: 宋体;">进行抽象，然后针对不同品牌的车产生不同的工厂。</span>
<span> </span>
<span style="font-family: 宋体;">如图</span>
<span lang="EN-US">3<br />
 </span>
 </p>
<p>&nbsp;</p>
<div style="text-align: center;"><img src="http://storage.msn.com/x1pBG_wmiiVq4fKhMkEoTbjopPcKCE3u0uJjfqcYoYvgBfvnLjsxFYObHTGR9CPTp9UBQ_GxnpRhEDmyikpUU9sqYJUmC-gy1fSl2JMcMWgb-txY8kEBN_QXG-d3HAtxoSpLo_Oz30QnQcLwQI2M5JChg" border="0" align="middle" alt="" style="width: 418px; height: 473px;" />
</div>
<p align="center" style="text-align: center;"><span style="font-family: 宋体;">图</span>
<span lang="DE">3 Abstract Factory Pattern</span>
 </p>
<p><span style="font-family: 宋体;">这个时候每个工厂类仍然只需要</span>
<span lang="DE">2</span>
<span style="font-family: 宋体;">个方法，如代码片断</span>
<span lang="DE">1</span>
<span style="font-family: 宋体;">所示，用户会在不同需要的情况下得到不同的工厂对象，进而生产出需要的</span>
<span lang="DE">Car</span>
<span style="font-family: 宋体;">。不论这里工厂类如何实现，客户端的代码可以始终不变，类似这样：</span>
<span lang="DE">getCarFactory().createBusinessCar()</span>
<span style="font-family: 宋体;">。</span>
 </p>
<p><span style="font-family: 宋体;">以上两个模式多用于：</span>
<span lang="DE">&nbsp;</span>
   </p>
<p><span lang="DE"><span>1<span style="font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-family: 'Times New Roman';"> 。 </span>
</span>
</span>
<span style="font-family: 宋体;">客户端需要依赖制造对象的细节。</span>
<br />
<span lang="DE"><span><span style="font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-family: 'Times New Roman';">&nbsp;</span>
</span>
</span>
<span style="font-family: 宋体;">2. 一系列类似的对象需要被制造出来。</span>
<span lang="DE"><span><br />
3.<span style="font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
</span>
</span>
<span style="font-family: 宋体;">同种对象不同实体需要在不同的地点不同是时间被制造出来。</span>
<span lang="DE">&nbsp;</span>
  </p>
<h3><span lang="DE">Factory Method Pattern</span>
</h3>
<p><span style="font-family: 宋体;">中文叫工厂方法模式，</span>
<span> </span>
<span style="font-family: 宋体;">通
常是用于当某个类的功能主要是针对生产出来的对象提供一些相关服务，而且这些对象有共同的接口，至于对象具体是什么，留给她的子类来决定。这样解释起来比
较晦涩难懂，我们还是沿用生产汽车的例子，不过不再用工厂，而是改用销售部门，因为销售部门主要为生产出来的车提供相关服务的，比方说，折扣，售后服务等
等。代码如代码片断</span>
<span lang="DE">3 </span>
<span style="font-family: 宋体;">所示</span>
<span lang="DE">, </span>
<span style="font-family: 宋体;">这里</span>
<span lang="EN-US">CarStore</span>
<span style="font-family: 宋体;">是个抽象类，如何生产需要的车将由子类来进一步实现，</span>
<span> </span>
<span style="font-family: 宋体;">比方说</span>
<span lang="EN-US">BMWStore</span>
<span style="font-family: 宋体;">就会生产出</span>
<span lang="EN-US">BMW</span>
<span style="font-family: 宋体;">。图</span>
<span lang="EN-US">4</span>
<span style="font-family: 宋体;">展示了相关的</span>
<span lang="EN-US">UML</span>
<span style="font-family: 宋体;">图</span>
<span lang="EN-US">, </span>
<span style="font-family: 宋体;">总体看起来图</span>
<span lang="EN-US">4</span>
<span style="font-family: 宋体;">和图</span>
<span lang="EN-US">3</span>
<span style="font-family: 宋体;">非常相似，</span>
<span> </span>
<span style="font-family: 宋体;">但是从实现原理和实际应用上来说两者是完全不同的，</span>
<span> </span>
<span style="font-family: 宋体;">图</span>
<span lang="EN-US">3 Abstract Factory</span>
<span style="font-family: 宋体;">是针对</span>
<span lang="EN-US">Interface</span>
<span style="font-family: 宋体;">的多种不同的实现，具体使用的</span>
 </p>
<p><span style="font-family: 宋体;">时候是&ldquo;组和&rdquo;，用英语术语表达就是&ldquo;</span>
<span lang="EN-US">composition</span>
<span style="font-family: 宋体;">&rdquo;。</span>
<span> </span>
<span style="font-family: 宋体;">而图</span>
<span lang="EN-US">4 Factory Method</span>
<span style="font-family: 宋体;">是子类对抽象父类继承，进而实现父类的抽象方法，</span>
<span> </span>
<span style="font-family: 宋体;">具体使用的时候是</span>
<span lang="EN-US">&rdquo;</span>
<span style="font-family: 宋体;">继承</span>
<span lang="EN-US">&rdquo;</span>
<span style="font-family: 宋体;">，</span>
<span> </span>
<span style="font-family: 宋体;">用英语术语表达就是</span>
<span lang="EN-US">&rdquo;inheritance&rdquo;</span>
<span style="font-family: 宋体;">。</span>
<span> </span>
<span style="font-family: 宋体;">也就是很多</span>
<span lang="EN-US">OO</span>
<span style="font-family: 宋体;">书里说谈到的&ldquo;</span>
<span lang="EN-US">is a? or has a?</span>
<span style="font-family: 宋体;">&rdquo;的问题，</span>
<span lang="EN-US"> composition</span>
<span style="font-family: 宋体;">指的就是</span>
<span lang="EN-US">has a, </span>
<span style="font-family: 宋体;">而</span>
<span lang="EN-US">inheritance</span>
<span style="font-family: 宋体;">指的就是</span>
<span lang="EN-US">is a</span>
<span style="font-family: 宋体;">。<br />
 </span>
 </p>
<p>&nbsp;</p>
<p style="font-family: geneva,arial,sans-serif;"><span lang="EN-US">public abstract class CarStore {</span>
 </p>
<p style="font-family: geneva,arial,sans-serif;"><span lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
// Factory method</span>
 </p>
<p style="font-family: geneva,arial,sans-serif;"><span lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
protected abstract Car createBusinessCar();</span>
 </p>
<p style="font-family: geneva,arial,sans-serif;"><span lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
protected abstract Car createSportCar();</span>
 </p>
<p style="font-family: geneva,arial,sans-serif;"><span lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
</span>
 </p>
<p style="font-family: geneva,arial,sans-serif;"><span lang="EN-US">public void sell() {</span>
 </p>
<p style="font-family: geneva,arial,sans-serif;"><span lang="EN-US"><span>&nbsp; </span>
createBusinessCar();</span>
 </p>
<p style="font-family: geneva,arial,sans-serif;"><span lang="EN-US"><span>&nbsp; </span>
discount(&hellip;);</span>
 </p>
<p style="font-family: geneva,arial,sans-serif;"><span lang="EN-US">....</span>
 </p>
<p style="font-family: geneva,arial,sans-serif;"><span lang="EN-US">}</span>
 </p>
<p style="font-family: geneva,arial,sans-serif;"><span lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
public double discount(Customer customer) {&hellip;.}</span>
 </p>
<p style="font-family: geneva,arial,sans-serif;"><span lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
public void service() {&hellip;}</span>
 </p>
<p style="font-family: geneva,arial,sans-serif;"><span lang="EN-US">}</span>
 </p>
<p>&nbsp;</p>
<p align="center" style="text-align: center;"><span style="font-family: 宋体;">代码片断</span>
<span lang="EN-US"> 3</span>
 </p>
<p><span style="font-family: 宋体;">这个模式多半会和另一个模式</span>
<span lang="EN-US">Template Method</span>
<span style="font-family: 宋体;">一起使用，事实上代码片断</span>
<span lang="EN-US">3</span>
<span style="font-family: 宋体;">中方法</span>
<span lang="EN-US">sell() </span>
<span style="font-family: 宋体;">就是</span>
<span lang="EN-US">template Method</span>
<span style="font-family: 宋体;">。具体关于</span>
<span lang="EN-US">template method pattern</span>
<span style="font-family: 宋体;">的详细讲解已不属于本文的讨论主题</span>
<span> </span>
<span style="font-family: 宋体;">，感兴趣的朋友请看相关书籍。<br />
 </span>
 </p>
<p>&nbsp;</p>
<div style="text-align: center;"><img src="http://storage.msn.com/x1pBG_wmiiVq4fKhMkEoTbjopPcKCE3u0uJjfqcYoYvgBcigtvc1JV34v6wh_gCCn9NXHLLHeWJlj76OiZDZRbf8X_zj_z_ah5oDKF02kC2D7bLcsLOYqw79e8FzS15halIoxPca7kCgYhxoeAXYgeCJQ" border="0" align="middle" alt="" style="width: 417px; height: 473px;" />
 </div>
<p align="center" style="text-align: center;"><span style="font-family: 宋体;">图</span>
<span lang="EN-US">4 Factory Method</span>
 </p>
<h3><span lang="EN-US">Builder Pattern</span>
</h3>
<p align="center" style="text-align: center;"><span style="font-family: 宋体;">中文叫生成器模式，我觉得叫构造模式更贴切，通常用于提供尽可能简单的接口来生成比较复杂的对象，这个复杂的对象通常包含有很多其他的对象。有些人认为</span>
<span lang="EN-US">Builder</span>
<span style="font-family: 宋体;">和</span>
<span lang="EN-US">Factory Method</span>
<span style="font-family: 宋体;">很相似，有时候是可以互换的，这样理解是错误的。这两个模式的侧重点是不同的，</span>
<span lang="EN-US">Builder</span>
<span style="font-family: 宋体;">侧重的是构造复杂对象，而且经常是使用到</span>
<span lang="EN-US">composite</span>
<span style="font-family: 宋体;">模式</span>
<span lang="EN-US">; Factory Method</span>
<span style="font-family: 宋体;">侧重的是生产各种各样不同的对象，这些对象通常都是比较简单的，一般而言，</span>
<span lang="EN-US">Factory Method</span>
<span style="font-family: 宋体;">不会和</span>
<span lang="EN-US">composite</span>
<span style="font-family: 宋体;">联合使用。总的来说这两个模式是相辅相成的，决不能视为同类。具体原因我会在讨论中加以阐述。图</span>
<span lang="EN-US">5 </span>
<span style="font-family: 宋体;">展示了</span>
<span lang="EN-US">Builder</span>
<span style="font-family: 宋体;">概念图。</span>
<span lang="EN-US"><br />
 <br />
 &nbsp;</span>
 </p>
<div style="text-align: center;"><img src="http://storage.msn.com/x1pBG_wmiiVq4fKhMkEoTbjopPcKCE3u0uJjfqcYoYvgBcWaDI_WugqSxGiMT8HyNq__h6MGuk8G87qbOMESYySsMzqcW0zl9jbcYK7c0PW5s02Yh6HLodZujaDwlHF4Y63a8zJLfnkuNUMAJhEQeQ5ag" border="0" align="middle" alt="" />
</div>
<p align="center" style="text-align: center;"><span style="font-family: 宋体;">图</span>
<span lang="EN-US">5 Builder Pattern</span>
 </p>
<p><span lang="EN-US">&nbsp;</span>
 </p>
<p><span style="font-family: 宋体;">考虑到使用</span>
<span lang="EN-US">composite</span>
<span style="font-family: 宋体;">模
式，我们使用另外一个例子，做饭，比较简单，常见，人人都做过，解释起来应该比较好懂。我们先定义好&ldquo;食品&rdquo;是对所有吃的物品的概括，做好的炸酱面是食
品，煮好的面条是食品，做好的酱是食品，做酱用的料也是食品。当我们去餐馆叫吃炸酱面时，我们只希望要一碗做好的炸酱面，</span>
<span> </span>
<span style="font-family: 宋体;">我们可不会希望对小二说煮面，切黄瓜丝，打鸡蛋，剁肉末，熬酱，等等。我们只希望说：&ldquo;小二，来碗炸酱面。&rdquo;</span>
<span> </span>
<span style="font-family: 宋体;">这时候就需要用到</span>
<span lang="EN-US">builder,<span>&nbsp; </span>
builder</span>
<span style="font-family: 宋体;">会提供一个简单的方法</span>
<span lang="EN-US">createNoodleWithSource() &mdash; </span>
<span style="font-family: 宋体;">做炸酱面，当顾客点吃炸酱面后，</span>
<span lang="EN-US">builder</span>
<span style="font-family: 宋体;">就会在内部制造一系列的食品，比方说，煮面，切黄瓜丝，打鸡蛋，剁肉末，熬酱，等等。而这些细节，作为顾客是不需要费心的。</span>
 </p>
<p>&nbsp;</p>
<h3><span style="font-family: 宋体;">讨论</span>
</h3>
<p><span lang="EN-US">4</span>
<span style="font-family: 宋体;">种模式都已经简要的介绍完了，到这里大家应该对她们有了大概地了解。从根本上来说，每一个模式都不难理解，真正困难的是选择，在什么情况下用哪个模式才是正确的？</span>
<span> </span>
<span style="font-family: 宋体;">每一个初学者碰到了实际的问题都会产生疑问，好像用那个模式都可以解决问题。我对以上</span>
<span lang="EN-US">4</span>
<span style="font-family: 宋体;">种模式进行了一番对比，并结合工作中的实际问题进行了思考，并且和同事们展开了讨论（这真是人生一大快事啊！）。我的建议是&ldquo;毛主席教导我们要用发展的眼光来看待这个问题&ldquo;</span>
<span> </span>
<span style="font-family: 宋体;"><img src="http://polygoncell.spaces.live.com/rte/emoticons/smile_wink.gif" alt="" />
。<br />
</span>
</p>
<p>&nbsp;</p>
<p><span style="font-family: 宋体;">一般来说，在软件开发过程中，总是把大的问题进行细化，然后从小处入手，逐渐发展壮大。也就是说最开始的时候遇到的问题往往很小，一个类就可以解决了，对于只需要生成简单对象的情况，使用</span>
<span lang="EN-US">Factory</span>
<span style="font-family: 宋体;">模式；对于需要生成复杂对象的情况，用</span>
<span lang="EN-US">builder</span>
<span style="font-family: 宋体;">模式，只需要写一个类，借口拉，抽象类拉，完全不需要！目前不需要担心松紧耦合的问题。进一步优化的话，可以写两个类，</span>
<span lang="EN-US">builder</span>
<span style="font-family: 宋体;">负责生成复杂的对象，而将所有关于生成简单对象的工作转交给</span>
<span lang="EN-US">Factory</span>
<span style="font-family: 宋体;">，用英语术语来表达的话叫&ldquo;</span>
<span lang="EN-US">delegate</span>
<span style="font-family: 宋体;">&rdquo;</span>
<span lang="EN-US">, </span>
<span style="font-family: 宋体;">对应的模式叫</span>
<span lang="EN-US">Business Delegate</span>
<span style="font-family: 宋体;">（</span>
<span lang="EN-US">core J2EE Patterns</span>
<span style="font-family: 宋体;">）。</span>
 </p>
<p><span style="font-family: 宋体;">当系统发展壮大后</span>
<span lang="EN-US">, </span>
<span style="font-family: 宋体;">需要生成很多种类的复杂对象，导致了需要很多</span>
<span lang="EN-US">builder</span>
<span style="font-family: 宋体;">来负责生成她们，这个时候就需要做两件事，第一是使用</span>
<span lang="EN-US">Abstract Factory</span>
<span style="font-family: 宋体;">模式，负责生成相对应的</span>
<span lang="EN-US">builder</span>
<span style="font-family: 宋体;">类，进而对各种复杂的对象生成进行系统的管理。第二是为各种类别的</span>
<span lang="EN-US">builder</span>
<span style="font-family: 宋体;">和</span>
<span lang="EN-US">Factory</span>
<span style="font-family: 宋体;">编写接口，然后利用</span>
<span lang="EN-US">refactoring</span>
<span style="font-family: 宋体;">将使用类的地方尽可能的替换为使用借口，也就是面向对象编程基本原理之一的&ldquo;尽量针对接口编程，而不是针对实现类&rdquo;。如果希望优化系统，减少对象实体的生成，可以视情况而定，采用</span>
<span lang="EN-US">Singleton</span>
<span style="font-family: 宋体;">模式。</span>
 </p>
<p><span style="font-family: 宋体;">请注意到目前为止，我们没有用到继承，这也是符合面向对象编程的原理的</span>
<span lang="EN-US">&mdash;</span>
<span style="font-family: 宋体;">组合优先于继承（</span>
<span lang="EN-US">composition</span>
<span style="font-family: 宋体;">，</span>
<span lang="EN-US"> not inheritance</span>
<span style="font-family: 宋体;">）。但是当系统再进一步发展长大后，她已经不能再称为模块，而是成长为框架（</span>
<span lang="EN-US">framework</span>
<span style="font-family: 宋体;">）时，我们就要考虑适当的使用</span>
<span lang="EN-US">Factory Method</span>
<span style="font-family: 宋体;">模式了。基本的功能将在父类中加以实现，而具体的对象生成交由子类来完成。如果结合其他模式来理解的话，就是子类中生成对象的工作将转交给其他</span>
<span lang="EN-US">3</span>
<span style="font-family: 宋体;">中模式类们来完成。如果希望在运行状态（</span>
<span lang="EN-US">runtime</span>
<span style="font-family: 宋体;">）时动态切换相关的</span>
<span lang="EN-US">Builder</span>
<span style="font-family: 宋体;">或</span>
<span lang="EN-US">Factory</span>
<span style="font-family: 宋体;">的话，可以采用</span>
<span lang="EN-US">Strategy</span>
<span style="font-family: 宋体;">模式。不过，就像很多介绍面向对象编程的书籍建议的那样，不到万不得已不要使用继承，也就是说，切忌在系统还非常简单的情况下就贸然使用</span>
<span lang="EN-US">Factory Method</span>
<span style="font-family: 宋体;">。</span>
 </p>
<p>&nbsp;</p>
<div style="text-align: center;"><img src="http://storage.msn.com/x1pBG_wmiiVq4fKhMkEoTbjopPcKCE3u0uJjfqcYoYvgBcvTDF0Pg2ZR7U3ahhCcauR5u1FUf05edNjFJfXq8-HjrJ7oCeeQrI9BBvsA8Vg6id6vZCSSzXtf9IsQAWDFEUjk_N_hAMhZyfQ54VQ8-o5kw" border="0" align="middle" alt="" style="width: 439px; height: 328px;" />
</div>
<p align="center" style="text-align: center;"><span style="font-family: 宋体;">图</span>
<span lang="EN-US">6 Big picture</span>
 </p>
<p><span style="font-family: 宋体;">到此为止所有</span>
<span lang="EN-US">4</span>
<span style="font-family: 宋体;">种模式都用上了，整个系统有如下优点：</span>
 </p>
<ol>
<li><span style="font-family: 宋体;">健壮，易于扩展，易于维护。</span>
</li>
<li><span style="font-family: 宋体;">针对接口，系统内部松散，解耦合。</span>
</li>
<li><span style="font-family: 宋体;">基本上避免了代码重复。</span>
 </li>
</ol>
<p><span style="font-family: 宋体;">这样构件的系统里，我们用到了下列模式：</span>
 </p>
<p style="text-indent: -18pt;"><span lang="EN-US"><span>1.<span style="font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
</span>
</span>
<span lang="EN-US">Factory Pattern</span>
 </p>
<p style="text-indent: -18pt;"><span lang="EN-US"><span>2.<span style="font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
</span>
</span>
<span lang="EN-US">Abstract Factory Pattern</span>
 </p>
<p style="text-indent: -18pt;"><span lang="EN-US"><span>3.<span style="font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
</span>
</span>
<span lang="EN-US">Builder Pattern</span>
 </p>
<p style="text-indent: -18pt;"><span lang="EN-US"><span>4.<span style="font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
</span>
</span>
<span lang="EN-US">Singleton Pattern</span>
 </p>
<p style="text-indent: -18pt;"><span lang="EN-US"><span>5.<span style="font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
</span>
</span>
<span lang="EN-US">Template Method Pattern</span>
 </p>
<p style="text-indent: -18pt;"><span lang="EN-US"><span>6.<span style="font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
</span>
</span>
<span lang="EN-US">Composite Pattern</span>
 </p>
<p style="text-indent: -18pt;"><span lang="EN-US"><span>7.<span style="font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
</span>
</span>
<span lang="EN-US">Strategy Pattern</span>
 </p>
<p style="text-indent: -18pt;"><span lang="EN-US"><span>8.<span style="font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>
</span>
</span>
<span lang="EN-US">Business Delegate Pattern</span>
 </p>
</span>
</p>
          <br/><br/>
          <span style="color:red;">
            <a href="http://polygoncell.javaeye.com/blog/214190#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">Windows7在微软WinHEC 2008上揭开神秘面纱</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sat, 12 Jul 2008 15:23:55 +0800</pubDate>
        <link>http://polygoncell.javaeye.com/blog/214190</link>
        <guid>http://polygoncell.javaeye.com/blog/214190</guid>
      </item>
          <item>
        <title>决定搬家来Javaeye</title>
        <author>polygoncell</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://polygoncell.javaeye.com">polygoncell</a>&nbsp;
                    链接：<a href="http://polygoncell.javaeye.com/blog/214158" style="color:red;">http://polygoncell.javaeye.com/blog/214158</a>&nbsp;
          发表时间: 2008年07月12日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>javaeye开始支持google广告了，这使我下定决心搬家来这里，以后我会将技术类文章在这里发表，我的MSN Space老家那里将只会出现非技术类的文章。</p>
          <br/><br/>
          <span style="color:red;">
            <a href="http://polygoncell.javaeye.com/blog/214158#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">Windows7在微软WinHEC 2008上揭开神秘面纱</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sat, 12 Jul 2008 14:00:58 +0800</pubDate>
        <link>http://polygoncell.javaeye.com/blog/214158</link>
        <guid>http://polygoncell.javaeye.com/blog/214158</guid>
      </item>
          <item>
        <title>几个关于Guice的问题，关心Guice的请进</title>
        <author>polygoncell</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://polygoncell.javaeye.com">polygoncell</a>&nbsp;
                    链接：<a href="http://polygoncell.javaeye.com/blog/182977" style="color:red;">http://polygoncell.javaeye.com/blog/182977</a>&nbsp;
          发表时间: 2008年04月15日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          最近考虑在项目中使用guice，但是在替换一些Design patterns时遇到一些问题，特来这里向大家请教。<br /><br />Guice的文档实在是太简单了，基本上就是几个简单的对象来回映射，对实际开发基本上没什么用。网上的例子也基本上停留在1+1=2的水平。<br /><br />下面是我遇到的问题：<br /><br />1. 如何在运行时态注入同一个对象的不同的实例？<br />&nbsp;&nbsp; 首先一个POJO：<br /><pre name="code" class="java"> public class Foo {

    private boolean a;
    private boolean b;

    @inject
    public Foo(boolean a, boolean b) {
        this.a = a;
        this.b = b;
    }
} </pre><br /><br />然后使用它： <br /><pre name="code" class="java">public class FooContainer {

    @inject
    private Foo foo;

} </pre><br /><br />我的问题是，Foo对象根据属性不同可以生成4中不同的实例，那么如何能够在runtime动态注入不同的实例呢？<br />另外，使用@Name注释可以绑定不同的实例，但是似乎无法动态绑定，而且如果类属性比较多的话，把每一种可能的实例都绑定起来，岂不是要吐血了。<br /><br />2. 如何在runtime动态绑定任意对象？<br /><br /><pre name="code" class="java"> public class Foo {
           @inject
           private Object o;
     } 
</pre><br />这个例子里，Foo对象需要使用任意类型的对象实例，如何用Guice动态注入？类型为Object的对象实例为无限多，用@Name应该是解决不了问题了。<br /><br />3. 如何解决传递对象问题？<br />&nbsp;&nbsp; 在API调用过程中，借助方法参数，可以将某一个对象实例在几个对象之间来回传递，而且它也不是singelton，这个被传递的对象不一定是Value Object。如果使用Guice的话如何实现？<br /><br />4. 如何解决动态扩展的问题？<br />&nbsp;&nbsp; 为了便于理解，我举个简单的例子，MVC模式大家应该都很清楚，假如一个Control对应一个Model的话，用Guice可以完美实现。但是如果一个Control可以控制多个Model，而Model的数量是动态的，也就是说Control需要在runtime创建新的Model，同时还要保存已经存在的Models。针对这种情况，如何使用Guice注入？<br /><br />5. 如何注入String？<br />&nbsp;&nbsp; 我刚刚开始接触Guice，估计用过Guice的朋友能够马上回答这个问题。先举个例子：<br /><pre name="code" class="java"> public class Foo {

    @inject
    private String a;

    public Foo(String a) {
        this.a = a;
    }
} </pre><br /><br />在使用Foo对象时，如何动态注入不同的String值？<br />其实这个问题和前面的几个问题类似，但是String是一个比较特殊的对象，所以单独拿出来提问。<br /><br />6. 如何解决类关联的问题。例如：<br /><br /><pre name="code" class="java">
public class Foo {

    private Bar bar;

    public Foo() {
        bar = new Bar(this);
    }

public class Bar {

    private Foo foo;

    public Bar(Foo foo) {
      this.foo = foo;
    }
</pre><br />如何保证使用guice注入后，bar中的foo是创建Bar的那个Foo对象实例？
          <br/><br/>
          <span style="color:red;">
            <a href="http://polygoncell.javaeye.com/blog/182977#comments" style="color:red;">已有 <strong>25</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">Windows7在微软WinHEC 2008上揭开神秘面纱</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 15 Apr 2008 17:35:25 +0800</pubDate>
        <link>http://polygoncell.javaeye.com/blog/182977</link>
        <guid>http://polygoncell.javaeye.com/blog/182977</guid>
      </item>
          <item>
        <title>Hibernate user type with Annotation</title>
        <author>polygoncell</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://polygoncell.javaeye.com">polygoncell</a>&nbsp;
                    链接：<a href="http://polygoncell.javaeye.com/blog/214145" style="color:red;">http://polygoncell.javaeye.com/blog/214145</a>&nbsp;
          发表时间: 2008年03月24日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <div class="postText"> 		使用UserType首先要弄清楚它的目的。大家知道Hibernate解决的主要是对象数据库阻抗失衡的问题，也就是如何将一个或多个对象保存到一个或多个数据库表格中。这其中有很多方法，其实大部分情况下采用<tt class="literal">@Embeddable和</tt>
@Embedded 就可以解决问题了，只有嵌入对象方式无法满足要求时，或者是Hibernate默认的持久化方式无法满足要求时，才应该考虑UserType。总之记住一 个原则，不到山穷水尽，不要轻易使用UserType。还有一个要慎重考虑使用UserType的原因是：一旦采用了UserType，你的项目就脱离了 JPA，而直接和Hibernate耦合在一起了。<br />
 <br />
 扩展UserType主要分为两种：<br />
<ol>
<li>immutable</li>
<li>mutable</li>
</ol>
今天我先举个immutable的例子。<br />
 <br />
 Java 5提出了一个新的enum类，JPA提供的标准方法是保存enum的name或者是ordinal。这种默认方式能够满足新开发的项目，但是对于一些老项目翻新并不一定适用。下面我们来看一个例子：<br />
 <br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--   <br  />
<br  />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br  />
<a href="http://www.CodeHighlighter.com/" target="_blank">http://www.CodeHighlighter.com/</a><br  />
<br  />
--><span style="color: #0000ff;">public</span>
<span style="color: #000000;">&nbsp;</span>
<span style="color: #0000ff;">class</span>
<span style="color: #000000;">&nbsp;Status&nbsp;{<br />
 <br />
 &nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">public</span>
<span style="color: #000000;">&nbsp;</span>
<span style="color: #0000ff;">static</span>
<span style="color: #000000;">&nbsp;</span>
<span style="color: #0000ff;">final</span>
<span style="color: #000000;">&nbsp;</span>
<span style="color: #0000ff;">int</span>
<span style="color: #000000;">&nbsp;ACTIVATED&nbsp;</span>
<span style="color: #000000;">=</span>
<span style="color: #000000;">&nbsp;</span>
<span style="color: #000000;">5</span>
<span style="color: #000000;">;<br />
 &nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">public</span>
<span style="color: #000000;">&nbsp;</span>
<span style="color: #0000ff;">static</span>
<span style="color: #000000;">&nbsp;</span>
<span style="color: #0000ff;">final</span>
<span style="color: #000000;">&nbsp;</span>
<span style="color: #0000ff;">int</span>
<span style="color: #000000;">&nbsp;DEACTIVATED&nbsp;</span>
<span style="color: #000000;">=</span>
<span style="color: #000000;">&nbsp;</span>
<span style="color: #000000;">6</span>
<span style="color: #000000;">;<br />
 }</span>
</div>
<br />
 这个是在java5之前常用的常量定义方法，老项目数据库里面已经保存了很多的5啊6的。现在要把Status改写成enum，而且不希望修改数据库中已有的数据，怎么做？第一反应，status enum可以这么写：<br />
 <br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--   <br  />
<br  />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br  />
<a href="http://www.CodeHighlighter.com/" target="_blank">http://www.CodeHighlighter.com/</a><br  />
<br  />
--><span style="color: #0000ff;">public</span>
<span style="color: #000000;">&nbsp;</span>
<span style="color: #0000ff;">enum</span>
<span style="color: #000000;">&nbsp;Status&nbsp;{<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ACTIVATED,<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DEACTIVATED;<br />
 }</span>
</div>
<br />
 持久化enum的name属性是肯定不用考虑了，ordinal属性呢？这里要保存的可是5和6，而Status enum只有两个实体，他们的ordinal只是0和1。而且项目中还会有其他很多类似的常量类需要改写成enum，JPA的默认方式无法完成任务，这时 候可以开始考虑使用UserType了。<br />
 <br />
 先定义一个接口，这样可以使用一个UserType支持所有类似的enum：<br />
 <br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--   <br  />
<br  />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br  />
<a href="http://www.CodeHighlighter.com/" target="_blank">http://www.CodeHighlighter.com/</a><br  />
<br  />
--><span style="color: #0000ff;">public</span>
<span style="color: #000000;">&nbsp;</span>
<span style="color: #0000ff;">interface</span>
<span style="color: #000000;">&nbsp;DescriptionID&nbsp;{<br />
 <br />
 &nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;getDescription();<br />
 <br />
 &nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">int</span>
<span style="color: #000000;">&nbsp;getId();<br />
 }</span>
</div>
<br />
 然后改写Status enum:<br />
 <br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--   <br  />
<br  />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br  />
<a href="http://www.CodeHighlighter.com/" target="_blank">http://www.CodeHighlighter.com/</a><br  />
<br  />
--><span style="color: #0000ff;">public</span>
<span style="color: #000000;">&nbsp;</span>
<span style="color: #0000ff;">enum</span>
<span style="color: #000000;">&nbsp;Status&nbsp;</span>
<span style="color: #0000ff;">implements</span>
<span style="color: #000000;">&nbsp;DescriptionID&nbsp;{<br />
 <br />
 &nbsp;&nbsp;&nbsp;&nbsp;ACTIVATED(</span>
<span style="color: #000000;">5</span>
<span style="color: #000000;">,&nbsp;</span>
<span style="color: #000000;">&quot;</span>
<span style="color: #000000;">This&nbsp;object&nbsp;is&nbsp;activated</span>
<span style="color: #000000;">&quot;</span>
<span style="color: #000000;">),&nbsp;&nbsp;<br />
 &nbsp;&nbsp;&nbsp; DEACTIVATED(</span>
<span style="color: #000000;">9</span>
<span style="color: #000000;">,&nbsp;</span>
<span style="color: #000000;">&quot;</span>
<span style="color: #000000;">This&nbsp;object&nbsp;is&nbsp;deactivated</span>
<span style="color: #000000;">&quot;</span>
<span style="color: #000000;">);<br />
 <br />
 &nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">private</span>
<span style="color: #000000;">&nbsp;Integer&nbsp;id;<br />
 &nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">private</span>
<span style="color: #000000;">&nbsp;String&nbsp;description;<br />
 &nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">private</span>
<span style="color: #000000;">&nbsp;</span>
<span style="color: #0000ff;">static</span>
<span style="color: #000000;">&nbsp;List</span>
<span style="color: #000000;">&lt;</span>
<span style="color: #000000;">Status</span>
<span style="color: #000000;">&gt;</span>
<span style="color: #000000;">&nbsp;list;<br />
 <br />
 &nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">static</span>
<span style="color: #000000;">&nbsp;{<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list&nbsp;</span>
<span style="color: #000000;">=</span>
<span style="color: #000000;">&nbsp;</span>
<span style="color: #0000ff;">new</span>
<span style="color: #000000;">&nbsp;ArrayList</span>
<span style="color: #000000;">&lt;</span>
<span style="color: #000000;">Status</span>
<span style="color: #000000;">&gt;</span>
<span style="color: #000000;">(</span>
<span style="color: #000000;">2</span>
<span style="color: #000000;">);<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list.add(ACTIVATED);<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list.add(DEACTIVATED);<br />
 &nbsp;&nbsp;&nbsp;&nbsp;}<br />
 <br />
 &nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">private</span>
<span style="color: #000000;">&nbsp;Status(</span>
<span style="color: #0000ff;">int</span>
<span style="color: #000000;">&nbsp;statusNr,&nbsp;String&nbsp;description)&nbsp;{<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">this</span>
<span style="color: #000000;">.id&nbsp;</span>
<span style="color: #000000;">=</span>
<span style="color: #000000;">&nbsp;statusNr;<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">this</span>
<span style="color: #000000;">.description&nbsp;</span>
<span style="color: #000000;">=</span>
<span style="color: #000000;">&nbsp;description;<br />
 &nbsp;&nbsp;&nbsp;&nbsp;}<br />
 <br />
 &nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">public</span>
<span style="color: #000000;">&nbsp;String&nbsp;getDescription()&nbsp;{<br />
 <br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">return</span>
<span style="color: #000000;">&nbsp;</span>
<span style="color: #0000ff;">this</span>
<span style="color: #000000;">.description;<br />
 &nbsp;&nbsp;&nbsp;&nbsp;}<br />
 <br />
 &nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">public</span>
<span style="color: #000000;">&nbsp;Integer&nbsp;getId()&nbsp;{<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">return</span>
<span style="color: #000000;">&nbsp;id;<br />
 &nbsp;&nbsp;&nbsp;&nbsp;}<br />
 <br />
 &nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">public</span>
<span style="color: #000000;">&nbsp;</span>
<span style="color: #0000ff;">static</span>
<span style="color: #000000;">&nbsp;List</span>
<span style="color: #000000;">&lt;</span>
<span style="color: #000000;">Status</span>
<span style="color: #000000;">&gt;</span>
<span style="color: #000000;">&nbsp;getAll()&nbsp;{<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">return</span>
<span style="color: #000000;">&nbsp;list;<br />
 &nbsp;&nbsp;&nbsp;&nbsp;}<br />
 <br />
 &nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">public</span>
<span style="color: #000000;">&nbsp;</span>
<span style="color: #0000ff;">static</span>
<span style="color: #000000;">&nbsp;Status&nbsp;findById(Integer&nbsp;id)&nbsp;{<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">for</span>
<span style="color: #000000;">&nbsp;(Status&nbsp;status&nbsp;:&nbsp;getAll())&nbsp;{<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">if</span>
<span style="color: #000000;">&nbsp;(id&nbsp;</span>
<span style="color: #000000;">==</span>
<span style="color: #000000;">&nbsp;status.getId())&nbsp;{<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">return</span>
<span style="color: #000000;">&nbsp;status;<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">return</span>
<span style="color: #000000;">&nbsp;</span>
<span style="color: #0000ff;">null</span>
<span style="color: #000000;">;<br />
 &nbsp;&nbsp;&nbsp;&nbsp;}<br />
 <br />
 }</span>
</div>
<br />
 注意这里每个enum都必须有两个static方法，这些方法名必须在所有的enum中保持一致。List（）方法是为了方便获取所有的Status常 量，例如在用户界面通过ComboBox展示，findById()方法是为了通过给定Id获得对应的Enum实例。其中findById()方法参数一 定要是Integer，原因后面会讲到。<br />
 <br />
 下面编写<span style="color: #000000;">DescriptionIDUserType：<br />
 <br />
 </span>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--   <br  />
<br  />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br  />
<a href="http://www.CodeHighlighter.com/" target="_blank">http://www.CodeHighlighter.com/</a><br  />
<br  />
--><span style="color: #000000;"><br />
 <br />
 </span>
<span style="color: #0000ff;">public</span>
<span style="color: #000000;">&nbsp;</span>
<span style="color: #0000ff;">class</span>
<span style="color: #000000;">&nbsp;DescriptionIDUserType&nbsp;</span>
<span style="color: #0000ff;">implements</span>
<span style="color: #000000;">&nbsp;UserType,&nbsp;ParameterizedType&nbsp;{<br />
 <br />
 &nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">private</span>
<span style="color: #000000;">&nbsp;Class&nbsp;enumClass;<br />
 <br />
 &nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">public</span>
<span style="color: #000000;">&nbsp;</span>
<span style="color: #0000ff;">void</span>
<span style="color: #000000;">&nbsp;setParameterValues(Properties&nbsp;parameters)&nbsp;{<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">try</span>
<span style="color: #000000;">&nbsp;{<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;enumClass&nbsp;</span>
<span style="color: #000000;">=</span>
<span style="color: #000000;">&nbsp;ReflectHelper.classForName(parameters.getProperty(</span>
<span style="color: #000000;">&quot;</span>
<span style="color: #000000;">class</span>
<span style="color: #000000;">&quot;</span>
<span style="color: #000000;">));<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span>
<span style="color: #0000ff;">catch</span>
<span style="color: #000000;">&nbsp;(ClassNotFoundException&nbsp;e)&nbsp;{<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #008000;">//</span>
<span style="color: #008000;">&nbsp;TODO&nbsp;Auto-generated&nbsp;catch&nbsp;block</span>
<span style="color: #008000;"><br />
 </span>
<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
 &nbsp;&nbsp;&nbsp;&nbsp;}<br />
 &nbsp;&nbsp;&nbsp;&nbsp;<br />
 &nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">public</span>
<span style="color: #000000;">&nbsp;Object&nbsp;assemble(Serializable&nbsp;cached,&nbsp;Object&nbsp;arg1)<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">throws</span>
<span style="color: #000000;">&nbsp;HibernateException&nbsp;{<br />
 <br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">return</span>
<span style="color: #000000;">&nbsp;cached;<br />
 &nbsp;&nbsp;&nbsp;&nbsp;}<br />
 &nbsp;&nbsp;&nbsp;&nbsp;<br />
 &nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #008000;">/*</span>
<span style="color: #008000;"><br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;(non-Javadoc)<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@see&nbsp;org.hibernate.usertype.UserType#deepCopy(java.lang.Object)<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #008000;">*/</span>
<span style="color: #000000;"><br />
 &nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">public</span>
<span style="color: #000000;">&nbsp;Object&nbsp;deepCopy(Object&nbsp;value)&nbsp;</span>
<span style="color: #0000ff;">throws</span>
<span style="color: #000000;">&nbsp;HibernateException&nbsp;{<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #008000;">//</span>
<span style="color: #008000;">&nbsp;TODO&nbsp;Auto-generated&nbsp;method&nbsp;stub</span>
<span style="color: #008000;"><br />
 </span>
<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">return</span>
<span style="color: #000000;">&nbsp;value;<br />
 &nbsp;&nbsp;&nbsp;&nbsp;}<br />
 <br />
 &nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #008000;">/*</span>
<span style="color: #008000;"><br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;(non-Javadoc)<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@see&nbsp;org.hibernate.usertype.UserType#disassemble(java.lang.Object)<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #008000;">*/</span>
<span style="color: #000000;"><br />
 &nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">public</span>
<span style="color: #000000;">&nbsp;Serializable&nbsp;disassemble(Object&nbsp;value)&nbsp;</span>
<span style="color: #0000ff;">throws</span>
<span style="color: #000000;">&nbsp;HibernateException&nbsp;{<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #008000;">//</span>
<span style="color: #008000;">&nbsp;TODO&nbsp;Auto-generated&nbsp;method&nbsp;stub</span>
<span style="color: #008000;"><br />
 </span>
<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">return</span>
<span style="color: #000000;">&nbsp;(Serializable)&nbsp;value;<br />
 &nbsp;&nbsp;&nbsp;&nbsp;}<br />
 <br />
 &nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #008000;">/*</span>
<span style="color: #008000;"><br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;(non-Javadoc)<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@see&nbsp;org.hibernate.usertype.UserType#equals(java.lang.Object,<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;java.lang.Object)<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #008000;">*/</span>
<span style="color: #000000;"><br />
 &nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">public</span>
<span style="color: #000000;">&nbsp;</span>
<span style="color: #0000ff;">boolean</span>
<span style="color: #000000;">&nbsp;equals(Object&nbsp;id1,&nbsp;Object&nbsp;id2)&nbsp;</span>
<span style="color: #0000ff;">throws</span>
<span style="color: #000000;">&nbsp;HibernateException&nbsp;{<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">if</span>
<span style="color: #000000;">&nbsp;(id1&nbsp;</span>
<span style="color: #000000;">==</span>
<span style="color: #000000;">&nbsp;id2)&nbsp;{<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">return</span>
<span style="color: #000000;">&nbsp;</span>
<span style="color: #0000ff;">true</span>
<span style="color: #000000;">;<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">if</span>
<span style="color: #000000;">&nbsp;(id1&nbsp;</span>
<span style="color: #000000;">==</span>
<span style="color: #000000;">&nbsp;</span>
<span style="color: #0000ff;">null</span>
<span style="color: #000000;">&nbsp;</span>
<span style="color: #000000;">||</span>
<span style="color: #000000;">&nbsp;id2&nbsp;</span>
<span style="color: #000000;">==</span>
<span style="color: #000000;">&nbsp;</span>
<span style="color: #0000ff;">null</span>
<span style="color: #000000;">)&nbsp;{<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">return</span>
<span style="color: #000000;">&nbsp;</span>
<span style="color: #0000ff;">false</span>
<span style="color: #000000;">;<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
 <br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">final</span>
<span style="color: #000000;">&nbsp;DescriptionID&nbsp;did1&nbsp;</span>
<span style="color: #000000;">=</span>
<span style="color: #000000;">&nbsp;(DescriptionID)&nbsp;id1;<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">final</span>
<span style="color: #000000;">&nbsp;DescriptionID&nbsp;did2&nbsp;</span>
<span style="color: #000000;">=</span>
<span style="color: #000000;">&nbsp;(DescriptionID)&nbsp;id2;<br />
 <br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">return</span>
<span style="color: #000000;">&nbsp;did1.getId()&nbsp;</span>
<span style="color: #000000;">==</span>
<span style="color: #000000;">&nbsp;did2.getId()<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #000000;">&amp;&amp;</span>
<span style="color: #000000;">&nbsp;StringUtils.equals(did1.getDescription(),&nbsp;did2<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.getDescription());<br />
 &nbsp;&nbsp;&nbsp;&nbsp;}<br />
 <br />
 &nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #008000;">/*</span>
<span style="color: #008000;"><br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;(non-Javadoc)<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@see&nbsp;org.hibernate.usertype.UserType#hashCode(java.lang.Object)<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #008000;">*/</span>
<span style="color: #000000;"><br />
 &nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">public</span>
<span style="color: #000000;">&nbsp;</span>
<span style="color: #0000ff;">int</span>
<span style="color: #000000;">&nbsp;hashCode(Object&nbsp;value)&nbsp;</span>
<span style="color: #0000ff;">throws</span>
<span style="color: #000000;">&nbsp;HibernateException&nbsp;{<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #008000;">//</span>
<span style="color: #008000;">&nbsp;TODO&nbsp;Auto-generated&nbsp;method&nbsp;stub</span>
<span style="color: #008000;"><br />
 </span>
<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">return</span>
<span style="color: #000000;">&nbsp;value.hashCode();<br />
 &nbsp;&nbsp;&nbsp;&nbsp;}<br />
 <br />
 &nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #008000;">/*</span>
<span style="color: #008000;"><br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;(non-Javadoc)<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@see&nbsp;org.hibernate.usertype.UserType#isMutable()<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #008000;">*/</span>
<span style="color: #000000;"><br />
 &nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">public</span>
<span style="color: #000000;">&nbsp;</span>
<span style="color: #0000ff;">boolean</span>
<span style="color: #000000;">&nbsp;isMutable()&nbsp;{<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #008000;">//</span>
<span style="color: #008000;">&nbsp;TODO&nbsp;Auto-generated&nbsp;method&nbsp;stub</span>
<span style="color: #008000;"><br />
 </span>
<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">return</span>
<span style="color: #000000;">&nbsp;</span>
<span style="color: #0000ff;">false</span>
<span style="color: #000000;">;<br />
 &nbsp;&nbsp;&nbsp;&nbsp;}<br />
 <br />
 &nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #008000;">/*</span>
<span style="color: #008000;"><br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;(non-Javadoc)<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@see&nbsp;org.hibernate.usertype.UserType#nullSafeGet(java.sql.ResultSet,<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;java.lang.String[],&nbsp;java.lang.Object)<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #008000;">*/</span>
<span style="color: #000000;"><br />
 &nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">public</span>
<span style="color: #000000;">&nbsp;Object&nbsp;nullSafeGet(ResultSet&nbsp;resultSet,&nbsp;String[]&nbsp;names,&nbsp;Object&nbsp;owner)<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">throws</span>
<span style="color: #000000;">&nbsp;HibernateException,&nbsp;SQLException&nbsp;{<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">try</span>
<span style="color: #000000;">&nbsp;{<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">int</span>
<span style="color: #000000;">&nbsp;id&nbsp;</span>
<span style="color: #000000;">=</span>
<span style="color: #000000;">&nbsp;resultSet.getInt(names[</span>
<span style="color: #000000;">0</span>
<span style="color: #000000;">]);<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">if</span>
<span style="color: #000000;">&nbsp;(resultSet.wasNull())&nbsp;{<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">return</span>
<span style="color: #000000;">&nbsp;</span>
<span style="color: #0000ff;">null</span>
<span style="color: #000000;">;<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">return</span>
<span style="color: #000000;">&nbsp;enumClass.getMethod(</span>
<span style="color: #000000;">&quot;</span>
<span style="color: #000000;">findById</span>
<span style="color: #000000;">&quot;</span>
<span style="color: #000000;">,&nbsp;</span>
<span style="color: #0000ff;">new</span>
<span style="color: #000000;">&nbsp;Class[]&nbsp;{&nbsp;Integer.</span>
<span style="color: #0000ff;">class</span>
<span style="color: #000000;">&nbsp;})<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.invoke(</span>
<span style="color: #0000ff;">null</span>
<span style="color: #000000;">,&nbsp;id);<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span>
<span style="color: #0000ff;">catch</span>
<span style="color: #000000;">&nbsp;(IllegalArgumentException&nbsp;e)&nbsp;{<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #008000;">//</span>
<span style="color: #008000;">&nbsp;TODO&nbsp;Auto-generated&nbsp;catch&nbsp;block</span>
<span style="color: #008000;"><br />
 </span>
<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span>
<span style="color: #0000ff;">catch</span>
<span style="color: #000000;">&nbsp;(SecurityException&nbsp;e)&nbsp;{<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #008000;">//</span>
<span style="color: #008000;">&nbsp;TODO&nbsp;Auto-generated&nbsp;catch&nbsp;block</span>
<span style="color: #008000;"><br />
 </span>
<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span>
<span style="color: #0000ff;">catch</span>
<span style="color: #000000;">&nbsp;(IllegalAccessException&nbsp;e)&nbsp;{<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #008000;">//</span>
<span style="color: #008000;">&nbsp;TODO&nbsp;Auto-generated&nbsp;catch&nbsp;block</span>
<span style="color: #008000;"><br />
 </span>
<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span>
<span style="color: #0000ff;">catch</span>
<span style="color: #000000;">&nbsp;(InvocationTargetException&nbsp;e)&nbsp;{<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #008000;">//</span>
<span style="color: #008000;">&nbsp;TODO&nbsp;Auto-generated&nbsp;catch&nbsp;block</span>
<span style="color: #008000;"><br />
 </span>
<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span>
<span style="color: #0000ff;">catch</span>
<span style="color: #000000;">&nbsp;(NoSuchMethodException&nbsp;e)&nbsp;{<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #008000;">//</span>
<span style="color: #008000;">&nbsp;TODO&nbsp;Auto-generated&nbsp;catch&nbsp;block</span>
<span style="color: #008000;"><br />
 </span>
<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">return</span>
<span style="color: #000000;">&nbsp;</span>
<span style="color: #0000ff;">null</span>
<span style="color: #000000;">;<br />
 &nbsp;&nbsp;&nbsp;&nbsp;}<br />
 <br />
 &nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #008000;">/*</span>
<span style="color: #008000;"><br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;(non-Javadoc)<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@see&nbsp;org.hibernate.usertype.UserType#nullSafeSet(java.sql.PreparedStatement,<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;java.lang.Object,&nbsp;int)<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #008000;">*/</span>
<span style="color: #000000;"><br />
 &nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">public</span>
<span style="color: #000000;">&nbsp;</span>
<span style="color: #0000ff;">void</span>
<span style="color: #000000;">&nbsp;nullSafeSet(PreparedStatement&nbsp;statement,&nbsp;Object&nbsp;value,&nbsp;</span>
<span style="color: #0000ff;">int</span>
<span style="color: #000000;">&nbsp;index)<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">throws</span>
<span style="color: #000000;">&nbsp;HibernateException,&nbsp;SQLException&nbsp;{<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">if</span>
<span style="color: #000000;">&nbsp;(value&nbsp;</span>
<span style="color: #000000;">==</span>
<span style="color: #000000;">&nbsp;</span>
<span style="color: #0000ff;">null</span>
<span style="color: #000000;">)&nbsp;{<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;statement.setNull(index,&nbsp;Hibernate.INTEGER.sqlType());<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span>
<span style="color: #0000ff;">else</span>
<span style="color: #000000;">&nbsp;{<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DescriptionID&nbsp;dID&nbsp;</span>
<span style="color: #000000;">=</span>
<span style="color: #000000;">&nbsp;(DescriptionID)&nbsp;value;<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;statement.setInt(index,&nbsp;dID.getId());<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
 &nbsp;&nbsp;&nbsp;&nbsp;}<br />
 <br />
 &nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #008000;">/*</span>
<span style="color: #008000;"><br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;(non-Javadoc)<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@see&nbsp;org.hibernate.usertype.UserType#replace(java.lang.Object,<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;java.lang.Object,&nbsp;java.lang.Object)<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #008000;">*/</span>
<span style="color: #000000;"><br />
 &nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">public</span>
<span style="color: #000000;">&nbsp;Object&nbsp;replace(Object&nbsp;original,&nbsp;Object&nbsp;arg1,&nbsp;Object&nbsp;arg2)<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">throws</span>
<span style="color: #000000;">&nbsp;HibernateException&nbsp;{<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #008000;">//</span>
<span style="color: #008000;">&nbsp;TODO&nbsp;Auto-generated&nbsp;method&nbsp;stub</span>
<span style="color: #008000;"><br />
 </span>
<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">return</span>
<span style="color: #000000;">&nbsp;original;<br />
 &nbsp;&nbsp;&nbsp;&nbsp;}<br />
 <br />
 &nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #008000;">/*</span>
<span style="color: #008000;"><br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;(non-Javadoc)<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@see&nbsp;org.hibernate.usertype.UserType#returnedClass()<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #008000;">*/</span>
<span style="color: #000000;"><br />
 &nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">public</span>
<span style="color: #000000;">&nbsp;Class&nbsp;returnedClass()&nbsp;{<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">return</span>
<span style="color: #000000;">&nbsp;DescriptionID.</span>
<span style="color: #0000ff;">class</span>
<span style="color: #000000;">;<br />
 &nbsp;&nbsp;&nbsp;&nbsp;}<br />
 <br />
 &nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #008000;">/*</span>
<span style="color: #008000;"><br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;(non-Javadoc)<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@see&nbsp;org.hibernate.usertype.UserType#sqlTypes()<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #008000;">*/</span>
<span style="color: #000000;"><br />
 &nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">public</span>
<span style="color: #000000;">&nbsp;</span>
<span style="color: #0000ff;">int</span>
<span style="color: #000000;">[]&nbsp;sqlTypes()&nbsp;{<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">return</span>
<span style="color: #000000;">&nbsp;</span>
<span style="color: #0000ff;">new</span>
<span style="color: #000000;">&nbsp;</span>
<span style="color: #0000ff;">int</span>
<span style="color: #000000;">[]{Hibernate.INTEGER.sqlType()};<br />
 &nbsp;&nbsp;&nbsp;&nbsp;}<br />
 <br />
 <br />
 }<br />
 </span>
</div>
<br />
 我们的这个UserType是要支持实现<span style="color: #000000;">DescriptionID的各种不同的enum，而enum是没法继承的。所以我们需要用户给出具体的参数，以进一步确定到底是哪个enum类。这也就导致了，我们的这个类需要实现</span>
<span style="color: #000000;">ParameterizedType接口。</span>
<br />
 <span style="color: #000000;"><br />
 由于enum类本身是immutable的，所以这个UserType的实现类相对比较简单，主要的两个方法是</span>
<span style="color: #000000;">nullSafeGet和</span>
<span style="color: #000000;">nullSafeSet。 在nullSaftGet中我们使用Java Reflection并借助用户给出的enum类参数直接调用该enum类的findById（）方法，这样我们就可以使用数据库中的integer找到 对应的enum实例。注意，由于使用了Java Reflection,所以findById()方法参数必须是Integer而非int。 在nullSafeSet中，我们则通过</span>
<span style="color: #000000;">DescriptionID接口直接获取enum实例的id属性，并且将它保存到数据库中去。<br />
 <br />
 最后看看怎么使用这个UserType：<br />
 <br />
 </span>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--   <br  />
<br  />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br  />
<a href="http://www.CodeHighlighter.com/" target="_blank">http://www.CodeHighlighter.com/</a><br  />
<br  />
--><span style="color: #000000;">@TypeDefs({@TypeDef(name&nbsp;</span>
<span style="color: #000000;">=</span>
<span style="color: #000000;">&nbsp;</span>
<span style="color: #000000;">&quot;</span>
<span style="color: #000000;">status</span>
<span style="color: #000000;">&quot;</span>
<span style="color: #000000;">,&nbsp;typeClass&nbsp;</span>
<span style="color: #000000;">=</span>
<span style="color: #000000;">&nbsp;DescriptionIDUserType.</span>
<span style="color: #0000ff;">class</span>
<span style="color: #000000;">,&nbsp;<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;parameters&nbsp;</span>
<span style="color: #000000;">=</span>
<span style="color: #000000;">&nbsp;{@Parameter(name&nbsp;</span>
<span style="color: #000000;">=</span>
<span style="color: #000000;">&nbsp;</span>
<span style="color: #000000;">&quot;</span>
<span style="color: #000000;">class</span>
<span style="color: #000000;">&quot;</span>
<span style="color: #000000;">,&nbsp;value&nbsp;</span>
<span style="color: #000000;">=</span>
<span style="color: #000000;">&nbsp;</span>
<span style="color: #000000;">&quot;</span>
<span style="color: #000000;">com.yourpackage.Status</span>
<span style="color: #000000;">&quot;</span>
<span style="color: #000000;">)})})<br />
 @Entity<br />
 </span>
<span style="color: #0000ff;">public</span>
<span style="color: #000000;">&nbsp;</span>
<span style="color: #0000ff;">class</span>
<span style="color: #000000;">&nbsp;SomeObject&nbsp;{<br />
 <br />
 &nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">private</span>
<span style="color: #000000;">&nbsp;Integer&nbsp;objectId;<br />
 &nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">private</span>
<span style="color: #000000;">&nbsp;Status&nbsp;status;<br />
 <br />
 &nbsp;&nbsp;&nbsp;&nbsp;@Id<br />
 &nbsp;&nbsp;&nbsp; </span>
@GeneratedValue(strategy=GenerationType.AUTO)<span style="color: #000000;">&nbsp;&nbsp;&nbsp; <br />
 &nbsp;&nbsp;&nbsp; </span>
<span style="color: #0000ff;">public</span>
<span style="color: #000000;">&nbsp;Integer&nbsp;getObjectId()&nbsp;{<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">return</span>
<span style="color: #000000;">&nbsp;objectId;<br />
 &nbsp;&nbsp;&nbsp;&nbsp;}<br />
 <br />
 &nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">public</span>
<span style="color: #000000;">&nbsp;</span>
<span style="color: #0000ff;">void</span>
<span style="color: #000000;">&nbsp;setObjectId(Integer&nbsp;objectId)&nbsp;{<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">this</span>
<span style="color: #000000;">.objectId&nbsp;</span>
<span style="color: #000000;">=</span>
<span style="color: #000000;">&nbsp;objectId;<br />
 &nbsp;&nbsp;&nbsp;&nbsp;}<br />
 <br />
 &nbsp;&nbsp;&nbsp;&nbsp;@Type(type&nbsp;</span>
<span style="color: #000000;">=</span>
<span style="color: #000000;">&nbsp;</span>
<span style="color: #000000;">&quot;</span>
<span style="color: #000000;">status</span>
<span style="color: #000000;">&quot;</span>
<span style="color: #000000;">)<br />
 &nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">public</span>
<span style="color: #000000;">&nbsp;Status&nbsp;getStatus()&nbsp;{<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">return</span>
<span style="color: #000000;">&nbsp;status;<br />
 &nbsp;&nbsp;&nbsp;&nbsp;}<br />
 <br />
 &nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">public</span>
<span style="color: #000000;">&nbsp;</span>
<span style="color: #0000ff;">void</span>
<span style="color: #000000;">&nbsp;setStatus(Status&nbsp;status)&nbsp;{<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span style="color: #0000ff;">this</span>
<span style="color: #000000;">.status&nbsp;</span>
<span style="color: #000000;">=</span>
<span style="color: #000000;">&nbsp;status;<br />
 &nbsp;&nbsp;&nbsp;&nbsp;}<br />
 }</span>
</div>
<br />
 其中值得讲讲的就是定义Type时使用的parameter,&quot;class&quot;参数是我们自己定义的，该参数为<span style="color: #000000;">DescriptionIDUserType提供</span>
了具体的enum类。前面已经讲过了，<span style="color: #000000;">DescriptionIDUserType就是在运行时态利用这个参数自定义enum与数据库之间的持久化逻辑。<br />
 <br />
 使用这个UserType之后，我们就可以在确保数据库数据不变的情况下，成功地将类型不保险的常量类改写成enum，而且这个UserType支持所有实现了</span>
<span style="color: #000000;">DescriptionID接口的enum类。<br />
 <br />
 类似的情况朋友们可以自由发挥了。<br />
 <br />
 <br />
 </span>
  	</div>
&nbsp;
          <br/><br/>
          <span style="color:red;">
            <a href="http://polygoncell.javaeye.com/blog/214145#comments" style="color:red;">已有 <strong>4</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">Windows7在微软WinHEC 2008上揭开神秘面纱</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 24 Mar 2008 02:39:00 +0800</pubDate>
        <link>http://polygoncell.javaeye.com/blog/214145</link>
        <guid>http://polygoncell.javaeye.com/blog/214145</guid>
      </item>
          <item>
        <title>Hibernate 3和Java Persistence API 程序开发从入门到精通</title>
        <author>polygoncell</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://polygoncell.javaeye.com">polygoncell</a>&nbsp;
                    链接：<a href="http://polygoncell.javaeye.com/blog/214146" style="color:red;">http://polygoncell.javaeye.com/blog/214146</a>&nbsp;
          发表时间: 2007年11月19日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>花了一年多的时间， 这本书终于出版了。这是我编写的第一本专业书籍，它是对我自大学毕业之后到目前为止整个职业经历的一个总结。这里面包括了，我在研究生期间从事的科研项目中获取的知识，以及硕士毕业后在德国各类公司参与开发和主持开发的各类项目中获取的实践经验。因此，这本书融合了学院派的理论知识和实践派的一线经验，我希望将自己多年学习和工作获取的知识和经验拿出来与国内的同行分享，并借这个机会与大家多多交流。 </p>
<p>这本书不单单局限在Hibernate 3和JPA上，而是强调知识的含金量。本书在以Hibernate为中心的前提下，尽可能地扩展到各类在软件开发中需要使用到的理论和技术上去。因此在阅读本书的过程中，读者除了掌握Hibernate3和JPA，理解它们的内部构架，还会同时了解诸如极限编程，测试驱动开发，Java SE 5的新特性，JUnit 4的全新构架，以及Log4j，ant和Hudson等一系列开源框架的使用方法。 </p>
<p>这里是本书的简介：本书介绍Hibernate开发知识。全书主要介绍信息持久化、对象持久化、对象关系映射等概念，以及Java SE5中最重要的新特性，初始化Hibernate的核心类，使用JPA提供的标准注释将实体类的不同属性映射到关系型数据库的表格，对象关系映射所要面对的两种复杂关系，使用Hibernate的扩展注释映射各类复杂的集合接口和集合类，实体对象在Hibernate中存在的4种状态，Session接口，Hibernate建立的一套完善的查询框架(Criterion)，Hibernate中封装SQL的策略，Hibernate EntityManager模块的内部构架。 </p>
<p>全国各大书店有售，各大网上书店有售，欢迎大家批评指正。</p>
<p><a href="http://www.dearbook.com.cn/book/viewbook.aspx?pno=TS00213837" target="_blank"><img src="http://p.blog.csdn.net/images/p_blog_csdn_net/schnell/H3Book.jpg" alt="Hibernate 3和Java Persistence API 程序开发从入门到精通（附光盘）" />
</a>