<?xml version="1.0" encoding="gb2312"?>

<!-- RSS generated by oioj.net on 4/16/2004 ; 感谢LeXRus提供 RSS 2.0 文档; 此文件可自由使用，但请保留此行信息 --> 
<!-- Source download URL: http://blogger.org.cn/blog/rss2.asp       -->
<rss version="2.0">

<channel>
<title>七月天</title>
<link>http://blogger.org.cn/blog/blog.asp?name=torrent</link>
<description>torrent的博客</description>
<copyright>blogger.org.cn</copyright>
<generator>W3CHINA Blog</generator>
<webMaster>webmaster@blogger.org.cn</webMaster>
<item>
<title><![CDATA[八年之后]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=torrent&amp;id=73019</link>
<author>torrent</author>
<pubDate>2013/5/23 12:13:50</pubDate>
<description><![CDATA[<A><FONT size=3 face=仿宋_GB2312>　</FONT></A><FONT size=3 face=仿宋_GB2312> </FONT>
<P><FONT size=3 face=仿宋_GB2312>&nbsp;&nbsp;&nbsp; 突然记起，多年之前曾写过一点博客，却怎么也回忆不起博客地址了。只记起在博客中曾尝试翻译《设计模式》，并使用了“四人帮版”这个词，多亏google还记得，带我回到了这里。（先用baidu搜索的，怎么也搜不到，只能小小的鄙视一下（baidu、这个站点、抑或是自己呢......））</FONT></P>
<P><FONT size=3 face=仿宋_GB2312>&nbsp;&nbsp;&nbsp; 我算是个被招安了的人，有段时间不做技术了。这次又看到八、九年前写的东西，回忆起自己曾如此着迷于标准、模式、框架...，忆起长期彻夜流连于w3c社区的时光...，也想起这些年的一些经历...，又萌发了要说点什么、甚至是做点什么的冲动。</FONT></P>
<P><FONT size=3 face=仿宋_GB2312>&nbsp;&nbsp;&nbsp; 到了午餐的时候，已不能再像以前那样不管不顾了，得按时吃饭。好吧，总之，我还会回来的----算是对自己的承诺.....</FONT></P>]]></description>
</item><item>
<title><![CDATA[《java开源开发》笔记（2）]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=torrent&amp;id=7955</link>
<author>torrent</author>
<pubDate>2005/8/23 9:03:11</pubDate>
<description><![CDATA[<A><FONT size=2>　</FONT></A><FONT size=2> </FONT>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=2><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">第</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">2</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">章</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=2><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">内容：讨论用来构建</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">PetSoar</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的工具和技巧，以及它们的组合使用。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=2><SPAN lang=EN-US><FONT face="Times New Roman">1</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。还有</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">PetStore</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">出现吗？</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=2><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">列出许多</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Petstore</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。（有一句话有意思，大意为：用</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">PetStore</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">卖技术的比卖宠物的多，哈哈！！！）</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=2><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">比较而言，</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">PetSoar</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的构建目标</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">----</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">应用速度快，包含代码少（</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">less is more</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">思想）；更关心可维护性！！</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=2><SPAN lang=EN-US><FONT face="Times New Roman">2</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。了解可维护性的重要性</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=2><SPAN lang=EN-US><FONT face="Times New Roman">3</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。了解</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">PetSoar</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的需求</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=2><SPAN lang=EN-US><FONT face="Times New Roman">4</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。架构和技术</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>架构</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=2><SPAN lang=EN-US><FONT face="Times New Roman"><SPAN style="mso-spacerun: yes">&nbsp;&nbsp; </SPAN>SOA</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">架构：</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">service-oriented-architecture:</FONT></SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 10.5pt; mso-char-indent-count: 1.0"><FONT size=2><SPAN lang=EN-US><SPAN style="mso-spacerun: yes"><FONT face="Times New Roman">&nbsp;</FONT></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">整个应用由一系列服务构成，底层服务提供系统功能（如文档索引和对象持久性），高层提供商业逻辑（维护宠物清单，购物篮）。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 10.5pt; mso-char-indent-count: 1.0"><FONT size=2><SPAN lang=EN-US><SPAN style="mso-spacerun: yes"><FONT face="Times New Roman">&nbsp;</FONT></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">每个服务都运用了门面模式（</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">facade</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">），在一个简单的接口后封装了逻辑复杂性和内部</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">API</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><FONT size=2><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">利用此架构的技术，如</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">CORBA</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">EJB</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">SOAP Webservice</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，通常由于分布性而导致复杂性（安全，检索，网络延迟等）。但本应用不将服务分布化，因而摆脱了复杂性。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><FONT size=2><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">业务实体（</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">pet,categories,orders</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）用</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">POJOs</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">（</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Plain Old Java Objects</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）表示。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><o:p><FONT face="Times New Roman" size=2>&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>实用库</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><FONT size=2><SPAN lang=EN-US><FONT face="Times New Roman">Jarkarta’s Common</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">项目（</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Common Lang</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中的实用类实现领域对象中的</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">code(),equals(),tostring()</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">方法，</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Common Degester</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">装载</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">XML</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">文件，</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Common Logging</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">记载日志信息），在</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">11</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">章讨论。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><SPAN lang=EN-US><o:p><FONT face="Times New Roman" size=2>&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>应用持久性和搜索</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt"><FONT size=2><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">应用</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Hibernate</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">框架来处理对象持久性（</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">5</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">章），</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">XDoclet</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">用来自动生成</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Hibernate</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">映射</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">XML</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">文件。用</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Lucene</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">来处理复杂的查询。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=2><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">应用</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Web Front End</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">？</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt"><FONT size=2><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">基于</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Web</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的接口和交互是通过</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">XWork</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">和</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">WebWork</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Xwork</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">是通用且可扩展的</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">MVC</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">框架，</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">WebWork</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">建立于</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Xwork</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">之上。（第</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">6</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">章讨论）</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt"><FONT size=2><SPAN lang=EN-US><FONT face="Times New Roman">View</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">层由</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">JSP</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">实现，</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">WebWork</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">提供了内建的</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">JSP</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">标签；</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt"><FONT size=2><SPAN lang=EN-US><FONT face="Times New Roman">Model</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">层由</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">POJO</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">领域对象和服务组成；</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt"><FONT size=2><SPAN lang=EN-US><FONT face="Times New Roman">Controller</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">层由一系列</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Web</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">独立的</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Xwork action</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">类构成。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>测试</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><FONT size=2><SPAN lang=EN-US><FONT face="Times New Roman">Junit</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p><FONT face="Times New Roman" size=2>&nbsp;</FONT></o:p></SPAN></P>]]></description>
</item><item>
<title><![CDATA[AOP@Work: 设计切入点来避免模式密集]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=torrent&amp;id=7954</link>
<author>torrent</author>
<pubDate>2005/8/23 9:00:34</pubDate>
<description><![CDATA[转载自: <A href="http://www-128.ibm.com/developerworks/cn/java/j-aopwork7/" target=_blank>http://www-128.ibm.com/developerworks/cn/java/j-aopwork7/</A><BR><BR><SPAN class=atitle2>“JUnit Cook's Tour”中的可用性和维护性</SPAN><BR>
<TABLE cellSpacing=0 cellPadding=0 border=0>
<TBODY>
<TR vAlign=top align=left>
<TD>
<P>级别: 中级</P></TD></TR></TBODY></TABLE>
<P><A href="http://www-128.ibm.com/developerworks/cn/java/j-aopwork7/#author1"><NAME>Wes Isberg</NAME></A><BR>顾问, IBM<BR>2005 年 8 月</P>
<BLOCKQUOTE><IMG height=38 alt="Column icon" src="http://www-128.ibm.com/developerworks/cn/i/c-j-tinkertoys.gif" width=38 align=left border=0><ABSTRACT-EXTENDED>在“JUnit: A Cook's Tour”一文中，作者 Erich Gamma 和 Kent Beck 讨论了 JUnit 的设计。他们指出，与很多成熟框架中的关键抽象一样，<CODE>TestCase</CODE> 也有很高的模式密集，易于使用而难以修改。在 <I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">AOP@Work</I> 系列的第四期文章中，Wes Isberg 重温了 Cook's Tour，说明如何通过使用 AOP 切入点设计来代替面向对象设计，在一定程度上避免导致成熟的设计难以修改的模式密集。</ABSTRACT-EXTENDED></BLOCKQUOTE>
<P>即使是最好的 Java&#8482; 程序，也会随着时间的推移而老化。为了满足新的需求，设计也在不断演化，关键对象承担着各种模式角色，直到它们变得难以使用或者难以修改，最终不得不重构或者重写系统。面向方面的编程（AOP）提供了一些将特性结合起来提供服务的更优雅的方法，这些方法可以减少交互、降低工作量、延长设计和代码的寿命。</P>
<P>本文将分析 Erich Gamma 和 Kent Beck 在“JUnit: A Cook's Tour”（请参阅 <A href="http://www-128.ibm.com/developerworks/cn/java/j-aopwork7/#resources" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">参考资料</A>）一文中提出的设计。对于他们提出的每种 Java 模式，都给出一种 AspectJ 替代方案，并说明这种方案是否满足下列标准设计目标：</P>
<UL xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<LI><B>功能性</B>：提供的服务是否强大、有用？ 
<LI><B>可用性</B>：客户能否方便地得到服务？ 
<LI><B>可扩展性</B>：程序变化时是否容易扩展或者调整？ 
<LI><B>结合（分解）性</B>：能否与其他部分协作？ 
<LI><B>保护</B>：面对运行时错误或者级联错误，如何保障 API 的安全？ 
<LI><B>可理解性</B>：代码是否清晰易懂？</LI></UL>
<P>设计的每一步中，Gamma 和 Beck 都面临着两难选择，比如可用性与可维护性、可理解性与结合性。在所有的选择中，他们采取的都是简单可用的路线，即便这意味着要放弃次要的目标。因此，他们的设计使得编写单元测试变得很容易。但我还是要问一问，如果使用 AOP 的话，能否避免其中一部分设计取舍呢？</P>
<P>这样问也许看起来不够通情达理，有些过于苛求。JUnit 把自己的工作做得很好，设计中的取舍被很多开发人员所了解，并认为是很正常的做法。要看看 AOP 能否做得更好，我必须问自己一些问题，比方说，能否增加更多的特性，使其更适合那些需要更多服务但不能满足 JUnit 最起码要求的客户。我这样做不是为了改变 JUnit，而是要在达到主要目标的同时不放弃次要的设计目标。</P>
<P>本文中所有的例子都使用了 AspectJ，但也可用于其他 AOP 方法，而且即使刚接触 AspectJ，这些例子也很容易理解。（事实上，阅读过 Cook's Tour 或者了解设计模式，可能要比您使用过 AspectJ 或 JUnit 更有帮助。）要下载本文中的源代码，请单击页面顶部或底部的 <B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">代码</B> 图标（或请参阅 <A href="http://www-128.ibm.com/developerworks/cn/java/j-aopwork7/#Download" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">下载</A>）。</P>
<P>
<TABLE cellSpacing=0 cellPadding=5 width="30%" align=right border=1>
<TBODY>
<TR>
<TD background=/developerworks/cn/i/bg-gold.gif>
<P><A name=sidebar1><B>关于本系列文章</B></A><BR><A href="http://www.ibm.com/developerworks/cn/views/java/libraryview.jsp?search_by=AOP@work:" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><I>AOP@Work</I></A> 系列面对的是在面向方面编程上有些基础，同时又想扩展或加深这方面了解的开发人员。同 developerWorks 的大多数文章一样，这个系列非常实用：读完每篇介绍新技术的文章，都可以立即将其投入使用。 </P>
<P>为该系列挑选的每位作者都是面向方面编程领域的先驱或专家。许多作者都是系列文章中介绍的项目和工具的参与者。每篇文章都力图提供一个中立的评述，以确保观点的公正性与正确性。</P>
<P>关于文章的建议或问题请与文章的作者联系。如果对整个系列有何建议论，可与本系列的负责人 <A href="mailto:ndlesiecki@apache.org" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Nicholas Lesiecki</A> 联系。关于 AOP 的更多背景知识，请参阅 <A href="http://www-128.ibm.com/developerworks/cn/java/j-aopwork7/#resources" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">参考资料</A>。</P></TD></TR></TBODY></TABLE></P>
<P><A name=IDAREOW><SPAN class=atitle2>使用 Command 模式还是进行假设？</SPAN></A><BR>下面是 Gamma 和 Beck 写在“JUnit: A Cook's Tour”开头的一段话：</P>
<BLOCKQUOTE xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">测试用例通常存在于开发人员的脑子里，但实现起来有不同的方式，如打印语句、调试器表达式、测试脚本。如果想要让测试处理起来更容易，则必须使它们成为对象。 </BLOCKQUOTE>
<P>为了使测试成为对象，他们使用了 Command 模式，该模式“将请求封装成对象，从而可以……建立请求队列或者记录请求”。能不能再简单一点呢？</P>
<P>既然焦点是可用性，有点奇怪的是，Gamma 和 Beck 也了解开发人员可以用不同的方式编写测试，但他们却坚持认为，开发人员应该只用一种方式编写测试，即封装成一个对象。为什么这样做呢？为了让测试使用起来更容易。可难就难在：要享受服务的好处，就必须按照这种形式。 </P>
<P>这种权衡影响了设计的成形和演化。可以以特定客户机为目标，按照某种可用性和能力的组合来构建系统。如果客户机改变了，那么可以增加一些层次或者改变可用性与能力的组合，每次都要使用和围绕着已经建立的系统。幸运的话，系统可能有足够的灵活度，这个演化的过程最终会集中到客户机解决方案上。Gamma 和 Beck 用<I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">模式密集</I> 来表达这种集中：</P>
<BLOCKQUOTE xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">一旦发现真正要解决的问题，就可以开始“压缩”解决方案，形成一个越来越密集的在此起决定作用的模式场。 </BLOCKQUOTE>
<P><A name=IDA5EOW><SPAN class=atitle3>设计造成的模式密集</SPAN></A><BR>将测试用例确定为关键抽象并使用 <CODE>Command</CODE> 封装它之后，Cook's Tour 进一步确定了新的需求，为表示这一关键抽象的对象增加了新的特性。下面的图示对此做作了很好的说明：</P>
<P><A name=figure1><B>图 1. JUnit 模式框图</B></A><BR><IMG alt="JUnit 模式框图" src="http://www-128.ibm.com/developerworks/cn/java/j-aopwork7/cooksTourStoryboard.gif" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"></P>
<P>Gamma 和 Beck 遵循了（或者应该说指引着）现在的标准设计过程：发现关键抽象，并将它们封装到对象中，添加模式来安排对象担任的角色和提供的服务。不幸的是，正是这些造成了模式密集。关键抽象的职责和关系在不断增加，直到像步入中年的父母一样只能按照老套的习惯行事。（如果需求超过了它们的能力，那么它们随后会陷入困境。） </P>
<P><A name=IDAUFOW><SPAN class=atitle3>给定一个测试用例……</SPAN></A><BR>AOP 提供了描述抽象的另一种方法：说明连接点的切入点。<I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">连接点</I> 是程序执行中可以有效连接行为的点。连接点的类型取决于 AOP 的方式，但所有连接点在一般程序修改中都应该是稳定的，容易作出有意义的说明。可以使用<I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">切入点</I> 指定程序的连接点，用<I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">通知（advice）</I>指定连接的行为。通知就是陈述“如果 X，则 Y”的一种方式。 </P>
<P>Command 模式说，“我不关心运行的代码是什么，把它放在该方法中就行了。”它要求将代码放在命令类的命令方法中，对于 JUnit 而言，该命令方法是 <CODE>Test</CODE> 的 <CODE>runTest()</CODE> 方法，如 <CODE>TestCase</CODE>：</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
public class MainTest extends TestCase {
  public void runTest(...) {...}
}
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>相反，切入点说“让某个连接点作为测试用例吧。”它只要求测试用例是<I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">某个</I> 连接点。不需要将代码放在特定类的特定方法中，只需要用切入点指定一个测试用例：</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
pointcut testCase() : ... ;
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>比如，可以将测试用例定义为 <CODE>Runnable.run()</CODE> 或main 方法，当然也可以使用 JUnit 测试：</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
pointcut testCase() : execution(void Runnable+.run());
pointcut testCase() : execution(static void main(String[]));
pointcut testCase() : execution(public void Test+.run(TestResult));
pointcut testCase() : execution(public void TestCase+.test*());
</CODE></PRE></TD></TR></TBODY></TABLE>
<P><A name=IDAFHOW><SPAN class=atitle3>切入点的可用性</SPAN></A><BR>切入点的可用性非常突出。在这里，只要测试能够被切入点选择，就可以作为测试用例，即使它不是作为测试编写的。如果能够通过通知而不是通过 API 提供服务，那么就可以减少开发人员在这些服务上的工作量。</P>
<P>通过 AOP，开发人员不需要做什么就能提供服务。这就产生了一种新的 API 客户机：不需要了解它，但可以为它提供服务，或者说它依赖于该服务。对于一般的 API，客户机和提供者之间有明确的契约和调用的具体时间。而对于 AOP，更像是人们依赖于政府的方式：无论叫警察、到 DMV 登记，还是吃饭或者上银行，人们都（无论是否意识到）仰仗于规则，在规定好的点（无论是否明确）上操作。</P>
<P>将 AOP 纳入视野之后，可用性就变成了一个更广泛的连续体，从 API 契约到基于容器的编程模型，再到 AOP 的多种形式。可用性的问题，也从服务接口对客户机公开了多少功能，转变成了客户机希望或需要对服务了解多少以及如何选择（无论是司机、骗子，还是应聘者）。</P>
<P><A name=IDANHOW><SPAN class=atitle3>可重用性</SPAN></A><BR>与方法一样，也可以将切入点声明成抽象的；即在通知中使用切入点，但是让子方面具体声明它。通常，抽象切入点规定的不是具体的时间或地点（如宾夕法尼亚大道 1600 号，星期二），而是很多人感兴趣的一般事件（如选举）。然后可以说明关于此类事件的事实（如，“选举中，新闻机构……”，或者“选举后，胜利者……”），用户可以指定某项选举的时间、地点和人物。如果将测试用例作为抽象切入点，那么我敢说，很多测试装置的特性都能用“如果 X，则 Y”的形式表示，而且不需要知道<I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">如果 X</I> 的很多细节，就能够编写大多数<I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">则 Y</I> 的结论。</P>
<P>如何使用通知来实现特性，同时又避免模式密集带来的危险呢？在类中添加新特性时，每个新成员都能看到其他可见的成员，这增加了理论上的复杂性。相反，AspectJ 最大限度地减少了通知之间的交互。一个连接点上的两个通知彼此是不可见的，它们都只绑定在它们声明的连接点上下文变量中。如果一个通知影响到另一个通知，并且需要排序，那么我可以规定它们的相对优先级，而不需要知道所有的通知并规定完整的顺序。每个通知都使用最少的连接点信息，仅透漏类型安全、异常检查等必需的自身信息。（AspectJ 在 AOP 技术中差不多是惟一支持这一级别的封装的。）由于减少了交互，与在类中添加成员相比，向连接点添加通知所增加的复杂性要小得多。</P>
<P>至于 Cook's Tour 的其他部分，我使用 <CODE>testCase()</CODE> 切入点实现了 Gamma 与 Beck 添加到 <CODE>TestCase</CODE> 中的特性。在其中的每一步中，我都努力避免他们必须要做的那些取舍，评估顺序对连接点是否重要，避免对连接点上下文作出假设，支持能够想到的各种 API 客户机。 </P>
<P><A name=IDAGYXW><SPAN class=atitle2>是使用模板方法还是使用 around 通知？</SPAN></A><BR>使用 Command 封装测试代码之后，Gamma 和 Beck 认识到使用某种通用数据装置测试的一般流程：“建立数据装置、对装置运行某些代码并检查结果，然后清除装置”。为了封装该过程，他们使用了 Template Method 模式：</P>
<BLOCKQUOTE xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">该模式的目的是，“定义操作中算法的框架，将某些步骤推迟到子类中。Template Method 允许子类重定义算法中的某些步骤，而不需要改变算法的结构。” </BLOCKQUOTE>
<P>在 JUnit 中，开发人员使用 <CODE>setUp()</CODE> 和 <CODE>cleanUp()</CODE> 为 <CODE>TestCase</CODE> 管理数据。JUnit 设施负责在运行每个测试用例之前和之后调用这些方法；<CODE>TestCase</CODE> 使用模板方法 <CODE>runBare()</CODE> 来实现这一点：</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
public void runBare() throws Throwable {
  setUp();
  try {
    // run the test method 
    runTest();
  } finally {
    tearDown();
  }
}
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>在 AspectJ 中，如果代码需要在连接点之前和之后运行，可以结合使用 <I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">before</I> 通知和 <I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">after</I> 通知，或者像下面这样单独使用 <I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">around</I> 通知：</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
/** around each test case, do setup and cleanup */
Object around() : testCase() {
  setup(thisJoinPoint);
  try {
    // continue running the test case join point
    return proceed();
  } finally {
     cleanup(thisJoinPoint);
   }
}       
protected void setup(JoinPoint jp) {}
protected void cleanup(JoinPoint jp) {}
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>这样的通知提供了三个自由度：</P>
<UL xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<LI>可用于支持 <I>around</I> 通知的任何连接点。<BR><BR>
<LI>可用于任何类型的测试，因为对运行的代码没有任何假设。<BR><BR>
<LI>通过将装置的建立/清除代码放在可以被覆盖或者委托实现的方法中，可以适应不同类型测试对象所需的不同的装置管理方式。有些可能管理自己的数据，如 <CODE>TestCase</CODE>；有些可能得益于依赖性倒置（dependency inversion），在外部建立配置。 <BR><BR>但是，这些方法都使用 <CODE>JoinPoint</CODE>，在连接点提供了可用于任何上下文的 <CODE>Object</CODE>（可能包含 <I>this</I> 对象、 <I>target</I> 对象和任何参数）。使用 <CODE>JoinPoint</CODE> 将使 <CODE>Object</CODE> 向下强制转换成实际的类型，从而获得了类型安全的一般性。（下面我将介绍一种不损失一般性而获得类型安全的方法。）</LI></UL>
<P>通知提供了和 Template Method 相同的保证但没有 Java 实现的约束。在 JUnit 中，<CODE>TestCase</CODE> 必须控制命令方法来实现模板方法，然后为实现真正的测试还要委派给另一个方法，为 command 代码创建 <CODE>TestCase</CODE> 专用的协议。因此，虽然 Command 使得测试很容易操纵，command 契约对开发人员而言实际上从 <CODE>Test</CODE> 到 <CODE>TestCase</CODE> 是不同的，因而使得 API 的职责更难以理解。 </P>
<P><A name=IDAP1XW><SPAN class=atitle2>使用 Collecting Parameter 还是使用 ThreadLocal？</SPAN></A><BR>Cook's Tour 继续它的漫步：“如果 <CODE>TestCase</CODE> 在森林中运行，那么谁还关心它的结果呢？”当然，Gamma 和 Beck 的回答是：需要记录失败和总结经验。为此，他们使用了 Collecting Parameter 模式： </P>
<BLOCKQUOTE xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">如果需要收集多个方法的结果，应该在方法中添加一个参数传递收集结果的对象。</BLOCKQUOTE>
<P>JUnit 将结果处理封装在一个 <CODE>TestResult</CODE> 中。从这里，订阅者可以找到所有测试的结果，测试装置可以在这里管理需要的结果集合。为了完成采集工作，Template Method <CODE>TestResult.runProtected(..)</CODE> 将测试执行放在 <I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">start</I> 和 <I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">end</I> 辅助调用（housekeeping call）之间，把抛出的异常解释为负的测试结果。 </P>
<P><A name=IDAJ2XW><SPAN class=atitle3>结合性</SPAN></A><BR>现在有了 <I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">N&gt;1</I> 个模式，模式实现之间的交互如何呢？如果对象可以很好地协作，则称为<I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">可结合的</I>。类似地，模式实现可能直接冲突（比如两者需要不同的超类）、并存但不交互，或者并存且以或多或少富有成效的方式进行交互。</P>
<P>在 JUnit 中，装置关注点和结果收集关注点的相互作用形成了 <CODE>TestCase</CODE> 和 <CODE>TestResult</CODE> 共享的调用顺序协议，如下所示：</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
Test.runTest(TestResult) calls...
  TestResult.run(TestCase) calls...
    TestResult.runProtected(Test, Protectable) calls...
      Protectable.protect() calls...
        TestCase.runBare() calls...
          Test.runTest() ...
          (TestCase.runTest() invokes test method...)
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>这表明模式密集使得代码很难修改。如果要修改装置模板方法或者收集参数，就必须在 <CODE>TestResult</CODE> 或 <CODE>TestCase</CODE> （或者子类）中同时修改二者。另外，因为测试装置的 <CODE>setUp()</CODE> 和 <CODE>cleanUp()</CODE> 方法在结果处理（result handling）的受保护上下文中运行，该调用序列包含了设计决策：装置代码中抛出的任何异常都视作测试错误。如果希望单独报告装置错误，那么不但要同时修改两个组件，还必须修改它们相互调用的方式。AspectJ 能否做得更好一点呢？</P>
<P>在 AspectJ 中，可以使用通知提供同样的保证但避免了锁定调用的顺序： </P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
/** Record test start and end, failure or error */
void around(): testCase() {
  startTest(thisJoinPoint);
  try {
    proceed();
    endTest(thisJoinPoint);
  } catch (Error e) {
    error(thisJoinPoint, e);
  } catch (Exception e) {
    failure(thisJoinPoint, e);
  }
}
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>与上述的装置处理通知一样，这可以用于任何类型的测试或者结果收集，但实现该方法需要向下类型转换。这一点将在后面进行修正。那么该通知如何与装置通知交互呢？这依赖于首先运行的是什么。</P>
<P><A name=IDA13XW><SPAN class=atitle3>谁先开始？</SPAN></A><BR>在 JUnit 中，结果收集和装置管理的模板方法必须（永远？）按照固定的调用顺序。在 AspectJ 中，大量通知可以在一个连接点上运行，而无需知道该连接点上的其他通知。如果不需要交互，那么可以（应该）忽略它们运行的顺序。但是，如果知道其中一个可能影响另一个，则可使用优先级控制运行的顺序。本例中，如果赋予结果处理通知更高的优先级，那么连接点在运行的时候，结果处理通知就会在装置处理通知之前运行，可以调用 <CODE>proceed(..)</CODE> 来运行后者，最后再收回控制权。下面是运行时的顺序：</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
# start running the join point
start result-handling around advice; proceed(..) invokes.. 
  start fixture-handling around advice; proceed(..) invokes.. 
    run underlying test case join point
  finish fixture-handling around advice
finish result-handling around advice
# finish running the join point
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>
<TABLE cellSpacing=0 cellPadding=5 width="30%" align=right border=1>
<TBODY>
<TR>
<TD background=/developerworks/cn/i/bg-gold.gif>
<P><A name=sidebar2><B>和连接点对话</B></A><BR>至于连接点是如何运行的，可以把它看作一个程序栈（但没有栈框架）。（整个）连接点在第一个通知启动之前启动，最后一个通知结束之后终止。“底层”或者“原始”的连接点就是接受通知的代码；它可能还运行其他（嵌套的）连接点。通知按照优先级顺序在底层连接点之前和之后运行。当 <I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">around</I> 通知调用 <CODE>proceed(..)</CODE> 时，“继续执行连接点”调用所有优先级较低的通知和底层连接点。如果切入点当时不匹配（比如禁用了日志功能），那么可能不运行某些通知。因此，如果开发人员说“连接点运行……”，他们说的是整个连接点、通知，等等（即使因为切入点不匹配、没有调用 <CODE>proceed(..)</CODE> 方法或者抛出了异常，造成通知或者底层连接点不运行）。</P></TD></TR></TBODY></TABLE></P>
<P>如果需要，可以显式控制两个通知的优先级，不论通知是否在相同或不同的方面中，甚至是来自其他方面。在这里因为顺序决定了装置错误是否作为测试错误报告的设计决策，可能希望显式设置优先级。我也可以使用单独的方面声明装置错误的处理策略：</P>
<TABLE cellSpacing=0 cellPadding=5 width=450 bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
aspect ReportingFixtureErrors {
  // fixture errors reported by result-handling 
  declare precedence: ResultHandling+, FixtureHandling+;
}
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>这两个 <CODE>Handling</CODE> 方面不需要知道对方的存在，而两个 JUnit 类 <CODE>TestResult</CODE> 与 <CODE>TestCase</CODE>，必须就谁首先运行命令达成一致。如果以后要改变这种设计，只需要修改 <CODE>ReportingFixtureErrors</CODE> 即可。 </P>
<P><A name=IDAU5XW><SPAN class=atitle3>Collecting Parameter 的可用性</SPAN></A><BR>多数 JUnit 测试开发人员都不直接使用 <CODE>TestResult</CODE>，就是说在调用链的每个方法中要作为参数来传递它，Gamma 和 Beck 称之为“签名污染”。相反，他们提供了 JUnit 断言来通知失效或者展开测试。 </P>
<P><CODE>TestCase</CODE> 扩展了 <CODE>Assert</CODE>，后者定义了一些有用的 <CODE>static assert{something}(..)</CODE> 方法，以检查和记录失效。如果断言失败，那么这些方法将抛出 <CODE>AssertionFailedError</CODE>，<CODE>TestResult</CODE> 在结果处理装置模板方法中捕获这些异常并进行解释。这样，JUnit 就巧妙地回避了 API 用户来回传递收集参数的关注点，让用户忘掉了 <CODE>TestResult</CODE> 的要求。JUnit 将结果报告关注点和验证与日志服务捆绑在了一起。</P>
<P><A name=IDA1AYW><SPAN class=atitle3>捆绑</SPAN></A><BR>捆绑使用户更难于选择需要的服务。可以使用 <CODE>Assert.assert{something}(..)</CODE> 将 <CODE>TestCase</CODE> 绑到 <CODE>TestResult</CODE> 上，进一步限制收集参数的灵活性。这样对测试增加了失效实时处理（fast-fail）语义， 即使有些测试可能希望在确认失效后继续执行。为了直接报告结果， JUnit 测试可以实现 <CODE>Test</CODE>，但这样就失去了 <CODE>TestCase</CODE> 的其他特性（可插接的选择器、装置处理、重新运行测试用例等）。</P>
<P>这是模式密集的另一个代价：API 用户常常被迫接受或者拒绝整个包。另外，虽然将问题捆绑到一起可能比较方便，但有时候会降低可用性。比如，很多类或方法常量首先作为 JUnit 断言写入，如果不自动触发异常这些常量，则可以在产品诊断中重复使用它们。</P>
<P>如上所述，AspectJ 可以支持 JUnit 断言风格的结果处理，但能否在支持希望得到直接结果收集的灵活性的 API 用户的同时，又单独决定何时展开测试呢？甚至允许用户定义自己的结果收集器报告中间结果？我认为能够做到。这一种解决方案包括四部分：(1) 支持结果收集器的工厂；(2)组件在不污染方法签名的情况下使用结果收集器；(3) 可以在直接报告给结果收集器后展开测试；(4) 保证正确报告抛出的异常。撰写 Cook's Tour 的时候这些还很难做到这些，但是现在有了新的 Java API 和 AspectJ，所以这一切都变得很容易。</P>
<P><A name=IDAYBYW><SPAN class=atitle3>ThreadLocal 收集器</SPAN></A><BR>为了让所有组件都能使用结果收集器和实现工厂，我使用了一个公共静态方法来获得线程本地（thread-local）结果收集器。下面是 <CODE>TestContext</CODE> 结果收集器的框架： </P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
public class TestContext {
  static final ThreadLocal<TESTCONTEXT> TEST_CONTEXT 
    = new ThreadLocal<TESTCONTEXT>();

  /** Clients call this to get test context */
  public static TestContext getTestContext(Object test) { 
    ...     
  }

  ...
}    
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>方法 <CODE>getTestContext(Object test)</CODE> 可支持结果收集器和测试之间的不同联系（每个测试、每个套件、每个线程、每个 VM），但 <CODE>TestContext</CODE> 的子类型需要向下强制转换，不支持其他类型。</P>
<P><A name=IDARCYW><SPAN class=atitle3>展开测试</SPAN></A><BR>抛出异常不仅要展开测试，还将报告错误。如果测试客户机直接使用 <CODE>getTestContext(..)</CODE> 通知错误，那么需要展开测试而不是报告更多的错误。为此，需要声明一个专门的异常类，指出已经告知结果。API 契约方式需要定义抛出异常的客户机和捕捉异常的装置都需要知道的类。为了向客户机隐藏类型细节，可以像下面这样声明一个返回用户抛出的异常的方法：</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
public class TestContext {
  ...
  public Error safeUnwind() { 
    return new ResultReported();
  }

  private static class ResultReported extends Error {}
}
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>然后测试抛出 <CODE>TestContext</CODE> 定义的所有异常： </P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
  public void testClient() { 
    ...
    TestContext tc = TestContext.getTestContext(this);
    tc.addFailure(..);
    ..
    throw tc.safeUnwind(); // could be any Error
  }
}
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>这样就把测试和 <CODE>TestContext</CODE> 绑定到了一起，但是 <CODE>safeUnwind()</CODE> 仅供那些进行自己的结果报告的测试使用。</P>
<P><A name=IDAUDYW><SPAN class=atitle3>保证异常被报告</SPAN></A><BR>下面是为 <CODE>TestContext</CODE> 收集结果的通知。这个通知具有足够的通用性，可用于不同的测试用例和不同的 <CODE>TestContext</CODE> 子类型： </P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
/** Record for each test start and end or exception */
void around() : testCase() {
  ITest test = wrap(getTest(thisJoinPoint));          
  TestContext testContext = TestContext.getTestContext(test); 
  testContext.startTest(test);
  try {
    proceed();
    testContext.endTest(test);
  } catch (ResultReported thrown)  {
    testContext.checkReported(test);
  } catch (Error thrown) { 
    testContext.testError(test, null, thrown);
  } catch (Throwable thrown) {
    testContext.testFailure(test, null, thrown);
  }
}

protected abstract Object getTest(JoinPoint jp);
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>因为该通知加强了 <CODE>TestContext</CODE> 的不变性，所以我把这个方面嵌套在 <CODE>TestContext</CODE> 中。为了让装置开发人员指定不同的测试用例，切入点和方法都是抽象的。比如，下面将其用于 <CODE>TestCase</CODE>： </P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
aspect ManagingJUnitContext 
  extends TestContext.ManagingTestResults {
    
  public pointcut testCase() : within(testing.junit..*) 
    &amp;&amp; execution(public !static void TestCase+.test*());

  protected Object getTest(JoinPoint jp) {
    assert jp.getTarget() instanceof TestCase;
    return jp.getTarget();
  }
}
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>我在一个重要的地方限制了这一解决方案：<I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">around</I> 通知声明它返回 <I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">void</I>。如果我声明该通知返回 <CODE>Object</CODE>，就可以在任何连接点上使用该通知。但是因为要捕获异常需要正常返回，我还需要知道返回的是什么 <CODE>Object</CODE>。我可以返回 <I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">null</I> 然后等待好消息，但我更愿意向任何子方面表明该问题，而不是等它在运行时抛出 <CODE>NullPointerException</CODE>。</P>
<P>虽然声明 <CODE>void</CODE> 限制了 <CODE>testCase()</CODE> 切入点的应用范围，但是这样降低了复杂性，增强了安全性。 AspectJ 中的通知具有和 Java 语言中的方法相同的类型安全和异常检查。通知可以声明它抛出了一个经过检查的异常，如果切入点选择了不抛出异常的连接点，那么 AspectJ 将报告错误。类似地，<I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">around</I> 通知可以声明一个返回值（（上面的“void”），要求所有链接点具有同样的返回值。最后，如果通过绑定具体的类型来避免向下类型转换（比如使用 <CODE>this(..)</CODE>，参见后述），那么就必须能够在连接点上找到这种类型。这些限制保证了 AspectJ 通知和 Java 方法具有同样的构建时安全性（不同于基于反射或代理的 AOP 方法）。 </P>
<P>有了这些限制，就可以同时支持有客户机控制的和没有客户机控制这两种情况下的结果收集，不必依赖客户机来加强不变性。无论对于新的客户机类型、新的结果收集器类型，还是和 <CODE>TestContext</CODE> 类及其子类型的何种交互，这种解决方案都是可扩展的。 </P>
<P><A name=IDAFGYW><SPAN class=atitle2>Adapter、Pluggable Selector 还是配置？</SPAN></A><BR>Cook's Tour 提出用 <CODE>Pluggable Selector</CODE> 作为由于为每个新测试用例创建子类造成的“类膨胀”的解决方案。如作者所述：</P>
<BLOCKQUOTE xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">想法是使用一个可参数化的类执行不同的逻辑，不需要子类化……Pluggable Selector 在实例变量中保存一个……方法选择器。 </BLOCKQUOTE>
<P>于是，<CODE>TestCase</CODE> 担负了使用 Pluggable Selector 模式将 <CODE>Test.run(TestResult)</CODE> 转化成 <CODE>TestCase.test...()</CODE> 的 <I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Adapter</I> 角色，可以用 name 字段作为方法选择器。<CODE>TestCase.runTest()</CODE> 方法反射调用和 name 字段对应的方法。这种约定使得开发人员通过添加方法就能增加测试用例。 </P>
<P>这样方便了 JUnit 测试开发人员，但是增加了装置开发人员修改和扩展的难度，为了适应 <CODE>runTest()</CODE>，构造函数 <CODE>TestCase(String name)</CODE> 的参数必须是不带参数的公共实例方法的名称。结果，<CODE>TestSuite</CODE> 实现了该协议，因此如果需要修改 <CODE>TestCase.runTest()</CODE> 中的反射调用，就必须修改 <CODE>TestSuite.addTestSuite(Class)</CODE>，反之亦然。要基于 <CODE>TestCase</CODE> 创建数据驱动或规格驱动的测试，就必须为每种配置创建单独的套件，在套件名中包含配置，用 <CODE>TestSuite</CODE> 定义后配置每个测试。 </P>
<P><A name=IDAGIYW><SPAN class=atitle3>配置连接点</SPAN></A><BR>AspectJ 能否更进一步出来测试，而不仅仅是选择处理测试配置呢？在一个连接点上配置测试有两种方法。</P>
<P>首先，可以通过改变连接点上的上下文来直接配置连接点，如方法参数或者执行对象本身。执行 <CODE>main(String[])</CODE> 方法的一个简单例子是用不同的 <CODE>String[]</CODE> 数组生成一些测试，并反复运行连接点。稍微复杂一点的，可以结合使用连接点上两类不同的变量。下面的通知将检查测试能否在所有彩色和单色打印机上工作：</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
void around(Printer printer) : testCase() &amp;&amp; context(printer) {
  // for all known printers...
  for (Printer p : Printer.findPrinters()) {
    // try both mono and color...
    p.setMode(Printer.MONOCHROME);
    proceed(p);
    p.setMode(Printer.COLOR);
    proceed(p);
  }
  // also try the original printer, in mono and color
  printer.setMode(Printer.MONOCHROME);
  proceed(printer);
  printer.setMode(Printer.COLOR);
  proceed(printer);
}
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>虽然这段代码是针对 <CODE>Printer</CODE> 的，但无论测试的是打印还是初始化，无论 <CODE>Printer</CODE> 是方法调用的目标还是方法参数，都没有关系。因此即使通知要求某种具体的类型，这或多或少与引用来自何处是无关的；这里通知将连接点和如何获得上下文都委派给了定义切入点的子方面。 </P>
<P>配置测试的第二种方法（更常用）是对测试组件使用 API。<CODE>Printer</CODE> 的例子说明了如何明确设置模式。为了更一般化，可以支持泛化的适配器接口 <CODE>IConfigurable</CODE>，如下所示：</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
public abstract aspect Configuration {

  protected abstract pointcut configuring(IConfigurable s);

  public interface IConfigurable {
    Iterator getConfigurations();
    void configure(Object input);
  }

  void around(IConfigurable me) : configuring(me) {
    Iterator iter = me.getConfigurations();
    while (iter.hasNext()){
      me.configure(iter.next());
      proceed(me);
    }
  }
}
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>该通知只能用于某些上下文是 <CODE>IConfigurable</CODE> 的情况，但是如果能运行，那么可以运行底层连接点多次。</P>
<P>如何与连接点上的其他测试类型、其他通知、运行该连接点的其他代码交互呢？对于测试而言，如果测试不是 <CODE>IConfigurable</CODE> 的，那么该通知将不运行。这里没有矛盾。 </P>
<P>对于其他通知，假设将 <CODE>configuring()</CODE> 定义为 <CODE>testCase()</CODE> 并包括其他的通知，因为这样可以高效地创建很多测试，结果和装置通知都应该有更低的优先级，以便能够管理和报告不同的配置与结果。此外，配置应该以某种形式包含在结果收集器用来报告结果的测试标识中；这是那些知道测试可配置、可标识的组件的职责（下面一节还将进一步讨论这些组件）。</P>
<P>对于运行连接点的代码，与通常的 <I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">around</I> 通知不同的是，它对每个配置都调用 <CODE>proceed(..)</CODE> 一次，因此底层连接点可运行多次。在这里通知应该返回什么结果呢？与结果处理通知一样，我惟一能确定的是 <CODE>void</CODE>，因此，我限制该通知返回 <CODE>void</CODE>，并把这个问题交给编写切入点的测试开发人员。</P>
<P><A name=IDA0KYW><SPAN class=atitle3>各取所需</SPAN></A><BR>假设我是一位装置开发人员，需要调整来适应新的测试，如果必须在测试类中实现 <CODE>IConfigurable</CODE>，那么 看起来似乎不得不增加测试的“模式密集”。为了避免这种情况，可以在 AspectJ 中声明其他类型的成员或者父类，包括接口的默认实现，只要所有定义保持二进制兼容即可。使用内部类型声明增加了通知的类型安全，从而更容易避免从 Object 的向下类型转换。</P>
<P>是不是像其他成员那样增加了目标类型的复杂性呢？其他类型的公共成员声明是可见的，因此在理论上可能增加目标类型的复杂性。但是，也可以将这些成员声明为某个方面私有的其他类型，因此，只有这个方面才能使用它们。这样就可以装配组合对象，而不会造成把所有成员在类中声明可能造成的一般冲突和交互。 </P>
<P>下面的代码给出了一个例子，用 <CODE>init(String)</CODE> 方法使 <CODE>Run</CODE> 适应于 <CODE>IConfigurable</CODE>： </P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
public class Run {

  public void walk() { ... }

  public void init(String arg) { ... }
}


public aspect RunConfiguration extends Configuration {

  protected pointcut configuring(IConfigurable s) : 
    execution(void Run+.walk()) &amp;&amp; target(s);
    
  declare parents : Run implements IConfigurable;

  /** Implement IConfigurable.getConfigurations() */
  public Iterator Run.getConfigurations() {
    Object[] configs = mockConfigurations();
    return Arrays.asList(configs).iterator();
  }

  /** Implement IConfigurable.configure(Object next) */
  public void Run.configure(Object config) {
    // hmm - downcast from mockConfigurations() element
    String[] inputs = (String[]) config; 
    for (String input: inputs) {
      init(input);
    }
  }

  static String[][] mockConfigurations() {
      return new String[][] { {"one", "two"}, {"three", "four"}};
  }
}
</CODE></PRE></TD></TR></TBODY></TABLE>
<P><A name=IDA0LYW><SPAN class=atitle3>测试标识符</SPAN></A><BR>测试标识符可由结果报告、选择或配置以及底层的测试本身共享。在一些系统中，只需要告诉用户哪些测试正在运行即可；在另外一些系统中，需要一个惟一的、一致的键来说明那些失败的测试获得通过（bug 修正），哪些通过的测试失败了（回归）。JUnit 仅提供了一种表示，它绕过了共享的需要，使用 <CODE>String Object.toString()</CODE> 来获得 String 表示。AspectJ 装置也可作同样的假设，但是也可用上面所述的 <CODE>IConfigurable</CODE> 来补充测试，根据系统需要为给定类型的测试计算和存储标识符。“相同的”测试可以根据需要来配置不同的标识符（比如，用于诊断和回归测试的标识符），这减少了 Java 语言中模式密集可能造成的冲突。虽然配置对于方面和配置的组件是本地的（从而可以是私有的），对于很多关注点，标识符都可以是可见的，所以可以用公共接口表示它。</P>
<P><A name=IDAJMYW><SPAN class=atitle2>使用组合还是使用递归？</SPAN></A><BR>Cook's Tour 认识到装置必须运行大量的测试——“一套一套的测试”。Composite 模式可以很好地满足这种要求：</P>
<BLOCKQUOTE xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">该模式的目的是，“把对象组合到树状结构中，以表示部分-整体关系。组合使客户机能够统一地看待单个对象和对象的组合。”<BR><BR>Composite 模式引入了三个参与方：Component、Composite 与 Leaf。Component 声明了我们希望用来与测试交互的接口。Composite 实现了该接口，并维护一个测试集合。Leaf 表示 Composite 中的测试用例，该用例符合 Component 接口。 </BLOCKQUOTE>
<P>这就形成了 JUnit 设计环，因为 <CODE>Test.runTest(..)</CODE> Command 接口是 Leaf <CODE>TestCase</CODE> Composite <CODE>TestSuite</CODE> 实现的 Component 接口。 </P>
<P><A name=IDACNYW><SPAN class=atitle3>可维护性</SPAN></A><BR>Cook's Tour 支出，“应用 Composite 时，我们首先想到的是应用它是多么复杂。”该模式中，节点和叶子的角色被添加到已有的组件上，并且它们都需要知道自己在实现组件接口时的职责。它们之间定义了调用协议，并由节点实现，节点也包含子节点。这意味着节点知道子节点，同时装置也知道节点。</P>
<P>在 JUnit 中，<CODE>TestSuite</CODE>（已经）非常了解 <CODE>TestCase</CODE>，JUnit 测试运行者假设要通过加载 suite 类来生成一个套件。从配置中可以看到，支持可配置的测试需要管理测试套件的生成。组合增加了模式密集。 </P>
<P>Composite 模式在 AspectJ 中可使用内部类型声明实现，如上面关于配置的一节所述。在 AspectJ 中，所有成员都是在一个方面中声明的，而不是分散在已有的类中。这样更容易发现角色是否被已有类的关注点污染了，在查看实现的时候也更容易了解这是一个模式（而不仅仅是类的另一个成员）。最后，组合是可用抽象方面实现的模式之一，可以使用标签接口来规定担任该角色的类。这意味着可以编写可重用的模式实现。（关于设计模式的 AspectJ 实现的更多信息，请参阅 Nicholas Lesiecki 所撰写的“Enhance design patterns with AspectJ”，参见 <A href="http://www-128.ibm.com/developerworks/cn/java/j-aopwork7/#resources" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">参考资料</A>。）</P>
<P><A name=IDAYNYW><SPAN class=atitle3>递归</SPAN></A><BR>AspectJ 能否不借助 Composite 模式而满足原来的需要呢？AspectJ 提供了运行多个测试的很多方法。上面关于配置的例子是一种方法：把一组子测试和一个测试关联，使用通知在切入点 <CODE>recursing()</CODE> 选择的连接点上递归运行各个成分。该切入点规定了应该递归的组合操作： </P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
// in abstract aspect AComposite

/** tag interface for subaspects to declare */
public interface IComposite {}

/** pointcut for subaspects to declare */
protected abstract pointcut recursing(IComposite c);

/** composites have children */
public ArrayList<ICOMPOSITE> IComposite.children 
    = new ArrayList<ICOMPOSITE>();

/** when recursing, go through all subtree targets */
void around(IComposite c) : recursing(c)  {
  // recurse...
}
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>下面说明了如何将该方面应用于 <CODE>Run</CODE>：</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
public aspect CompositeRun extends AComposite {
  declare parents : Run implements IComposite;
  
  public pointcut recursing(IComposite c) : 
    execution(void Run+.walk()) &amp;&amp; target(c);
}
</CODE></PRE></TD></TR></TBODY></TABLE>
<P><A name=IDAUOYW><SPAN class=atitle3>将连接点封装为对象</SPAN></A><BR>在连接点上递归？这就是有趣的地方。在 AspectJ <I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">around</I> 通知中，可以使用 <CODE>proceed(..)</CODE> 运行连接点的其他部分。为了实现递归，可以通过将 <CODE>proceed(..)</CODE> 调用封装在匿名类中来隐藏连接点的其他部分。为了在递归方法中传递，匿名类应该扩展方法已知的包装器类型。比如，下面定义了 <CODE>IClosure</CODE> 包装器接口，将 <CODE>proceed(..)</CODE> 包装到<I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> around </I>通知中，并把结果传递给 <CODE>recurse(..)</CODE> 方法： </P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
// in aspect AComposite...


/** used only when recursing here */
public interface IClosure {
    public void runNext(IComposite next);
}

/** when recursing, go through all subtree targets */
void around(IComposite c) : recursing(c)  {
  recurseTop(c, new IClosure() {
    // define a closure to invoke below
    public void runNext(IComposite next) { 
      proceed(next); 
    }});
}

/** For clients to find top of recursion. */
void recurseTop(IComposite targ, IClosure closure) {
    recurse(targ, closure);
}

/** Invoke targ or recurse through targ's children. */
void recurse(IComposite targ, IClosure closure) {
  List children 
    = (null == targ?null:targ.children);
  if ((null == children) || children.isEmpty()) {
    // assume no children means leaf to run
    closure.runNext(targ);
  } else {
    // assume children mean not a leaf to run
    for (Object next: children) {
      recurse((IComposite) next, closure);
    }        
  }
}
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>使用 <CODE>IClosure</CODE> 可以结合 Command 模式和使用 <CODE>proceed(..)</CODE> 的通知的优点。与 Command 类似，它也可以用新规定的参数在运行或重新运行中传递。与 <CODE>proceed(..)</CODE> 类似，它隐藏了连接点中其他上下文、其他低优先级通知和底层连接本身的细节。它和连接点一样通用，比通知更安全（因为上下文更加隐蔽），并且和 Command 一样可以重用。因为对目标类型没有要求，所以，与 Command 相比，IClosure 的结合性更好。 </P>
<P>如果逐渐习惯于封闭 <CODE>proceed(..)</CODE>，不必感到奇怪，对许多 Java 开发人员来说，这仅仅是一种很常见的怪事。如果在连接点完成之后调用 <CODE>IClosure</CODE> 对象，<I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">那么结果可能有所不同</I>。 </P>
<P><A name=IDAWQYW><SPAN class=atitle3>可用性</SPAN></A><BR><CODE>RunComposite</CODE> 方面将这种组合解决方案应用于 <CODE>Run</CODE> 类，只需要用 <CODE>IComposite</CODE> 接口标记该类，并定义 <CODE>recursing()</CODE> 切入点即可。但是，为了将组件安装到树中，需要添加子类，这意味着某个组装器组件必须知道 <CODE>Run</CODE> 是带有子类的 <CODE>IComposite</CODE>。下面显示了组件以及它们之间的关系： </P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
Assembler, knows about...
  Run component, and
  CompositeRun concrete aspect, who knows about...
    Run component, and
    AComposite abstract aspect
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>您可能希望让 <CODE>CompositeRun</CODE> 方面也负责发现每次运行的子类（就像带配置的组合那样），但使用单独的装配器意味着不必将 <CODE>Run</CODE> 组合（对于所有运行都是一样的）与 <CODE>Run</CODE> 组合的特定应用（随着联系子类和特定 <CODE>Run</CODE> 子类的方式不同而变）搅在一起。面向对象依赖性的规则依赖于稳定性的方向，特别是，（变化更多的）具体的元素应该取决于是否要完全依赖于（更稳定的）抽象成分。按照这一原则，上面的依赖性似乎不错。</P>
<P><A name=IDAKSYW><SPAN class=atitle3>结合性</SPAN></A><BR>与配置一样，组合通知（应用于测试用例时）应该优先于装置和结果报告。如果配置影响到测试的确认，那么组合也应该优先于配置。按照这些约束，可得到下面的顺序：</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
Composition      # recursion
  Configuration  # defining test, identity
    Context      # reporting results
      Fixture    # managing test data
        test     # underlying test
</CODE></PRE></TD></TR></TBODY></TABLE>
<P><A name=pointcut><SPAN class=atitle2>作为设计抽象的切入点</SPAN></A><BR>上面就是我对 JUnit Cook's Tour 的评述。我所讨论的所有面向方面的设计解决方案都可在本文的代码压缩包中找到。这些解决方案具有以下特点：</P>
<UL xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<LI>依赖于切入点而不是类型，要么不作任何假定，要么将上下文规格推迟到具体的子方面中。 
<LI>都是独立的，可单独使用。 
<LI>可以在同一系统中多次重用。 
<LI>可以共同工作，有时候需要定义它们的相对优先级。 
<LI>不需要修改客户机部分。 
<LI>与 JUnit 相比，可做的工作更多，需要客户机的干预也更少。</LI></UL>
<P>对于给定的 Java 模式，AspectJ 提供了完成同一任务的多种方式，有时候是一个简单的短语。这里采用了在可重用解决方案中使用切入点和做最少假定的方法，这些主要是为了说明 AspectJ 如何通过封装通知和切入点来减少交互，从而很容易在连接点上改变行为。有时候，可以使用具体的（非重用的）方面，将特性组合到一个方面中；或者使用内部类型声明来实现对应的 Java 模式可能更清楚。但是这些解决方案示范了最大限度地减少一个连接点上的交互的技术，从而使将切入点用作一流设计抽象变得更简单。 </P>
<P>切入点仅仅是减少重重假设的设计方法的第一步。应在可能不需要对象的地方真正利用切入点。如果对象是必需的，那么应该尝试在方面中使用内部类型声明来组合对象，从而使不同的（模式）角色保持区别，即使在同一个类中定义也是如此。与面向对象编程一样，应避免不同的组件了解对方。如果必须彼此了解，比较具体的一方应该知道抽象的一方，装配器应该知道各个部分。如果彼此都要知道，那么这种关系应该尽量简练、明确、稳定和可实施的。</P>
<P><A name=full-speed><SPAN class=atitle2>全速 AOP</SPAN></A><BR>AspectJ 1.0 是三年前发布的。多数开发人员都看过并尝试了 AspectJ 的入门应用，即模块化跟踪这样的横切关注点。但是有些开发人员更进一步，尝试进行我所说的“全速 AOP”：</P>
<UL xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<LI>设计失败和设计成功一样平常。 
<LI>重用（或者可重用）切入点这样的横切规格。 
<LI>方面可能有很多互相依赖的成分。 
<LI>方面用于倒置依赖和解耦代码。 
<LI>方面用于连接组件或子系统。 
<LI>方面打包成可重用的二进制库。 
<LI>系统中有很多方面。一些对另一些无关紧要，但还有一些则依赖于另一些。 
<LI>虽然方面可能是不可插接的，但是插入后可以增加基本功能或者结构。 
<LI>可以重构库代码创建更好的连接点模型。</LI></UL>
<P>是什么让一些开发人员裹足不前呢？在最初听说 AOP 或者学习基础知识后，似乎进入了一个平台阶段。比如进入了这样的思维陷阱：</P>
<BLOCKQUOTE xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">AOP 模块化了横切关注点，因此我要在代码中寻找横切关注点。我找到了所有需要的跟踪、同步等关注点，因此不再需要做其他事了。 </BLOCKQUOTE>
<P>这个陷阱就像在面向对象编程初期单纯按照“is-a”和“has-a”思考一样。寻找单个的关注点（即使是横切关注点），就丢失了关系和协议，在规范化为模式时，关系和协议是编码实践的支柱。 </P>
<P>另一种思维陷阱是：</P>
<BLOCKQUOTE xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">AOP 模块化横切关注点。因此应该寻找那些分散和纠缠在代码中的代码。这些代码似乎都很好的本地化了，因此不需要 AOP。 </BLOCKQUOTE>
<P>虽然分散和纠缠可能是非模块化横切关注点的标志，AOP 除了收集分散的代码或者纠缠在一起的复杂方法或对象之外，还有很多用处。 </P>
<P>最后，最难以避开的思维陷阱是： </P>
<BLOCKQUOTE xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">AOP 用新的语言设施补充了面向对象编程，因此应该用于解决面向对象编程不能解决的关注点。面向对象编程解决了所有关注点，因此我不需要 AOP。</BLOCKQUOTE>
<P>本文中没有讨论横切关注点，我重新实现的多数解决方案照目前来看都是经过很好模块化的。我给出的代码并非完全成功的（特别是与 JUnit 比较），但给出这些代码的目的并不仅仅是说明它们能够做到或者证明代码能更好地本地化，而在于提出面向对象开发人员是否必须忍受此类设计权衡的问题。我相信，如果在实现主要目标的同时能够不放弃次要目标，那么就可以避免编写难以使用或修改的代码。</P>
<P><A name=IDA2TYW><SPAN class=atitle2>结束语</SPAN></A><BR>重温“JUnit: A Cook's Tour”，更好地理解 AspectJ 减少和控制连接点交互的方法，这是在设计中有效使用切入点的关键。模式密集可能导致成熟的面向对象框架难以修改，但这是面向对象开发人员设计系统的方法所带来的自然结果。本文提供的解决方案，即用切入点代替对象，尽可能地避免了交互或者最大限度地减少了交互，避免了 JUnit 的不灵活性，本文还展示了您如何能够在自己的设计中做到这一点。通过避免开发人员已经逐渐认可的设计权衡，这些解决方案表明，即使您认为代码已经被很好地模块化了，AOP 仍然很有用。希望本文能鼓励您在更多的应用程序中全面使用 AOP。</P>
<P><A name=resources><SPAN class=atitle2>参考资料 </SPAN></A>
<UL>
<LI>您可以参阅本文在 developerWorks 全球站点上的 <A href="http://www-128.ibm.com/developerworks/java/library/j-aopwork7/" target=_blank xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">英文原文</A>。<BR><BR>
<LI>单击本文顶端或底端的 <B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">代码</B> 图标（或者参阅 <A href="http://www-128.ibm.com/developerworks/cn/java/j-aopwork7/#download" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">下载</A>），下载本文使用的源代码。<BR><BR>
<LI><I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">AOP@Work</I> 是为期一年的一个系列，目的是帮助读者将 AOP 纳入到日常的 Java 编程中。不要错过本系列的任何一篇文章。请参阅 <A href="http://www-128.ibm.com/developerworks/cn/views/java/articles.jsp?view_by=search&amp;search_by=AOP%40Work%3A" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">完整的系列清单</A>。<BR><BR>
<LI>本文从面向方面的角度分析了 Erich Gamma 和 Kent Beck 合著的“<A href="http://junit.sourceforge.net/doc/cookstour/cookstour.htm" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">JUnit: A Cook's Tour</A>”（<I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Java Report</I>，1999 年 5 月）。<BR><BR>
<LI>Erich Gamma 和 Kent Beck 的“<A href="http://junit.sourceforge.net/doc/testinfected/testing.htm" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">JUnit Test Infected: Programmers Love Writing Tests</A>”（<I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Java Report</I>，1998 年 7 月）提到了作者早期撰写的关于用 AspectJ 测试的一篇文章“<A href="http://www.sdmagazine.com/documents/s=7134/sdm0205b/0205b.htm" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Get Test Inoculated!</A>”（最初的标题为“Test-Inoculated: Programmers Love Not Writing Tests”，<I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">SD Magazine</I>，2002 年 5 月）。 <BR><BR>
<LI>Nicholas Lesiecki 向 developerWorks 读者介绍了如何用 AspectJ 进行单元测试，“<A href="http://www-128.ibm.com/developerworks/cn/java/j-aspectj2/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">AspectJ 和模仿对象的测试灵活性</A>”（developerWorks，2002 年 5 月）。<BR><BR>
<LI>在 <I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">AOP@Work</I> 系列第三期“<A href="http://www-128.ibm.com/developerworks/cn/java/j-aopwork5/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">http://www-128.ibm.com/developerworks/cn/java/j-aopwork5/</A>”（developerWorks，2005 年 3 月）中，Nick 也讨论了 Java 语言设计模式的 AspectJ 实现。<BR><BR>
<LI>Tony Morris 在 “<A href="http://www-128.ibm.com/developerworks/cn/java/j-unitx/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">JUnit 断言扩展</A>”（developerWorks，2005 年 3 月）中提供了易用的高级 JUnit 断言。<BR><BR>
<LI>Jan Hannemman 和 Gregor Kiczales 在 AspectJ 中实现了面向对象设计模式，他们发现，无论是否增加模式角色，都可得到模块化方面的改进，请参阅“<A href="http://www.cs.ubc.ca/~jan/AODPs/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Aspect-Oriented Design Pattern Implementations</A>”（University of British Columbia，2004 年 4 月）。<BR><BR>
<LI>Bertrand Meyer 发表了受到普遍认可的模块化标准。现在使用 Google 搜索“<A href="http://www.google.com/search?q=Bertrand+Meyer+modularity" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Bertrand Meyer + modularity</A>”能得到 4,050 个结果。<BR><BR>
<LI>在 developerWorks 的 <A href="http://www.ibm.com/developerworks/cn/java/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Java 技术专区</A>中可以找到关于 Java 编程各个方面的文章。<BR><BR>
<LI>在 <A href="http://devworks.krcinfo.com/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Developer Bookstore</A> 中可以找到技术书籍的完整清单，其中包括数百本 <A href="http://devworks.krcinfo.com/WebForms/ProductList.aspx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Java 相关主题</A> 的书籍。 <BR><BR>
<LI>从 <A href="http://www.ibm.com/developerworks/cn/views/java/tutorials.jsp" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Java 技术专区教程页</A> 可找到 <A href="http://www.ibm.com/developerWorks/cn/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">developerWorks</A> Java 教程的完整清单。<BR></LI></UL>
<P></P><A name=download></A><SPAN class=atitle2>下载</SPAN><BR>
<TABLE cellSpacing=0 cellPadding=0 border=0>
<TBODY>
<TR vAlign=top>
<TD width=1 height=8><IMG height=8 alt="" src="http://www.ibm.com/i/c.gif" width=1 border=0></TD></TR></TBODY></TABLE>
<TABLE cellSpacing=0 cellPadding=0 border=0>
<TBODY>
<TR vAlign=top>
<TD class=lgray width=4 height=18><NBSP></NBSP></TD>
<TD class=lgray height=18><B>描述</B></TD>
<TD class=lgray width=8 height=18><NBSP></NBSP></TD>
<TD width=2 height=18><IMG alt="" src="http://www.ibm.com/i/c.gif" width=2 border=0></TD>
<TD class=lgray width=4 height=18><NBSP></NBSP></TD>
<TD class=lgray height=18><B>Name</B></TD>
<TD class=lgray width=8 height=18><NBSP></NBSP></TD>
<TD width=2 height=18><IMG alt="" src="http://www.ibm.com/i/c.gif" width=2 border=0></TD>
<TD class=lgray width=4 height=18><NBSP></NBSP></TD>
<TD class=lgray height=18><B>Size</B></TD>
<TD class=lgray width=8 height=18><NBSP></NBSP></TD>
<TD width=2 height=18><IMG alt="" src="http://www.ibm.com/i/c.gif" width=2 border=0></TD>
<TD class=lgray width=4 height=18><NBSP></NBSP></TD>
<TD class=lgray height=18><B>Download method</B></TD>
<TD class=lgray width=8 height=18><NBSP></NBSP></TD>
<TD width=2 height=18><IMG alt="" src="http://www.ibm.com/i/c.gif" width=2 border=0></TD></TR>
<TR vAlign=top>
<TD width=4 height=18><NBSP></NBSP></TD>
<TD height=18>Source code</TD>
<TD width=8 height=18><NBSP></NBSP></TD>
<TD width=2 height=18><IMG alt="" src="http://www.ibm.com/i/c.gif" width=2 border=0></TD>
<TD width=4 height=18><NBSP></NBSP></TD>
<TD height=18>j-aopwork7code.zip</TD>
<TD width=8 height=18><NBSP></NBSP></TD>
<TD width=2 height=18><IMG alt="" src="http://www.ibm.com/i/c.gif" width=2 border=0></TD>
<TD width=4 height=18><NBSP></NBSP></TD>
<TD height=18>41 KB</TD>
<TD width=8 height=18><NBSP></NBSP></TD>
<TD width=2 height=18><IMG alt="" src="http://www.ibm.com/i/c.gif" width=2 border=0></TD>
<TD width=4 height=18><NBSP></NBSP></TD>
<TD noWrap height=18><A class=fbox href="ftp://www6.software.ibm.com/software/developer/library/j-aopwork7code.zip"><B>FTP</B></A></TD>
<TD width=8 height=18><NBSP></NBSP></TD>
<TD width=2 height=18><IMG alt="" src="http://www.ibm.com/i/c.gif" width=2 border=0></TD></TR>
<TR vAlign=top>
<TD class=lgray height=1><IMG height=1 alt="" src="http://www.ibm.com/i/c.gif" width="100%" border=0></TD>
<TD class=lgray height=1><IMG height=1 alt="" src="http://www.ibm.com/i/c.gif" width="100%" border=0></TD>
<TD class=lgray height=1><IMG height=1 alt="" src="http://www.ibm.com/i/c.gif" width="100%" border=0></TD>
<TD width=2 height=1><IMG height=1 alt="" src="http://www.ibm.com/i/c.gif" width=2 border=0></TD>
<TD class=lgray height=1><IMG height=1 alt="" src="http://www.ibm.com/i/c.gif" width="100%" border=0></TD>
<TD class=lgray height=1><IMG height=1 alt="" src="http://www.ibm.com/i/c.gif" width="100%" border=0></TD>
<TD class=lgray height=1><IMG height=1 alt="" src="http://www.ibm.com/i/c.gif" width="100%" border=0></TD>
<TD width=2 height=1><IMG height=1 alt="" src="http://www.ibm.com/i/c.gif" width=2 border=0></TD>
<TD class=lgray height=1><IMG height=1 alt="" src="http://www.ibm.com/i/c.gif" width="100%" border=0></TD>
<TD class=lgray height=1><IMG height=1 alt="" src="http://www.ibm.com/i/c.gif" width="100%" border=0></TD>
<TD class=lgray height=1><IMG height=1 alt="" src="http://www.ibm.com/i/c.gif" width="100%" border=0></TD>
<TD width=2 height=1><IMG height=1 alt="" src="http://www.ibm.com/i/c.gif" width=2 border=0></TD>
<TD class=lgray height=1><IMG height=1 alt="" src="http://www.ibm.com/i/c.gif" width="100%" border=0></TD>
<TD class=lgray height=1><IMG height=1 alt="" src="http://www.ibm.com/i/c.gif" width="100%" border=0></TD>
<TD class=lgray height=1><IMG height=1 alt="" src="http://www.ibm.com/i/c.gif" width="100%" border=0></TD>
<TD width=2 height=1><IMG height=1 alt="" src="http://www.ibm.com/i/c.gif" width=2 border=0></TD></TR></TBODY></TABLE>
<TABLE cellSpacing=0 cellPadding=0 border=0>
<TBODY>
<TR vAlign=top>
<TD><IMG height=12 alt="" src="http://www.ibm.com/i/c.gif" width=12 border=0></TD></TR>
<TR>
<TD><IMG height=11 alt=* src="http://www-128.ibm.com/developerworks/cn/i/fprtarrow.gif" width=12 border=0><A href="http://www-128.ibm.com/developerworks/cn/whichmethod.html">关于下载方法的信息</A><BR><IMG height=30 alt="" src="http://www.ibm.com/i/c.gif" width=10 border=0></TD></TR></TBODY></TABLE>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD><A name=author1></A><SPAN class=atitle2>关于作者</SPAN><BR>Wes Isberg 是 Eclipse AspectJ 项目的一位顾问和负责人。他曾经参加过 Xerox PARC 的 AspectJ 团队，为 Lutris Technologies 研究开放源代码的 Enhydra J2EE 应用程序服务器，还在 Sun 的 JavaSoft 部门时就从 JDK 1.1.2 开始学习 Java 语言。您可以通过 <A href="mailto:wesisberg@yahoo.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">wesisberg@yahoo.com</A> 与他联系。 </TD></TR></TBODY></TABLE>]]></description>
</item><item>
<title><![CDATA[Spring 系列: Spring 框架简介]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=torrent&amp;id=7953</link>
<author>torrent</author>
<pubDate>2005/8/23 8:32:26</pubDate>
<description><![CDATA[转载自: <A href="http://www-128.ibm.com/developerworks/cn/java/wa-spring1/" target=_blank>http://www-128.ibm.com/developerworks/cn/java/wa-spring1/</A><BR><BR>
<TABLE id=content-table cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR vAlign=top>
<TD width="100%">
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR vAlign=top>
<TD width="100%">
<H1><SPAN style="COLOR: #999999">Spring 系列: </SPAN>Spring 框架简介</H1>
<P id=subtitle><EM>Spring AOP 和 IOC 容器入门</EM></P><IMG class=display-img height=6 alt="" src="http://www.ibm.com/i/c.gif" width=1></TD>
<TD class=no-print width=192><IMG height=18 alt=developerWorks src="http://www-128.ibm.com/developerworks/i/dw.gif" width=192></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR vAlign=top>
<TD width=10><IMG height=1 alt="" src="http://www.ibm.com/i/c.gif" width=10></TD>
<TD width="100%">
<TABLE class=no-print cellSpacing=0 cellPadding=0 width=160 align=right border=0>
<TBODY>
<TR>
<TD width=10><IMG height=1 alt="" src="http://www.ibm.com/i/c.gif" width=10></TD>
<TD>
<TABLE cellSpacing=0 cellPadding=0 width=150 border=0>
<TBODY>
<TR>
<TD class=v14-header-1-small>文档选项</TD></TR></TBODY></TABLE>
<TABLE class=v14-gray-table-border cellSpacing=0 cellPadding=0 border=0>
<TBODY>
<TR>
<TD class=no-padding width=150>
<TABLE cellSpacing=0 cellPadding=0 width=143 border=0><IMG height=1 alt="" src="http://www.ibm.com/i/c.gif" width=8> 
<FORM name=email action=https://www-130.ibm.com/developerworks/secure/email-it.jsp><INPUT type=hidden value="在这由三部分组成的介绍 Spring 框架的系列文章的第一期中，将开始学习如何用 Spring 技术构建轻量级的、强壮的 J2EE 应用程序。" name=body><INPUT type=hidden value="Spring 系列: Spring 框架简介" name=subject><INPUT type=hidden value=cn name=lang>
<SCRIPT language=JavaScript type=text/javascript>
<!--
document.write('<tr valign="top"><td width="8"><img src="//www.ibm.com/i/c.gif" width="8" height="1" alt=""/></td><td width="16"><img src="//www.ibm.com/i/v14/icons/em.gif" height="16" width="16" vspace="3" alt="将此页作为电子邮件发送" /></td><td width="122"><p><a class="smallplainlink" href="javascript:document.email.submit();"><b>将此页作为电子邮件发送</b></a></p></td></tr>');
//-->
</SCRIPT>
 
<TBODY>
<TR vAlign=top>
<TD width=8><IMG height=1 alt="" src="http://www.ibm.com/i/c.gif" width=8></TD>
<TD width=16><IMG height=16 alt=将此页作为电子邮件发送 src="http://www.ibm.com/i/v14/icons/em.gif" width=16 vspace=3></TD>
<TD width=122>
<P><A class=smallplainlink href="javascript:document.email.submit();"><B>将此页作为电子邮件发送</B></A></P></TD></TR><NOSCRIPT><tr valign="top"><td width="8"><img src="//www.ibm.com/i/c.gif" width="8" height="1" alt="" /></td><td width="16"><img src="//www.ibm.com/i/c.gif" height="16" width="16" alt="" /></td><td width="122" class="small"><p><span class="ast">未显示需要 JavaScript 的文档选项</span></p></td></tr></NOSCRIPT></FORM>
<TR vAlign=top>
<TD width=8><IMG height=1 alt="" src="http://www.ibm.com/i/c.gif" width=8></TD>
<TD width=16><IMG height=16 alt="" src="http://www.ibm.com/i/v14/icons/dn.gif" width=16 vspace=3 border=0></TD>
<TD width=122>
<P><A class=smallplainlink href="http://www-128.ibm.com/developerworks/cn/java/wa-spring1/#download"><B>Sample code</B></A></P></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE><BR>
<TABLE cellSpacing=0 cellPadding=0 width=150 border=0>
<TBODY>
<TR>
<TD class=v14-header-1-small>对此页的评价</TD></TR></TBODY></TABLE>
<TABLE class=v14-gray-table-border cellSpacing=0 cellPadding=0 border=0>
<TBODY>
<TR>
<TD class=no-padding width=150>
<TABLE cellSpacing=0 cellPadding=0 width=143 border=0>
<TBODY>
<TR vAlign=top>
<TD width=8><IMG height=1 alt="" src="http://www.ibm.com/i/c.gif" width=8></TD>
<TD><IMG height=16 alt="" src="http://www.ibm.com/i/v14/icons/d_bold.gif" width=16 vspace=3 border=0></TD>
<TD width=125>
<P><A class=smallplainlink href="http://www-128.ibm.com/developerworks/cn/java/wa-spring1/#rate"><B>帮助我们改进这些内容</B></A></P></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE><BR></TD></TR></TBODY></TABLE>
<P>级别: 初级</P>
<P><A href="http://www-128.ibm.com/developerworks/cn/java/wa-spring1/#author">Naveen Balani </A>, 技术架构师, Webify Solutions<BR></P>
<P>2005 年 8 月 18 日</P>
<BLOCKQUOTE>在这由三部分组成的介绍 Spring 框架的系列文章的第一期中，将开始学习如何用 Spring 技术构建轻量级的、强壮的 J2EE 应用程序。developerWorks 的定期投稿人 Naveen Balani 通过介绍 Spring 框架开始了他由三部分组成的 <I>Spring 系列</I>，其中还将介绍 Spring 面向方面的编程（AOP）和控制反转（IOC）容器。</BLOCKQUOTE>
<P>Spring 是一个开源框架，是为了解决企业应用程序开发复杂性而创建的。框架的主要优势之一就是其分层架构，分层架构允许您选择使用哪一个组件，同时为 J2EE 应用程序开发提供集成的框架。</P>
<P>在这篇由三部分组成的 <I>Spring 系列</I> 的第 1 部分中，我将介绍 Spring 框架。我先从框架底层模型的角度描述该框架的功能，然后将讨论两个最有趣的模块：Spring 面向方面编程（AOP）和控制反转 （IOC） 容器。接着将使用几个示例演示 IOC 容器在典型应用程序用例场景中的应用情况。这些示例还将成为本系列后面部分进行的展开式讨论的基础，在本文的后面部分，将介绍 Spring 框架通过 Spring AOP 实现 AOP 构造的方式。</P>
<P>请参阅 <A href="http://www-128.ibm.com/developerworks/cn/java/wa-spring1/#download">下载</A>，下载 Spring 框架和 Apache Ant，运行本系列的示例应用程序需要它们。</P>
<P><A name=1><SPAN class=atitle>Spring 框架</SPAN></A></P>
<P>Spring 框架是一个分层架构，由 7 个定义良好的模块组成。Spring 模块构建在核心容器之上，核心容器定义了创建、配置和管理 bean 的方式，如图 1 所示。</P><BR><A name=fig1><B>图 1. Spring 框架的 7 个模块</B></A><BR><IMG height=288 alt="Spring 框架图示" src="http://www-128.ibm.com/developerworks/cn/java/wa-spring1/spring_framework.gif" width=555><BR>
<P>组成 Spring 框架的每个模块（或组件）都可以单独存在，或者与其他一个或多个模块联合实现。每个模块的功能如下： 
<UL>
<LI><B>核心容器</B>：核心容器提供 Spring 框架的基本功能。核心容器的主要组件是 <CODE>BeanFactory</CODE>，它是工厂模式的实现。<CODE>BeanFactory</CODE> 使用<I>控制反转</I> （IOC） 模式将应用程序的配置和依赖性规范与实际的应用程序代码分开。 
<LI><B>Spring 上下文</B>：Spring 上下文是一个配置文件，向 Spring 框架提供上下文信息。Spring 上下文包括企业服务，例如 JNDI、EJB、电子邮件、国际化、校验和调度功能。 
<LI><B>Spring AOP</B>：通过配置管理特性，Spring AOP 模块直接将面向方面的编程功能集成到了 Spring 框架中。所以，可以很容易地使 Spring 框架管理的任何对象支持 AOP。Spring AOP 模块为基于 Spring 的应用程序中的对象提供了事务管理服务。通过使用 Spring AOP，不用依赖 EJB 组件，就可以将声明性事务管理集成到应用程序中。 
<LI><B>Spring DAO</B>：JDBC DAO 抽象层提供了有意义的异常层次结构，可用该结构来管理异常处理和不同数据库供应商抛出的错误消息。异常层次结构简化了错误处理，并且极大地降低了需要编写的异常代码数量（例如打开和关闭连接）。Spring DAO 的面向 JDBC 的异常遵从通用的 DAO 异常层次结构。 
<LI><B>Spring ORM</B>：Spring 框架插入了若干个 ORM 框架，从而提供了 ORM 的对象关系工具，其中包括 JDO、Hibernate 和 iBatis SQL Map。所有这些都遵从 Spring 的通用事务和 DAO 异常层次结构。 
<LI><B>Spring Web 模块</B>：Web 上下文模块建立在应用程序上下文模块之上，为基于 Web 的应用程序提供了上下文。所以，Spring 框架支持与 Jakarta Struts 的集成。Web 模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。 
<LI><B>Spring MVC 框架</B>：MVC 框架是一个全功能的构建 Web 应用程序的 MVC 实现。通过策略接口，MVC 框架变成为高度可配置的，MVC 容纳了大量视图技术，其中包括 JSP、Velocity、Tiles、iText 和 POI。</LI></UL>
<P></P>
<P>Spring 框架的功能可以用在任何 J2EE 服务器中，大多数功能也适用于不受管理的环境。Spring 的核心要点是：支持不绑定到特定 J2EE 服务的可重用业务和数据访问对象。毫无疑问，这样的对象可以在不同 J2EE 环境 （Web 或 EJB）、独立应用程序、测试环境之间重用。 </P><BR>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD><IMG height=1 alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%"></TD></TR></TBODY></TABLE>
<TABLE class=no-print cellSpacing=0 cellPadding=0 align=right>
<TBODY>
<TR align=right>
<TD>
<TABLE cellSpacing=0 cellPadding=0 border=0>
<TBODY>
<TR>
<TD vAlign=center><IMG height=16 alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width=16 border=0><BR></TD>
<TD vAlign=top align=right><A class=fbox href="http://www-128.ibm.com/developerworks/cn/java/wa-spring1/#main"><B>回页首</B></A></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE><BR><BR>
<P><A name=2><SPAN class=atitle>IOC 和 AOP</SPAN></A></P>
<P>控制反转模式（也称作依赖性介入）的基本概念是：不创建对象，但是描述创建它们的方式。在代码中不直接与对象和服务连接，但在配置文件中描述哪一个组件需要哪一项服务。容器 （在 Spring 框架中是 IOC 容器） 负责将这些联系在一起。</P>
<P>在典型的 IOC 场景中，容器创建了所有对象，并设置必要的属性将它们连接在一起，决定什么时间调用方法。下表列出了 IOC 的一个实现模式。</P>
<TABLE cellSpacing=4 cellPadding=2 width="80%" border=1>
<TBODY>
<TR vAlign=top>
<TD>类型 1</TD>
<TD>服务需要实现专门的接口，通过接口，由对象提供这些服务，可以从对象查询依赖性（例如，需要的附加服务）</TD></TR>
<TR vAlign=top>
<TD>类型 2</TD>
<TD>通过 JavaBean 的属性（例如 setter 方法）分配依赖性</TD></TR>
<TR vAlign=top>
<TD>类型 3</TD>
<TD>依赖性以构造函数的形式提供，不以 JavaBean 属性的形式公开</TD></TR></TBODY></TABLE>
<P>Spring 框架的 IOC 容器采用类型 2 和类型3 实现。</P>
<P><A name=IDAUFYMB><SPAN class=smalltitle>面向方面的编程</SPAN></A></P>
<P><I>面向方面的编程</I>，即 AOP，是一种编程技术，它允许程序员对横切关注点或横切典型的职责分界线的行为（例如日志和事务管理）进行模块化。AOP 的核心构造是<I>方面</I>，它将那些影响多个类的行为封装到可重用的模块中。</P>
<P>AOP 和 IOC 是补充性的技术，它们都运用模块化方式解决企业应用程序开发中的复杂问题。在典型的面向对象开发方式中，可能要将日志记录语句放在所有方法和 Java 类中才能实现日志功能。在 AOP 方式中，可以反过来将日志服务<I>模块化</I>，并以声明的方式将它们应用到需要日志的组件上。当然，优势就是 Java 类不需要知道日志服务的存在，也不需要考虑相关的代码。所以，用 Spring AOP 编写的应用程序代码是松散耦合的。</P>
<P>AOP 的功能完全集成到了 Spring 事务管理、日志和其他各种特性的上下文中。</P><BR>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD><IMG height=1 alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%"></TD></TR></TBODY></TABLE>
<TABLE class=no-print cellSpacing=0 cellPadding=0 align=right>
<TBODY>
<TR align=right>
<TD>
<TABLE cellSpacing=0 cellPadding=0 border=0>
<TBODY>
<TR>
<TD vAlign=center><IMG height=16 alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width=16 border=0><BR></TD>
<TD vAlign=top align=right><A class=fbox href="http://www-128.ibm.com/developerworks/cn/java/wa-spring1/#main"><B>回页首</B></A></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE><BR><BR>
<P><A name=3><SPAN class=atitle>IOC 容器</SPAN></A></P>
<P>Spring 设计的核心是 <CODE>org.springframework.beans</CODE> 包，它的设计目标是与 JavaBean 组件一起使用。这个包通常不是由用户直接使用，而是由服务器将其用作其他多数功能的底层中介。下一个最高级抽象是 <CODE>BeanFactory</CODE> 接口，它是工厂设计模式的实现，允许通过名称创建和检索对象。<CODE>BeanFactory</CODE> 也可以管理对象之间的关系。</P>
<P><CODE>BeanFactory</CODE> 支持两个对象模型。</P>
<UL>
<LI><B>单态</B> 模型提供了具有特定名称的对象的共享实例，可以在查询时对其进行检索。Singleton 是默认的也是最常用的对象模型。对于无状态服务对象很理想。 
<LI><B>原型</B> 模型确保每次检索都会创建单独的对象。在每个用户都需要自己的对象时，原型模型最适合。</LI></UL>
<P>bean 工厂的概念是 Spring 作为 IOC 容器的基础。IOC 将处理事情的责任从应用程序代码转移到框架。正如我将在下一个示例中演示的那样，Spring 框架使用 JavaBean 属性和配置数据来指出必须设置的依赖关系。</P>
<P><A name=IDAFHYMB><SPAN class=smalltitle>BeanFactory 接口</SPAN></A></P>
<P>因为 <CODE>org.springframework.beans.factory.BeanFactory</CODE> 是一个简单接口，所以可以针对各种底层存储方法实现。最常用的 <CODE>BeanFactory</CODE> 定义是 <CODE>XmlBeanFactory</CODE>，它根据 XML 文件中的定义装入 bean，如清单 1 所示。</P><BR><A name=IDAZHYMB><B>清单 1. XmlBeanFactory</B></A><BR>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE class=section>
BeanFactory factory = new XMLBeanFactory(new FileInputSteam("mybean.xml"));
</CODE></PRE></TD></TR></TBODY></TABLE><BR>
<P>在 XML 文件中定义的 Bean 是被消极加载的，这意味在需要 bean 之前，bean 本身不会被初始化。要从 <CODE>BeanFactory</CODE> 检索 bean，只需调用 <CODE>getBean()</CODE> 方法，传入将要检索的 bean 的名称即可，如清单 2 所示。</P><BR><A name=IDAPAANB><B>清单 2. getBean()</B></A><BR>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE class=section>
MyBean mybean = (MyBean) factory.getBean("mybean");
</CODE></PRE></TD></TR></TBODY></TABLE><BR>
<P>每个 bean 的定义都可以是 POJO （用类名和 JavaBean 初始化属性定义） 或 <CODE>FactoryBean</CODE>。<CODE>FactoryBean</CODE> 接口为使用 Spring 框架构建的应用程序添加了一个间接的级别。</P><BR>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD><IMG height=1 alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%"></TD></TR></TBODY></TABLE>
<TABLE class=no-print cellSpacing=0 cellPadding=0 align=right>
<TBODY>
<TR align=right>
<TD>
<TABLE cellSpacing=0 cellPadding=0 border=0>
<TBODY>
<TR>
<TD vAlign=center><IMG height=16 alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width=16 border=0><BR></TD>
<TD vAlign=top align=right><A class=fbox href="http://www-128.ibm.com/developerworks/cn/java/wa-spring1/#main"><B>回页首</B></A></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE><BR><BR>
<P><A name=4><SPAN class=atitle>IOC 示例</SPAN></A></P>
<P>理解控制反转最简单的方式就是看它的实际应用。在对由三部分组成的 <I>Spring 系列</I> 的第 1 部分进行总结时，我使用了一个示例，演示了如何通过 Spring IOC 容器注入应用程序的依赖关系（而不是将它们构建进来）。</P>
<P>我用开启在线信用帐户的用例作为起点。对于该实现，开启信用帐户要求用户与以下服务进行交互： 
<UL>
<LI>信用级别评定服务，查询用户的信用历史信息。 
<LI>远程信息链接服务，插入客户信息，将客户信息与信用卡和银行信息连接起来，以进行自动借记（如果需要的话）。 
<LI>电子邮件服务，向用户发送有关信用卡状态的电子邮件。</LI></UL>
<P></P><BR>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD><IMG height=1 alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%"></TD></TR></TBODY></TABLE>
<TABLE class=no-print cellSpacing=0 cellPadding=0 align=right>
<TBODY>
<TR align=right>
<TD>
<TABLE cellSpacing=0 cellPadding=0 border=0>
<TBODY>
<TR>
<TD vAlign=center><IMG height=16 alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width=16 border=0><BR></TD>
<TD vAlign=top align=right><A class=fbox href="http://www-128.ibm.com/developerworks/cn/java/wa-spring1/#main"><B>回页首</B></A></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE><BR><BR>
<P><A name=5><SPAN class=atitle>三个接口</SPAN></A></P>
<P>对于这个示例，我假设服务已经存在，理想的情况是用松散耦合的方式把它们集成在一起。以下清单显示了三个服务的应用程序接口。</P><BR><A name=IDAZBANB><B>清单 3. CreditRatingInterface</B></A><BR>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE class=section>
public interface CreditRatingInterface {

   public boolean getUserCreditHistoryInformation(ICustomer iCustomer);

}
</CODE></PRE></TD></TR></TBODY></TABLE><BR>
<P>清单 3 所示的信用级别评定接口提供了信用历史信息。它需要一个包含客户信息的 <CODE>Customer</CODE> 对象。该接口的实现是由 <CODE>CreditRating</CODE> 类提供的。</P><BR><A name=IDAMCANB><B>清单 4. CreditLinkingInterface</B></A><BR>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE class=section>

public interface CreditLinkingInterface {

public String getUrl();

		public void setUrl(String url);

		public void linkCreditBankAccount() throws Exception ;

}
</CODE></PRE></TD></TR></TBODY></TABLE><BR>
<P>信用链接接口将信用历史信息与银行信息（如果需要的话）连接在一起，并插入用户的信用卡信息。信用链接接口是一个远程服务，它的查询是通过 <CODE>getUrl()</CODE> 方法进行的。URL 由 Spring 框架的 bean 配置机制设置，我稍后会讨论它。该接口的实现是由 <CODE>CreditLinking</CODE> 类提供的。</P><BR><A name=IDA5CANB><B>清单 5. EmailInterface</B></A><BR>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE class=section>

public interface EmailInterface {

      public void sendEmail(ICustomer iCustomer);

      public String getFromEmail();

      public void setFromEmail(String fromEmail) ;

      public String getPassword();

      public void setPassword(String password) ;

      public String getSmtpHost() ;

      public void setSmtpHost(String smtpHost);

      public String getUserId() ;

      public void setUserId(String userId);
   }
</CODE></PRE></TD></TR></TBODY></TABLE><BR>
<P><CODE>EmailInterface</CODE> 负责向客户发送关于客户信用卡状态的电子邮件。邮件配置参数（例如 SMPT 主机、用户名、口令）由前面提到的 bean 配置机制设置。<CODE>Email</CODE> 类提供了该接口的实现。</P><BR>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD><IMG height=1 alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%"></TD></TR></TBODY></TABLE>
<TABLE class=no-print cellSpacing=0 cellPadding=0 align=right>
<TBODY>
<TR align=right>
<TD>
<TABLE cellSpacing=0 cellPadding=0 border=0>
<TBODY>
<TR>
<TD vAlign=center><IMG height=16 alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width=16 border=0><BR></TD>
<TD vAlign=top align=right><A class=fbox href="http://www-128.ibm.com/developerworks/cn/java/wa-spring1/#main"><B>回页首</B></A></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE><BR><BR>
<P><A name=6><SPAN class=atitle>Spring 使其保持松散</SPAN></A></P>
<P>这些接口就位之后，接下来要考虑的就是如何用松散耦合方式将它们集成在一起。在 <A href="http://www-128.ibm.com/developerworks/cn/java/wa-spring1/listing1.html">清单 6</A> 中可以看到信用卡帐户用例的实现。</P>
<P>注意，所有的 setter 方法都是由 Spring 的配置 bean 实现的。所有的依赖关系 （也就是三个接口）都可以由 Spring 框架用这些 bean 注入。<CODE>createCreditCardAccount()</CODE> 方法会用服务去执行其余实现。在 <A href="http://www-128.ibm.com/developerworks/cn/java/wa-spring1/listing2.html">清单 7 </A>中可以看到 Spring 的配置文件。我用箭头突出了这些定义。 </P><BR>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD><IMG height=1 alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%"></TD></TR></TBODY></TABLE>
<TABLE class=no-print cellSpacing=0 cellPadding=0 align=right>
<TBODY>
<TR align=right>
<TD>
<TABLE cellSpacing=0 cellPadding=0 border=0>
<TBODY>
<TR>
<TD vAlign=center><IMG height=16 alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width=16 border=0><BR></TD>
<TD vAlign=top align=right><A class=fbox href="http://www-128.ibm.com/developerworks/cn/java/wa-spring1/#main"><B>回页首</B></A></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE><BR><BR>
<P><A name=7><SPAN class=atitle>运行应用程序</SPAN></A></P>
<P>要运行示例应用程序，首先必须 <A href="http://prdownloads.sourceforge.net/springframework/spring-%20framework-1.2-rc2-with-dependencies.zip?download" target=_new>下载 Spring 框架</A> 及其所有依赖文件。接下来，将框架释放到（比如说）磁盘 <I>c:\</I>，这会创建 <I>C:\spring-framework-1.2-rc2</I> （适用于当前发行版本） 这样的文件夹。在继续后面的操作之前，还必须下载和释放 <A href="http://ant.apache.org/" target=_new>Apache Ant</A>。</P>
<P>接下来，将源代码释放到文件夹，例如 <I>c:\</I> 盘，然后创建 <I>SpringProject</I>。将 Spring 库（即 <I>C:\spring-framework-1.2-rc2\dist</I> 下的 <I>spring.jar</I> 和 <I>C:\spring-framework-1.2-rc2\lib\jakarta-commons</I> 下的 <I>commons-logging.jar</I>）复制到 <I>SpringProject\lib</I> 文件夹中。完成这些工作之后，就有了必需的构建依赖关系集。</P>
<P>打开命令提示符，将当前目录切换到 <I>SpringProject</I>，在命令提示符中输入以下命令：<CODE>build</CODE>。 </P>
<P>这会构建并运行 <CODE>CreateCreditAccountClient</CODE> 类，类的运行将创建 <CODE>Customer</CODE> 类对象并填充它，还会调用 <CODE>CreateCreditCardAccount</CODE> 类创建并链接信用卡帐户。<CODE>CreateCreditAccountClient</CODE> 还会通过 <CODE>ClassPathXmlApplicationContext</CODE> 装入 Spring 配置文件。装入 bean 之后，就可以通过 <CODE>getBean()</CODE> 方法访问它们了，如清单 8 所示。</P><BR><A name=code8><B>清单 8. 装入 Spring 配置文件</B></A><BR>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE class=section>
ClassPathXmlApplicationContext appContext = 
                    new ClassPathXmlApplicationContext(new String[] {
     "springexample-creditaccount.xml"
    });

CreateCreditCardAccountInterface creditCardAccount = 
                    (CreateCreditCardAccountInterface)
	appContext.getBean("createCreditCard");
</CODE></PRE></TD></TR></TBODY></TABLE><BR><BR>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD><IMG height=1 alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%"></TD></TR></TBODY></TABLE>
<TABLE class=no-print cellSpacing=0 cellPadding=0 align=right>
<TBODY>
<TR align=right>
<TD>
<TABLE cellSpacing=0 cellPadding=0 border=0>
<TBODY>
<TR>
<TD vAlign=center><IMG height=16 alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width=16 border=0><BR></TD>
<TD vAlign=top align=right><A class=fbox href="http://www-128.ibm.com/developerworks/cn/java/wa-spring1/#main"><B>回页首</B></A></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE><BR><BR>
<P><A name=8><SPAN class=atitle>结束语</SPAN></A></P>
<P>在这篇由三部分组成的 <I>Spring 系列</I> 的第一篇文章中，我介绍了 Spring 框架的基础。我从讨论组成 Spring 分层架构的 7 个模块开始，然后深入介绍了其中两个模块：Spring AOP 和 IOC 容器。</P>
<P>由于学习的最佳方法是实践，所以我用一个工作示例介绍了 IOC 模式 （像 Spring 的 IOC 容器实现的那样）如何用松散耦合的方式将分散的系统集成在一起。在这个示例中可以看到，将依赖关系或服务注入工作中的信用卡帐户应用程序，要比从头开始构建它们容易得多。</P>
<P>请继续关注这一系列的下一篇文章，我将在这里学习的知识基础上，介绍 Spring AOP 模块如何在企业应用程序中提供持久支持，并让您开始了解 Spring MVC 模块和相关插件。 </P><BR><BR>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD><IMG height=1 alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%"></TD></TR></TBODY></TABLE>
<TABLE class=no-print cellSpacing=0 cellPadding=0 align=right>
<TBODY>
<TR align=right>
<TD>
<TABLE cellSpacing=0 cellPadding=0 border=0>
<TBODY>
<TR>
<TD vAlign=center><IMG height=16 alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width=16 border=0><BR></TD>
<TD vAlign=top align=right><A class=fbox href="http://www-128.ibm.com/developerworks/cn/java/wa-spring1/#main"><B>回页首</B></A></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE><BR><BR>
<P><SPAN class=atitle><A name=download>下载</A></SPAN></P>
<TABLE class=data-table-1 cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TH>描述</TH>
<TH>Name</TH>
<TH style="TEXT-ALIGN: right">Size</TH>
<TH>&nbsp;Download method</TH></TR>
<TR>
<TD class=tb-row>Examples: source code, spring files, build scripts</TD>
<TD noWrap>wa-spring1-SpringProject.zip</TD>
<TD style="TEXT-ALIGN: right" noWrap>9 KB</TD>
<TD noWrap>&nbsp;<A class=fbox href="ftp://www6.software.ibm.com/software/developer/library/wa-spring1-SpringProject.zip"><B>FTP</B></A></TD></TR></TBODY></TABLE>
<TABLE cellSpacing=0 cellPadding=0 border=0>
<TBODY>
<TR vAlign=top>
<TD colSpan=5><IMG height=12 alt="" src="http://www.ibm.com/i/c.gif" width=12 border=0></TD></TR>
<TR>
<TD><IMG height=16 alt="" src="http://www.ibm.com/i/v14/icons/fw.gif" width=16></TD>
<TD><A class=fbox href="http://www-128.ibm.com/developerworks/cn/whichmethod.html">Information about download methods</A></TD>
<TD><IMG height=1 alt="" src="http://www.ibm.com/i/c.gif" width=50></TD>
<TD><IMG height=16 alt="" src="http://www.ibm.com/i/v14/icons/sout.gif" width=16></TD>
<TD><A class=fbox href="http://www.adobe.com/products/acrobat/readstep2.html">Get Adobe&reg; Reader&reg;</A></TD></TR></TBODY></TABLE><BR>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD><IMG height=1 alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%"></TD></TR></TBODY></TABLE>
<TABLE class=no-print cellSpacing=0 cellPadding=0 align=right>
<TBODY>
<TR align=right>
<TD>
<TABLE cellSpacing=0 cellPadding=0 border=0>
<TBODY>
<TR>
<TD vAlign=center><IMG height=16 alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width=16 border=0><BR></TD>
<TD vAlign=top align=right><A class=fbox href="http://www-128.ibm.com/developerworks/cn/java/wa-spring1/#main"><B>回页首</B></A></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE><BR><BR>
<P><A name=resources><SPAN class=atitle>参考资料 </SPAN></A></P>
<UL>
<LI>您可以参阅本文在 developerWorks 全球站点上的 <A href="http://www.ibm.com/developerworks/web/library/wa-spring1/" target=_blank>英文原文</A> 。<BR><BR>
<LI>虽然 Spring AOP 提供了独特的优势，但它并不是惟一的 AOP 实现。请参阅“<A href="http://www-128.ibm.com/developerworks/cn/java/j-aopwork1/">http://www-128.ibm.com/developerworks/cn/java/j-aopwork1/</A>”（<I>developerWorks</I>，2005 年 2 月），了解 Spring AOP 的构成。<BR><BR>
<LI>通过“<A href="http://www.ibm.com/developerworks/cn/java/j-hibern/">无需容器的对象关系映射</A>”（<I>developerWorks</I>，2004 年 4 月）学习如何用 Hibernate 和 Spring AOP 开发事务性的持久层（persistence layer）。<BR><BR>
<LI>请从 <A href="http://prdownloads.sourceforge.net/springframework/">Spring homepage</A> 下载 Spring 框架。<BR><BR>
<LI>请从 <A href="http://ant.apache.org/">Ant homepage</A> 下载 Apache Ant。<BR><BR>
<LI>通过参与 <A href="http://www.ibm.com/developerworks/blogs/">developerWorks blogs</A> 加入 developerWorks 社区。<BR><BR>
<LI>还请参阅 <I>developerWorks</I> 上的一些丰富的参考资料： 
<UL>
<LI><A href="http://www.ibm.com/developerworks/web/">Web 架构专区</A> 中的文章专门介绍了各种基于 Web 的解决方案。 
<LI><A href="http://devworks.krcinfo.com/">Developer Bookstore</A> 提供了技术书籍的完整清单，其中包括数百本 Web 相关主题的书籍。</LI></UL><BR></LI></UL><BR>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD><IMG height=1 alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%"></TD></TR></TBODY></TABLE>
<TABLE class=no-print cellSpacing=0 cellPadding=0 align=right>
<TBODY>
<TR align=right>
<TD>
<TABLE cellSpacing=0 cellPadding=0 border=0>
<TBODY>
<TR>
<TD vAlign=center><IMG height=16 alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width=16 border=0><BR></TD>
<TD vAlign=top align=right><A class=fbox href="http://www-128.ibm.com/developerworks/cn/java/wa-spring1/#main"><B>回页首</B></A></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE><BR><BR>
<P><A name=author><SPAN class=atitle>关于作者</SPAN></A></P>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD colSpan=2><IMG height=5 alt="" src="http://www.ibm.com/i/c.gif" width="100%"></TD></TR>
<TR vAlign=top align=left>
<TD>
<P></P></TD>
<TD>
<P>Naveen Balani 把他的大多数时间都花在了设计和开发基于 J2EE 的框架和产品上。他为 IBM <I>developerWorks</I> 撰写了各种不同的文章，涉及的主题包括：ESB、SOA、JMS、WebServices Architectures、CICS、AXIS、DB2 XML Extender、WebSphere Studio、MQSeries 和 Java Wireless Devices，以及 DB2 Everyplace for Palm、J2ME、MIDP、Java-Nokia、Visual Studio .Net 和无线数据同步。您可以通过 <A href="mailto:naveenbalani@rediffmail.com?cc=htc@us.ibm.com">mailto:naveenbalani@rediffmail.com?cc=htc@us.ibm.com</A> 与他联系。 </P></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE>]]></description>
</item><item>
<title><![CDATA[《java开源开发》笔记（1）]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=torrent&amp;id=7866</link>
<author>torrent</author>
<pubDate>2005/8/17 23:30:23</pubDate>
<description><![CDATA[<A><FONT size=3>　</FONT></A><FONT size=3>（先翻译一段） </FONT>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><STRONG><FONT size=3>前言</FONT></STRONG></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"></SPAN><FONT size=3>&nbsp;</FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=3><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">今日之</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">IT</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">界，</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Java</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">是企业级开发中的领导技术。由于管理方面的需求往往大于技术因素，基础机制的复杂性呈现指数级增长的趋势，导致很多人不可能跟上如此快速变化世界的步伐。这类复杂性可从被过分升级的</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">J2EE</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">描述中可见一斑。正是这种不必要复杂性逼迫我们寻求简化开发的步伐。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=3><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">请别误会，我们热爱</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">J2EE</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">！只是为什么要花这么久的时间去掌握它的填充品呢？我们（指本文的作者们）都早就接受了</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">J2EE</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，掌握了其概念与复杂性。那是一个痛苦和费时的过程，为了开始掌握</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">(?</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">开发</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">,making use of)</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">可大幅减少开发时间的可重用开源工具。因此，我们也开始质问（探讨），（在</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">J2EE</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中）什么技术确实有用，什么技术已经变成了妨碍因素。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=3><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">本书讨论，应用开发技术以及利用开源技术，去降低构建企业级应用的耗费。我们的目标是演示如何结合上述技术来建立一个实际应用，而同时避免复杂性。我们将帮助你扩展</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">java</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">和</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">J2EE</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的知识，让你能够利用这些价值数千万的研究开发（成果）。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=3>本书不仅教你如何利用开源工具马上展开工作，它也将增强和拓宽你的开发哲学观，正如我们一样，你将很快发现头脑中会有这样的想法，“为什么我早没有这样干？”。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><o:p><FONT face="Times New Roman" size=3>&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=3>本书有什么用？</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; mso-list: l2 level1 lfo1; tab-stops: list 21.0pt"><FONT size=3><SPAN lang=EN-US style="FONT-FAMILY: Wingdings; mso-fareast-font-family: Wingdings; mso-bidi-font-family: Wingdings"><SPAN style="mso-list: Ignore">n<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">直接的好处是能够熟悉部分可利用的开源技术；</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; mso-list: l2 level1 lfo1; tab-stops: list 21.0pt"><FONT size=3><SPAN lang=EN-US style="FONT-FAMILY: Wingdings; mso-fareast-font-family: Wingdings; mso-bidi-font-family: Wingdings"><SPAN style="mso-list: Ignore">n<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">而且，我们将介绍简单的技术方法和开发哲学，它们既适合现在的情况，同样也将适用未来的开发，即使今天的技术被更好的技术所代替。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=3>在本书里，我们利用这些技术和方法来重新构建著名的“宠物商店”应用。。。。。。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p><FONT face="Times New Roman" size=3>&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=3>谁应读此书？</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=3><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">本书瞄准两个目标：技术和方法（技术和技巧，</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">technology and techniques</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）。对应两类用户群。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=3><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">一类是希望磨练开源</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Java</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">组件（工具）的应用。本书将深入几个著名的开源项目，包括</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">JUnit, Ant, Hibernate, WebWork, SiteMesh, XDoclet, </FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">及</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Lucene</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。讨论每一工具所针对的问题，并给出如何在实际应用中使用它们的，一步一步地指导。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=3><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">第二类是被控制项目复杂性所纠缠的人。我们发现，这种复杂性往往是来源于</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">----</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">开发者认为，复杂的需求，需要复杂的解决方案。其实，应用简单性的原则，也能在最短的时间内达成目标。我们在本书的“宠物商店”中应用“测试驱动开发（</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">TDD</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）”，</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">TDD</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">是一种表现了“少就是多”思想的实践。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p><FONT face="Times New Roman" size=3>&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><STRONG><FONT size=3>（以下以笔记的方式完成）</FONT></STRONG></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=3><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">第一部分</SPAN><SPAN lang=EN-US><SPAN style="mso-spacerun: yes"><FONT face="Times New Roman">&nbsp; </FONT></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">介绍</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"></SPAN><FONT size=3>&nbsp;</FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=3>开源工具和应用开发方法的简介，分两章</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p><FONT face="Times New Roman" size=3>&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=3><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">第</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">1</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">章</SPAN><SPAN lang=EN-US><FONT face="Times New Roman"> </FONT></SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><FONT face="Times New Roman"></FONT></SPAN><FONT size=3>&nbsp;</FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=3><SPAN lang=EN-US><FONT face="Times New Roman">1</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。开源技术简介</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=3><SPAN lang=EN-US><FONT face="Times New Roman">Open Source Software</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">（</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">OSS</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）：文章提出一个有趣观点，开源项目本身的成败与你的应用的成败并不相关。因为你可以通过开源的特点，了解其较深层次内容，从而保证其能与你自己的项目良好整合</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">---even if the OSS project itself is not considered a widespread “success”.</FONT></SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=3>该书介绍了部分开源项目：</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; mso-list: l0 level1 lfo3; tab-stops: list 21.0pt"><FONT size=3><SPAN lang=EN-US style="FONT-FAMILY: Wingdings; mso-fareast-font-family: Wingdings; mso-bidi-font-family: Wingdings"><SPAN style="mso-list: Ignore">n<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN lang=EN-US style="FONT-FAMILY: Palatino-Roman; mso-fareast-font-family: ZapfDingbats; mso-bidi-font-family: Palatino-Roman; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt"><FONT face="Times New Roman">JUnit and Mock Object<SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>------</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">测试工具和库；</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; mso-list: l0 level1 lfo3; tab-stops: list 21.0pt"><FONT size=3><SPAN lang=EN-US style="FONT-FAMILY: Wingdings; mso-fareast-font-family: Wingdings; mso-bidi-font-family: Wingdings"><SPAN style="mso-list: Ignore">n<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN lang=EN-US><FONT face="Times New Roman">OpenSymphony WebWork<SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp; </SPAN><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN>----- MVC</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">架构；</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; mso-list: l0 level1 lfo3; tab-stops: list 21.0pt"><FONT size=3><SPAN lang=EN-US style="FONT-FAMILY: Wingdings; mso-fareast-font-family: Wingdings; mso-bidi-font-family: Wingdings"><SPAN style="mso-list: Ignore">n<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Hibernate<SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="mso-spacerun: yes">&nbsp;</SPAN>-----</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">透明和强力的，对象</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">/</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">关系持久性和查询服务；</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; mso-list: l0 level1 lfo3; tab-stops: list 21.0pt"><FONT size=3><SPAN lang=EN-US style="FONT-FAMILY: Wingdings; mso-fareast-font-family: Wingdings; mso-bidi-font-family: Wingdings"><SPAN style="mso-list: Ignore">n<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN lang=EN-US><FONT face="Times New Roman">OpenSymphony SiteMesh<SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN>-------</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">页面布局和</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Web</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">应用整合系统（不了解）</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; mso-list: l0 level1 lfo3; tab-stops: list 21.0pt"><FONT size=3><SPAN lang=EN-US style="FONT-FAMILY: Wingdings; mso-fareast-font-family: Wingdings; mso-bidi-font-family: Wingdings"><SPAN style="mso-list: Ignore">n<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN lang=EN-US><FONT face="Times New Roman">OpenSymphony OSCache<SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN>-------</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">可缓冲站点动态内容的实用组件！！！（好东西，可用到论文中，学！！！）</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; mso-list: l0 level1 lfo3; tab-stops: list 21.0pt"><FONT size=3><SPAN lang=EN-US style="FONT-FAMILY: Wingdings; mso-fareast-font-family: Wingdings; mso-bidi-font-family: Wingdings"><SPAN style="mso-list: Ignore">n<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN lang=EN-US><FONT face="Times New Roman">XDoclet<SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp; </SPAN><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN>-------</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">代码生成工具，开始用于</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">EJB</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">配置，现在可完成更多的任务。文中将演示其如何简化</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Hibernate</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的配置。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; mso-list: l0 level1 lfo3; tab-stops: list 21.0pt"><FONT size=3><SPAN lang=EN-US style="FONT-FAMILY: Wingdings; mso-fareast-font-family: Wingdings; mso-bidi-font-family: Wingdings"><SPAN style="mso-list: Ignore">n<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Jakarta Lucent<SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN>--------</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">搜索引擎（文本搜索）</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; mso-list: l0 level1 lfo3; tab-stops: list 21.0pt"><FONT size=3><SPAN lang=EN-US style="FONT-FAMILY: Wingdings; mso-fareast-font-family: Wingdings; mso-bidi-font-family: Wingdings"><SPAN style="mso-list: Ignore">n<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Jakarta Commons<SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN>-------</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">简单、可重用的</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Java</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">组件池</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p><FONT face="Times New Roman" size=3>&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=3><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">奇怪，此处没提</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">ant</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">；</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p><FONT face="Times New Roman" size=3>&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=3><SPAN lang=EN-US><FONT face="Times New Roman">2</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。设计和开发方法体系</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">?</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">（</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Philosophies</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=3>分为三类：</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; mso-list: l1 level1 lfo2; tab-stops: list 21.0pt"><FONT size=3><SPAN lang=EN-US style="FONT-FAMILY: Wingdings; mso-fareast-font-family: Wingdings; mso-bidi-font-family: Wingdings"><SPAN style="mso-list: Ignore">n<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Test First<SPAN style="mso-spacerun: yes">&nbsp; </SPAN></FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">不论是否为极限编程者，都应该测试优先</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">!</FONT></SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; mso-list: l1 level1 lfo2; tab-stops: list 21.0pt"><FONT size=3><SPAN lang=EN-US style="FONT-FAMILY: Wingdings; mso-fareast-font-family: Wingdings; mso-bidi-font-family: Wingdings"><SPAN style="mso-list: Ignore">n<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Less is More<SPAN style="mso-spacerun: yes">&nbsp; </SPAN></FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">尽量选用轻量级解决方案（</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">so less is more, haha</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; mso-list: l1 level1 lfo2; tab-stops: list 21.0pt"><FONT size=3><SPAN lang=EN-US style="FONT-FAMILY: Wingdings; mso-fareast-font-family: Wingdings; mso-bidi-font-family: Wingdings"><SPAN style="mso-list: Ignore">n<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Always Ask the Dumb Questions<SPAN style="mso-spacerun: yes">&nbsp; </SPAN></FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在实现之前问自己，“</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">why</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">？”。</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">/*</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">更像是个建议，不知道将来有哪些方法归入这一类</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">*/</FONT></SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-spacerun: yes"><FONT face="Times New Roman" size=3>&nbsp;&nbsp; </FONT></SPAN></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=3><SPAN lang=EN-US><FONT face="Times New Roman">3</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。宠物商店项目探索</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=3>（一小段废话）</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p><FONT face="Times New Roman" size=3>&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p><FONT face="Times New Roman" size=3>&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=3><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">第</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">2</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">章</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"></SPAN><FONT size=3>&nbsp;</FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=3><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">内容：讨论用来构建</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">PetSoar</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的工具和技巧，以及它们的组合使用。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=3><SPAN lang=EN-US><FONT face="Times New Roman">1</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。还有</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">PetStore</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">出现吗？</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=3><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">列出许多</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Petstore</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。（有一句话有意思，大意为：用</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">PetStore</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">卖技术的比卖宠物的多，哈哈！！！）</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=3><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">比较而言，</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">PetSoar</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的构建目标</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">----</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">应用速度快，包含代码少（</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">less is more</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">思想）；更关心可维护性！！</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=3><SPAN lang=EN-US><FONT face="Times New Roman">2</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。了解可维护性的重要性</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=3><SPAN lang=EN-US><FONT face="Times New Roman">3</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。了解</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">PetSoar</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的需求</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p><FONT face="Times New Roman" size=3>&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p><FONT face="Times New Roman" size=3>&nbsp;</FONT></o:p></SPAN></P>]]></description>
</item><item>
<title><![CDATA[设计模式（8）--采用委托减少继承的使用（原则2）]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=torrent&amp;id=7847</link>
<author>torrent</author>
<pubDate>2005/8/16 16:20:33</pubDate>
<description><![CDATA[
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><B style="mso-bidi-font-weight: normal"><FONT size=2><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">让重用机制发挥作用</SPAN></FONT></B></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><B style="mso-bidi-font-weight: normal"><FONT size=2><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"></SPAN><SPAN lang=EN-US><?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><o:p></o:p></SPAN></FONT></B>&nbsp;</P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>多数人能够理解对象、接口、类、继承等概念。然而，真正的挑战在于应用这些概念来构建灵活、可重用的软件。设计模式告诉你如何做到这一点。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2></FONT></SPAN>&nbsp;</P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=2><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">继承</SPAN><SPAN lang=EN-US><FONT face=宋体>VS</FONT></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">合成</SPAN></B></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=2><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"></SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></B></FONT>&nbsp;</P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>在面向对象系统的功能重用过程中，两个最普遍的技术就是类的继承和对象合成。我们之前解释过，类的继承让你能通过某个类的实现定义另外的类的实现。通过子类实现的重用通常指“白盒重用”。术语“白盒”指的是可见性：通过继承，父类的内部结构对子类来说是可见的。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>对象合成是类继承的替代选择。通过汇编或合成对象可以获得新的功能。对象合成需要用来进行合成的对象具备良好定义的接口。这种类型的重用被称为“黑盒重用”，因为对象的内部细节是不可见的。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2></FONT></SPAN>&nbsp;</P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>继承和合成都有各自的优缺点。类的继承是在编译时静态定义的，且由于语言的直接支持，可直接实现。类继承也使得可以较易的在重用时修改实现，当子类重载部分而不是所有的操作时，它同样可影响其继承而来的操作（在使用了重载的情况下）。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><FONT size=2><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">类继承也有一些缺点。首先，由于继承在编译时完成，因此，不可能在运行时改变继承自其父类的实现；其次，更糟的是，父类通常定义了其子类的部分物理表示。因为继承向子类暴露了父类的实现细节，故有这样的说法</SPAN><FONT face=宋体><SPAN lang=EN-US>—</SPAN><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">继承打破封装</SPAN></B><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。因为子类的实现与父类的实现关系密切，所以父类实现的任何改变将引起子类的变化。</SPAN></FONT></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>当你试图重用一个子类时，这种实现依赖可能会产生问题，由于通过继承得到的实现不可能在每个方面都适合新的问题领域，故父类可能会要更改或重写。这种依赖限制了灵活性，并最终限制了可重用性。解决的方案是仅仅通过抽象类来继承，因为抽象类通常提供很少的实现、甚至根本没有任何实现。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"></SPAN>&nbsp;</P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>对象合成是对象通过获得其他对象的引用，而在运行时动态完成的。合成需要对象表明各自的接口，这需要小心的设计接口，以利对象可与其他更多对象一起使用。因为对象通过其接口进行访问，我们不必打破封装。只要拥有同一类型，任何对象都能在运行时替换为另外的对象。而且，因为对象的实现是根据其接口而编写，这将减少实现依赖。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>对象合成在系统设计中还有另外一个效果。任用对象合成能帮助你保持类的封装而可专心处理一项任务。你的类和类层次将保持较小，很少出现变成难以管理的层次大怪。另一方面，基于对象合成的设计中将拥有更多的对象（在更少的类的情况下），系统的行为将决定于它们之间的相互关系，而不是在一个类中定义。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>这里导出了我们的第二个面向对象设计原则：</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT face=宋体 size=2></FONT></SPAN>&nbsp;</P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 62.95pt; mso-char-indent-count: 5.97"><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>优先采用对象合成来代替类继承</FONT></SPAN></B></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 62.95pt; mso-char-indent-count: 5.97"><B style="mso-bidi-font-weight: normal"><FONT size=2><FONT face=宋体><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"></SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></FONT></FONT></B>&nbsp;</P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>理想情况下，你应该在不必编写新组件的情况下达成重用，你应当可以通过对象合成来组装存在的组件而得到所需的功能。但这种情况很少，因为在实践中可获得的组件集并不十分丰富。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>根据我们的经验，设计中采用继承作为重用技术的情况有些过滥，其实，在设计中更多的任用对象合成技术将带来更好的可重用性。在设计模式中，你将看到一次又一次的对象合成应用。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT face=宋体 size=2></FONT></SPAN>&nbsp;</P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>委托</FONT></SPAN></B></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><B style="mso-bidi-font-weight: normal"><FONT size=2><FONT face=宋体><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"></SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></FONT></FONT></B>&nbsp;</P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><FONT size=2><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">委托是使得合成技术在重用中完成和继承一样功能的一个办法。在委托中，当处理请求时，涉及到两个对象：接收者对象委托其操作给委托人对象（代表）。一个类比是子类处理发给父类的请求。但是，在继承中，继承而来的操作总可以通过</SPAN><FONT face=宋体><SPAN lang=EN-US>this</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">成员变量指向接收者对象；而在委托中，为了达成同样的效果，接收者将自己传递给委托人，以让被委托的操作指向接受者。</SPAN></FONT></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>例如，代替将窗口类作为矩形类的子类的方案，窗口类可以通过保持一个矩形实例变量，并将矩形的详细行为委托给它，而重用矩形类的行为。换句话说，“窗口是矩形”的替代方案是，“窗口可以作为一个矩形”。应用委托，窗口对象可以明确的发送请求给其矩形对象实例；而如果不采用委托，它可能必须继承这些操作。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT face=宋体 size=2></FONT></SPAN>&nbsp;</P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN lang=EN-US><?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" /><v:shapetype id=_x0000_t75 coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f"><FONT size=2><FONT face=宋体><v:stroke joinstyle="miter"></v:stroke><v:formulas><v:f eqn="if lineDrawn pixelLineWidth 0"></v:f><v:f eqn="sum @0 1 0"></v:f><v:f eqn="sum 0 0 @1"></v:f><v:f eqn="prod @2 1 2"></v:f><v:f eqn="prod @3 21600 pixelWidth"></v:f><v:f eqn="prod @3 21600 pixelHeight"></v:f><v:f eqn="sum @0 0 1"></v:f><v:f eqn="prod @6 1 2"></v:f><v:f eqn="prod @7 21600 pixelWidth"></v:f><v:f eqn="sum @8 21600 0"></v:f><v:f eqn="prod @7 21600 pixelHeight"></v:f><v:f eqn="sum @10 21600 0"></v:f></v:formulas><v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"></v:path><o:lock v:ext="edit" aspectratio="t"></o:lock></FONT></FONT></v:shapetype></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN lang=EN-US><o:p><FONT face=宋体 size=2></FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><FONT size=2><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">委托的主要优点在于，可以容易的在运行时合成（</SPAN><FONT face=宋体><SPAN lang=EN-US>compose</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）行为并改变其合成方式。假设矩形类和圆类拥有同样的类型，我们的窗口可以在运行时变成圆，只需通过用圆实例替换矩形实例。</SPAN></FONT></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT face=宋体 size=2></FONT></SPAN>&nbsp;</P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><FONT size=2><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">委托与其它通过对象合成来增强软件灵活性的技术一样，都有一个共同的缺点：动态、高参数化的软件与相对静态的软件相比，比较难以理解。另外，委托也存在运行时效率问题。只有当运用委托的简化性超过其复杂性的情况下，委托才是一种好的设计选择。很难说明何时运用委托，因为其效率取决于其应用环境，而对效率的判断取决于设计者运用它的经验。最好的应用委托的情况是当它运用于高度程式化的环境----</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">即，在标准模式中。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT face=宋体 size=2></FONT></SPAN>&nbsp;</P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>有几个设计模式应用了委托，如状态模式、策略模式、和访问者模式。在状态模式中，一个对象委托其请求给状态对象，状态对象表示了它的当前状态；策略模式中，一个对象委托一个详细请求给另外一个表示携带请求的策略的对象；一个对象只有一个状态，但可以有多个针对不同请求的策略，这两个模式的目的都是为了通过改变委托请求的对象，而改变对象的行为。在访问者模式中，对对象结构的每一个元素的执行操作总是委托给了访问者对象。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>在其他的模式中委托的应用，没有在上述模式中那么重要。解调器模式用一个对象去协调其它对象的通信，解调器对象有时简单的直接用其它对象执行操作，有的时候，它提交一个对自身的引用，此时真正运用了委托；责任链对象通过将请求沿着对象链从一个对象传到另外一个，从而处理请求。有时，请求携带了一个接收请求的原始对象的引用，此时，该模式运用了委托；桥接模式分离了实现与其抽象，当抽象和特定实现匹配时，抽象可简单的委托对具体实现的操作。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT face=宋体 size=2></FONT></SPAN>&nbsp;</P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><FONT size=2><U><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><STRONG>委托是对象合成的一个特例</STRONG></SPAN></U><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。这说明，为了代码重用，总能用对象合成机制来替换继承。</SPAN></FONT></P>]]></description>
</item><item>
<title><![CDATA[设计模式（7）--原则1：对接口编程]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=torrent&amp;id=7715</link>
<author>torrent</author>
<pubDate>2005/8/8 22:46:20</pubDate>
<description><![CDATA[
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><B style="mso-bidi-font-weight: normal"><FONT size=2><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">类继承与接口继承</SPAN><SPAN lang=EN-US><?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><o:p></o:p></SPAN></FONT></B></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>理解对象的类与对象的类型的不同非常重要。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><FONT size=2><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">对象的类定义了对象如何实现，类定义了对象的内部状态及操作的实现。对象的类型所指的仅仅是它的接口</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">—</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">即类可以响应的请求的集合，对象可有多个类型，不同类的对象可以拥有同一类型。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>当然，类和类型之间有更紧密的关系。因为类定义了对象可执行的操作，因此，类也定义了对象的类型。当我们说对象是类的一个实例，实际上暗示了此对象支持类所定义的接口。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><FONT size=2><SPAN lang=EN-US><FONT face="Times New Roman">C++</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">和</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Eiffel</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">语言用类同时来描述对象的类型和对象的实现。</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Smalltalk</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">语言并不声明变量的类型，因此，编译器并不检查那种是变量类型的子类型的变量的对象类型。发送消息时需要检查接受者的类，但当接受器是特定类的实例时，则不需检查。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>理解对象继承和接口继承（或子类型）的区别亦十分重要。类继承定义对象的实现是根据另一个对象的实现，简单的说，它是一种用于代码和表示共享的机制；与之比较，接口继承（子类型）规定了对象何时用来替代另一个。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><FONT size=2><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">很容易混淆这两个概念，因为多数语言对此不作区分。在</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">C++</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">和</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Eiffel</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中，继承意味着接口继承和实现继承。</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">C++</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中继承一个接口的标准方式是从一个具有（纯）虚成员方法的类中公开声明继承。纯接口继承近似于</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">C++</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中的从纯虚函数公开继承。在</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Smalltalk</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中，继承仅意味着继承的实现，你可以将任何类的实例分配给一个变量，只要实例支持在该变量的值上执行操作。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><FONT size=2><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">尽管大多数的语言都不支持接口继承和实现继承的区分，人们在实践中对此进行了区分。</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Smalltalk</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">程序员通常将子类型当作子类来处理（）；</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">C++</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">程序员通过抽象类所定义的类型来操作对象。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>很多设计模式都依赖于这种区分。例如，责任链对象必须有一个公共类型，但通常不共享一个公共实现。在合成模式中，元件定义了一个公共接口，但合成器通常定义一个公共实现。命令模式、观测者模式、状态模式、和策略模式常常要实现纯接口的抽象类。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><B style="mso-bidi-font-weight: normal"><FONT size=2><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">对接口而非对实现进行编程</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></FONT></B></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>类继承主要作为通过重用父类的函数而扩展应用的功能的机制，它可从旧对象迅速生成新对象，让你从已存在的类中继承你所需要的功能，从而得到新的实现。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>然而，执行重用不需要做这么多工作。继承的能力包括用相同的接口（通常从抽象类中继承）定义对象族，这也很重要。为什么呢？因为多态性依赖于它。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>当合适的使用继承时，所有源于抽象类的类都共享其接口。这说明子类仅仅增加或重载操作，并不隐藏父类的操作。所有的子类都能向对抽象类的接口的请求作出响应，因此，他们都是抽象类的子类型。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>从抽象类所定义的接口单独地操纵对象有两个好处：</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 35.95pt; TEXT-INDENT: -18pt; mso-list: l0 level1 lfo1; tab-stops: list 35.95pt"><A name=auto1096></A><FONT size=2><SPAN lang=EN-US style="mso-fareast-font-family: 'Times New Roman'"><SPAN style="mso-list: Ignore"><FONT face="Times New Roman">1．<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp; </SPAN></FONT></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">只要对象使用客户所预期的接口，客户不必关心对象所使用的详细类型。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 35.95pt; TEXT-INDENT: -18pt; mso-list: l0 level1 lfo1; tab-stops: list 35.95pt"><FONT size=2><SPAN lang=EN-US style="mso-fareast-font-family: 'Times New Roman'"><SPAN style="mso-list: Ignore"><FONT face="Times New Roman">2．<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp; </SPAN></FONT></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">客户不必关心实现这些对象的类，客户所要了解的仅仅是定义接口的抽象类。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>这样，减少了子系统间的实现依赖性，导致了以下的可重用的面向对象设计的原则：</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 70.6pt; mso-char-indent-count: 6.7"><B style="mso-bidi-font-weight: normal"><FONT size=2><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">为接口而不为实现编程</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></FONT></B></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>不要为特定具体类的实例声明变量，而应该向抽象类定义的接口提交。你将发现，这也是本书所讨论的设计模式的普遍主题。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>当然，系统中有时必须实例化具体对象（即详细描述特定实现），创建性模式就可实现这样的功能。通过对对象创建过程的抽象，这些模式让你以不同方式将接口与其实现相联系，从而透明地实例化。创建性模式可以确保你的系统的编写是根据接口而不是实现。</FONT></SPAN></P>]]></description>
</item><item>
<title><![CDATA[设计模式（6）--描述对象实现]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=torrent&amp;id=7703</link>
<author>torrent</author>
<pubDate>2005/8/8 1:16:43</pubDate>
<description><![CDATA[
<P><A>　------（续上节--设计模式如何解决设计问题）</A></P>
<P>&nbsp;</P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><B style="mso-bidi-font-weight: normal"><FONT size=3><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">描述对象实现</SPAN><SPAN lang=EN-US><?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><o:p></o:p></SPAN></FONT></B></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=3>对象的实现要通过类中的定义，类详细描述了对象的内部数据和表示，以及定义了对象可以执行的操作。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><FONT size=3><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">我们采用基于</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">OMT</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的概念（见附录</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">B</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">），以矩形描述类，将类名用粗体字显示，而操作出现在类名下面，以正常字体表示，数据的定义紧跟着操作。类名、操作、和数据之间用线分隔：</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN lang=EN-US><FONT face="Times New Roman"><FONT size=3><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<IMG style="BORDER-LEFT-COLOR: #000000; BORDER-BOTTOM-COLOR: #000000; BORDER-TOP-COLOR: #000000; BORDER-RIGHT-COLOR: #000000" src="http://blogger.org.cn/blog/uploadfile/20058811822374.GIF" border=0>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN><?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" /><v:shapetype id=_x0000_t75 stroked="f" filled="f" path="m@4@5l@4@11@9@11@9@5xe" o:preferrelative="t" o:spt="75" coordsize="21600,21600"><v:stroke joinstyle="miter"></v:stroke><v:formulas><v:f eqn="if lineDrawn pixelLineWidth 0"></v:f><v:f eqn="sum @0 1 0"></v:f><v:f eqn="sum 0 0 @1"></v:f><v:f eqn="prod @2 1 2"></v:f><v:f eqn="prod @3 21600 pixelWidth"></v:f><v:f eqn="prod @3 21600 pixelHeight"></v:f><v:f eqn="sum @0 0 1"></v:f><v:f eqn="prod @6 1 2"></v:f><v:f eqn="prod @7 21600 pixelWidth"></v:f><v:f eqn="sum @8 21600 0"></v:f><v:f eqn="prod @7 21600 pixelHeight"></v:f><v:f eqn="sum @10 21600 0"></v:f></v:formulas><v:path o:connecttype="rect" gradientshapeok="t" o:extrusionok="f"></v:path><o:lock aspectratio="t" v:ext="edit"></o:lock></v:shapetype></FONT></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=3>返回类型和实例变量类型是可选的，因为我们没有采取静态类型实现语言。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=3>对象通过类的实例化而建立，对象被称为类的实例。类实例化的过程包括为对象的内部数据分配内存空间（建立实例变量），和将数据与操作相联系。类的实例化可创建多个相似的实例对象。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=3>虚线表明了一个类实例化另一个类的对象，箭头所指为实例化对象所属的类。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN lang=EN-US><FONT size=3><SPAN style="mso-spacerun: yes"><FONT face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<IMG style="BORDER-LEFT-COLOR: #000000; BORDER-BOTTOM-COLOR: #000000; BORDER-TOP-COLOR: #000000; BORDER-RIGHT-COLOR: #000000" src="http://blogger.org.cn/blog/uploadfile/20058811847573.GIF" border=0>&nbsp;</FONT></SPAN><SPAN style="mso-spacerun: yes"><FONT face="Times New Roman">&nbsp;</FONT></SPAN></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=3>新类可以通过类继承的方式从已存的类中派生。当子类继承于父类时，子类包括了父类中定义的数据和操作。子类的实例对象包含子类定义的数据和其从父类继承来的数据，并且可以执行子类和父类中定义的所有操作。我们在下图中指明了子类和父类的关系。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=3>&nbsp;&nbsp;&nbsp;&nbsp; <IMG style="BORDER-LEFT-COLOR: #000000; BORDER-BOTTOM-COLOR: #000000; BORDER-TOP-COLOR: #000000; BORDER-RIGHT-COLOR: #000000" src="http://blogger.org.cn/blog/uploadfile/2005881196936.GIF" border=0></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"></SPAN><FONT size=3><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">抽象类的主要目的是为了定义其子类的共同接口。抽象类将其部分或全部的操作推迟到在其子类中实现，因此，<B style="mso-bidi-font-weight: normal">抽象类不能被实例化</B>。在抽象类中声明但未实现的操作称为抽象操作。非抽象类称为具体类（</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">concrete classes</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><FONT size=3><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">子类可重定义其父类的行为，具体的说，子类可以重载（</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">override</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）父类所定义的操作。重载使得子类可以代替其父类处理请求。类的继承机制使你能够通过简单的扩展其它类而定义一个类，可以容易的定义出一个具有相关功能的类族。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=3>抽象类的名字用斜体表示，以区分具体类，抽象操作也是如此。如果包含操作的伪代码，则用狗耳虚线指向操作名。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=3>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <IMG style="BORDER-LEFT-COLOR: #000000; BORDER-BOTTOM-COLOR: #000000; BORDER-TOP-COLOR: #000000; BORDER-RIGHT-COLOR: #000000" src="http://blogger.org.cn/blog/uploadfile/20058811926382.GIF" border=0></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"></SPAN><FONT size=3><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">混合类（</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">mixin class</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）可为其它类提供可选的接口和功能。类似于抽象类，它也不能实例化。混合类的实现需要借助于多继承。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=3>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <IMG style="BORDER-LEFT-COLOR: #000000; BORDER-BOTTOM-COLOR: #000000; BORDER-TOP-COLOR: #000000; BORDER-RIGHT-COLOR: #000000" src="http://blogger.org.cn/blog/uploadfile/20058811959767.GIF" border=0></FONT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --------（又未完）------</SPAN></P>]]></description>
</item><item>
<title><![CDATA[google的使用]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=torrent&amp;id=7672</link>
<author>torrent</author>
<pubDate>2005/8/5 23:51:09</pubDate>
<description><![CDATA[<A href="http://blogger.org.cn/blog/more.asp?name=fermos&amp;id=7618">　引用地址</A>]]></description>
</item><item>
<title><![CDATA[设计模式（5）如何解决设计问题]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=torrent&amp;id=7668</link>
<author>torrent</author>
<pubDate>2005/8/5 19:05:27</pubDate>
<description><![CDATA[
<P>-----------设计模式翻译（5）￥￥￥￥￥（最近有点忙，不过还是要抽点时间弄完它）</P>
<P>------------------------------------------------------------------------------------------------------</P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=3>设计模式采用许多不同的方法来解决面向对象设计方面许多的问题。下面列出一些类似问题和用设计模式来解决的办法。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><A name=auto1069></A><B style="mso-bidi-font-weight: normal"><FONT size=3><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">发现合适的对象</SPAN><SPAN lang=EN-US><?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><o:p></o:p></SPAN></FONT></B></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><FONT size=3><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">面向对象编程的基础是对象。一个对象包括数据及处理数据的过程，过程又称为方法或操作。对象在接受到客户的请求</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Request</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">（或消息</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Message</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）执行某个操作。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=3>（发送）请求是使得对象执行操作的唯一方法；操作是改变对象内部数据的唯一途径。因为这些限制，对象的内部状态可以说是被封装，不能够直接访问，其表示在对象外部也是不可见的。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=3>面向对象设计最难的部分是将系统分解为对象，这因为多个因素的影响：封装、粒度、依赖、灵活性、性能、演变、可重用性、等等。这些因素都能影响分解过程，并常常存在冲突。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=3>面向对象设计方法学有不同的侧重点。你可以使用问题描述，列出所有的名词和动词，接着设计相应的类和操作；你也可以关注系统的协作与职责关系；或者对现实世界建模，再由分析到设计的过程中得出对象。常常可见到哪种方法最好的争论。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=3>设计中，很多对象都由分析模型而得出，但面向对象设计常常出现在现实世界中没有对应物的对象。有些是低级的类如数组，而有些则是高级的类，如，合成模式介绍了一种统一处理对象的提取（对象）就没有实际的对应物。对现实世界的严格建模只能反映当前的现实而不能反映日后的状况。在设计时考虑对显露出来的（）的提取是达成设计灵活性的关键所在。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=3>设计模式可帮你识别这种不明显的提取，以及能够捕获这种提取的对象。例如，在现实中不会出现的表示处理或算法的对象，在灵活的设计中是至关重要的部分。在策略模式中，描述了如何实现可替代的算法族；在状态模式中，对每个实体的状态表示为对象；这些对象在分析过程、甚至在早期的设计过程中很难发现，对它们的发现出现在其后的为重用和灵活性设计的过程当中。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><B style="mso-bidi-font-weight: normal"><FONT size=3><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">决定对象的粒度</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></FONT></B></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=3>对象的大小和数目各不相同。从底层的硬件到完整的应用，都能用对象来表示。那么，我们怎么来决定对象的粒度呢？</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><FONT size=3><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">设计模式也涉及到了这个问题。</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Fa&ccedil;ade</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">模式描述了怎么将一个子系统表示为一个对象；轻量</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Flyweight</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">模式描述了如何用最合适的粒度来支持多个对象；还有其它的设计模式描述了将某个对象分解到较小的对象的方法；抽象工厂和构建者模式产生对象，该对象唯一的目的就是构建其它对象；访问者和命令模式同样产生对象，其目的是向其它对象或对象组发送请求。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><A name=def-type></A><A name=def-subtype></A><A name=def-supertype></A><B style="mso-bidi-font-weight: normal"><FONT size=3><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">描述对象接口</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></FONT></B></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><FONT size=3><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">对象操作的定义是通过对象指定操作名、参数、和返回值，这些是一个操作的指定要素（</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">signature</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">），所有操作的要素集合被称为对象的接口。接口指明了可以发送给对象的请求的完整集合，任何匹配对象接口要素的请求将发送给相应的对象。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><FONT size=3><SPAN lang=EN-US><FONT face="Times New Roman">??</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">类型用来指明特定的接口。如果某个对象接受的请求定义在一个称为“</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Window</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">”的接口上，我们称这个对象具有“</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Window</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">”类型。一个对象可能有多个类型，不同的对象也可共有一个类型。对象的某部分可能具有某个类型特征，而其它部分确具有另外的类型特征。具有相同类型的两个对象需要共享它们的部分接口。接口中又能够包含其它接口作为子集，该接口的类型是被包含的接口的子类型</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">subtype</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，相应的，被包含的接口的类型是该类型的超类型</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">supertype</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。通常，我们说子类型继承了超类型的接口。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=3>接口是面向对象编程的基础，对象是通过其接口而为外界所知。不通过接口，无法了解和操纵一个对象。对象的接口没有描述它本身的实现细节，这意味着两个具有相同接口的对象可以具有不同的实现。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><FONT size=3><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">当请求发送到对象时，具体操作的执行依赖于请求和接受对象。支持相同请求的不同对象为了完成请求执行不同的操作。一个对对象的请求与对象的某个操作之间在运行时的联系称为动态绑定（</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">dynamic binding</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><FONT size=3><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">动态绑定意味着对特定实现的请求到运行时才提交。因此，知道了具备可接受某种请求的接口的对象，就可以编写出期望一个对象具备特定接口的程序。而且，动态绑定让你能够在运行时替换具有相同接口的对象，这种替换能力即多态性（</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">polymorphism</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">），它是面向对象的一个关键概念。多态性简化了客户的定义、减少了对象之间的耦合、并使得可在运行时改变彼此的关系。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=3>通过识别关键元素和递交给接口的数据的种类，设计模式有助于定义接口。某些设计模式将告诉你什么不应该放到接口部分，纪念品模式就是一个很好的例子，它描述了如何封装和保存对象的内部状态，以利对象在其后保存该状态。这一模式规定纪念品对象必须定义两个接口：一个限制性接口，使得客户能够保持和拷贝纪念品；和一个特权接口，只有原始对象有权使用，用来保存和抽取纪念品的状态。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=3>设计模式也描述了接口之间的关系。模式经常需要一些相同接口的类，或者，给某些类的接口加上限制。例如，装饰器和代理模式就需要装饰对象和代理对象具备与装饰和代理客户一致的接口。在访问者模式中，访问者接口必须反映所有类的对象，以便访问者访问。</FONT></SPAN></P>
<P><FONT size=3>---------------------------------------------（本节未完，留待下次）</FONT></P>]]></description>
</item><item>
<title><![CDATA[设计模式（4）分类及其分类标准]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=torrent&amp;id=6725</link>
<author>torrent</author>
<pubDate>2005/6/22 2:08:43</pubDate>
<description><![CDATA[<A><FONT size=2>　</FONT></A><FONT size=2> (设计模式翻译4)</FONT> 
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center" align=center><FONT size=2><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">设计模式目录</SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="FONT-SIZE: 14pt"><?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><o:p></o:p></SPAN></B></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><FONT size=2><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">此目录包含</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">23</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">个设计模式，在这里仅列出其命名（</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Name</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）和意图（</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Intent</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt; mso-char-indent-count: 1.71; mso-outline-level: 1"><FONT size=2><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US><FONT face="Times New Roman">Abstract Factory </FONT></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">抽象工厂</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></B></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>提供一个接口，在不说明具体类的情况下建立具有相关性或依赖关系的对象族。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt; mso-char-indent-count: 1.71; mso-outline-level: 1"><FONT size=2><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US><FONT face="Times New Roman">Adapter </FONT></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">适配器</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></B></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>将某个类的接口转换成客户所期望的另一个接口。适配器可使得接口本来不匹配的类在一起工作。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt; mso-char-indent-count: 1.71; mso-outline-level: 1"><FONT size=2><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US><FONT face="Times New Roman">Bridge </FONT></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">桥接</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></B></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN lang=EN-US><o:p><FONT face="Times New Roman" size=2>&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt; mso-char-indent-count: 1.71; mso-outline-level: 1"><FONT size=2><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US><FONT face="Times New Roman">Builder </FONT></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">建造器</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></B></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>将一个复杂类的表示与其构造相分离，使得相同的构建过程能够得出不同的表示。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt; mso-char-indent-count: 1.71; mso-outline-level: 1"><FONT size=2><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US><FONT face="Times New Roman">Chain of Responsibility </FONT></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">责任链</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></B></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>通过不止一个对象有机会处理请求的方式，消除发送者和接受者之间的耦合。将接受者对象组成链，请求发送到链，直到有对象处理</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt; mso-char-indent-count: 1.71; mso-outline-level: 1"><FONT size=2><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US><FONT face="Times New Roman">Command </FONT></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">命令</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></B></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>将请求封装成一个对象，这样可通过不同的请求来确定客户的参数，从而执行操作。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt; mso-char-indent-count: 1.71; mso-outline-level: 1"><FONT size=2><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US><FONT face="Times New Roman">Composite </FONT></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">合成器</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></B></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><FONT size=2><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">将对象组织成树结构从而表示部分</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">-</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">整体的层次关系。合成器模式可以使客户能够使用统一的方式来处理个体对象和合成对象。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt; mso-char-indent-count: 1.71; mso-outline-level: 1"><FONT size=2><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US><FONT face="Times New Roman">Decorator </FONT></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">装饰器</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></B></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>给对象动态添加额外的职责。装饰器模式为子类扩展功能提供灵活的选择。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt; mso-char-indent-count: 1.71; mso-outline-level: 1"><FONT size=2><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US><FONT face="Times New Roman">Fa&ccedil;ade </FONT></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">门面模式</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></B></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>为子系统的一系列接口提供一个统一的接口。此模式通过提供高一层的接口使得子系统更易用。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt; mso-char-indent-count: 1.71; mso-outline-level: 1"><FONT size=2><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US><FONT face="Times New Roman">Factory Method </FONT></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">工厂方法</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></B></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>定义一个创建对象的接口，而让子类来决定实例化哪一个类。工厂方法使得子类实例化的过程推迟。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt; mso-char-indent-count: 1.71; mso-outline-level: 1"><FONT size=2><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US><FONT face="Times New Roman">Flyweight </FONT></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">轻量模式</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></B></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>通过共享</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt; mso-char-indent-count: 1.71; mso-outline-level: 1"><FONT size=2><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US><FONT face="Times New Roman">Interpreter </FONT></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">解释器</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></B></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN lang=EN-US><o:p><FONT face="Times New Roman" size=2>&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt; mso-char-indent-count: 1.71; mso-outline-level: 1"><FONT size=2><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US><FONT face="Times New Roman">Iterator </FONT></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">迭代</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></B></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>提供一种方法，可顺序访问对象的元素而不需要暴露对象的底层表示。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt; mso-char-indent-count: 1.71; mso-outline-level: 1"><FONT size=2><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US><FONT face="Times New Roman">Mediator </FONT></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">解调器</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></B></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>定义一个对象来掩盖一系列对象的交互。通过不让对象显式引用，解调器模式促进了松散耦合，并使得可独立的改变交互。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt; mso-char-indent-count: 1.71; mso-outline-level: 1"><FONT size=2><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US><FONT face="Times New Roman">Memento </FONT></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">纪念品模式</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></B></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>在不违反封装的情况下，捕获对象的内部状态，使得对象以后能保存这一状态。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt; mso-char-indent-count: 1.71; mso-outline-level: 1"><FONT size=2><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US><FONT face="Times New Roman">Observer </FONT></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">观测者</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></B></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>在对象间建立一对多的依赖关系，当一个对象状态改变时，它的所有依赖对象能够感受到这种改变并能自动更新。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt; mso-char-indent-count: 1.71; mso-outline-level: 1"><FONT size=2><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US><FONT face="Times New Roman">Prototype </FONT></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">原型模式</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></B></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>详细说明对象的类型，用原型化实例建立对象，通过拷贝这个原型来创建新对象。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt; mso-char-indent-count: 1.71; mso-outline-level: 1"><FONT size=2><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US><FONT face="Times New Roman">Proxy </FONT></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">代理模式</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></B></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>提供一个代用品或占位符，使得其他对象能够通过对它的访问来控制实际对象。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt; mso-char-indent-count: 1.71; mso-outline-level: 1"><FONT size=2><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US><FONT face="Times New Roman">Singleton </FONT></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">独身模式</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></B></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>保持一个类只有一个实例，并提供一个全局访问点。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt; mso-char-indent-count: 1.71; mso-outline-level: 1"><FONT size=2><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US><FONT face="Times New Roman">State </FONT></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">状态模式</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></B></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>允许对象在内部状态改变时改变其行为。对象似乎能改变它所属的类。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt; mso-char-indent-count: 1.71; mso-outline-level: 1"><FONT size=2><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US><FONT face="Times New Roman">Strategy </FONT></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">策略模式</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></B></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>定义一组算法，并对每一个都进行封装，使得它们可以在内部进行替换。策略模式使得客户所用的算法能够独立改变。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt; mso-char-indent-count: 1.71; mso-outline-level: 1"><FONT size=2><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US><FONT face="Times New Roman">Template Method </FONT></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">模版方法</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></B></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>在一个操作中定义算法的纲要，将某些步骤延迟到子类中实现。模版方法使得子类能够在不改变算法结构的情况下，重新定义算法的某些步骤。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt; mso-char-indent-count: 1.71; mso-outline-level: 1"><FONT size=2><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US><FONT face="Times New Roman">Visitor </FONT></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">访问者</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></B></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN lang=EN-US><o:p><FONT face="Times New Roman" size=2>&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center" align=center><FONT size=2><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">模式的组织</SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="FONT-SIZE: 14pt"><o:p></o:p></SPAN></B></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>各种设计模式在其粒度和抽象级别上各不相同。因为有很多的设计模式，我们需要通过某种方式来组织它们。此部分对设计模式进行分类，以便于找出相关的设计模式，而且有利于发现新的设计模式。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><FONT size=2><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">我们以两个标准来对设计模式进行分类。其中一个标准，称为目的（</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Purpose</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">），反映了这个设计模式是干什么的。根据其目的（</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Purpose</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">），模式可分为创建（</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Creational</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）、结构（</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Structural</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）、和行为（</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Behavioral</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）。“创建性模式”关心对象的创建过程；“结构性模式”涉及类和对象的组成；“行为性模式”刻画了类和对象交互及分配职责的方式。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><FONT size=2><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">第二个标准，称为范围（</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Scope</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）。范围描述了模式主要是应用于对象，还是主要应用于类。“类模式”主要处理类与其子类的关系，这种关系是通过继承得来的，因此它们是静态</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">-</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">固定、由编译时决定的；“对象模式”处理对象关系，这种关系是运行时决定的，是动态关系。几乎所有的模式都在某种程度上使用了继承，因此只有那些标明为“类模式”的模式才重点关注类关系，大多数模式都在“对象模式”范畴。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN lang=EN-US><o:p><FONT face="Times New Roman" size=2>&nbsp;<IMG style="BORDER-LEFT-COLOR: #000000; BORDER-BOTTOM-COLOR: #000000; BORDER-TOP-COLOR: #000000; BORDER-RIGHT-COLOR: #000000" src="http://blogger.org.cn/blog/uploadfile/20056222508487.BMP" border=0></FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>“创建性类模式”将部分的对象创建工作延迟到了子类，而“创建性对象模式”将其延迟到了另外的对象。“结构性类模式”应用继承机制来合成类，而“结构性对象模式”则规定了装配对象的方式。行为性类模式用继承机制来描述算法和控制流，而行为性对象模式则规定一组对象如何合作以完成某项单一对象不能达成的任务。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><A name=auto1066></A><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>组织模式有另外的方式。有些模式通常在一起使用，例如，合成模式通常与重复模式或访问者模式一同使用。有些设计模式是可替换的，如原型模式常常替换抽象工厂模式。有些设计模式的设计是相似的，虽然它们各有不同的意图，如合成模式与装饰模式的结构图非常相似。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><A name=auto1067></A><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>另一种组织设计模式的方式就是按照它们在“相关模式”部分如何彼此涉及。下图描述了这些关系。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN lang=EN-US><?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" /><v:shapetype id=_x0000_t75 coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f"><FONT size=2><v:stroke joinstyle="miter"></v:stroke><v:formulas><v:f eqn="if lineDrawn pixelLineWidth 0"></v:f><v:f eqn="sum @0 1 0"></v:f><v:f eqn="sum 0 0 @1"></v:f><v:f eqn="prod @2 1 2"></v:f><v:f eqn="prod @3 21600 pixelWidth"></v:f><v:f eqn="prod @3 21600 pixelHeight"></v:f><v:f eqn="sum @0 0 1"></v:f><v:f eqn="prod @6 1 2"></v:f><v:f eqn="prod @7 21600 pixelWidth"></v:f><v:f eqn="sum @8 21600 0"></v:f><v:f eqn="prod @7 21600 pixelHeight"></v:f><v:f eqn="sum @10 21600 0"></v:f></v:formulas><v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"></v:path><o:lock v:ext="edit" aspectratio="t"></o:lock></FONT></v:shapetype></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 175.35pt; mso-char-indent-count: 16.7"><SPAN lang=EN-US><o:p><FONT face="Times New Roman"><FONT size=2>&nbsp;<SPAN lang=EN-US style="FONT-SIZE: 10.5pt; FONT-FAMILY: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-fareast-font-family: 宋体; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA"><v:shapetype id=_x0000_t75 coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f"> <IMG style="BORDER-LEFT-COLOR: #000000; BORDER-BOTTOM-COLOR: #000000; BORDER-TOP-COLOR: #000000; BORDER-RIGHT-COLOR: #000000" src="http://blogger.org.cn/blog/uploadfile/200562222329608.GIF" border=0><v:stroke joinstyle="miter"></v:stroke><v:formulas><v:f eqn="if lineDrawn pixelLineWidth 0"></v:f><v:f eqn="sum @0 1 0"></v:f><v:f eqn="sum 0 0 @1"></v:f><v:f eqn="prod @2 1 2"></v:f><v:f eqn="prod @3 21600 pixelWidth"></v:f><v:f eqn="prod @3 21600 pixelHeight"></v:f><v:f eqn="sum @0 0 1"></v:f><v:f eqn="prod @6 1 2"></v:f><v:f eqn="prod @7 21600 pixelWidth"></v:f><v:f eqn="sum @8 21600 0"></v:f><v:f eqn="prod @7 21600 pixelHeight"></v:f><v:f eqn="sum @10 21600 0"></v:f></v:formulas><v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"></v:path><o:lock v:ext="edit" aspectratio="t"></o:lock></v:shapetype></SPAN></FONT></FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 175.35pt; mso-char-indent-count: 16.7"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>设计模式之间的关系</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 175.35pt; mso-char-indent-count: 16.7"><SPAN lang=EN-US><o:p><FONT face="Times New Roman" size=2>&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>很显然，有多种方式来组织设计模式。拥有多种模式来考虑模式将加深对模式的理解，如该模式是干什么的、模式之间如何比较、何时运用该模式？等等</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN lang=EN-US><o:p><FONT face="Times New Roman" size=2>&nbsp;</FONT></o:p></SPAN></P>]]></description>
</item><item>
<title><![CDATA[贪官文化--中国传统文化讲义之五]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=torrent&amp;id=6680</link>
<author>torrent</author>
<pubDate>2005/6/19 2:50:26</pubDate>
<description><![CDATA[<P><A href="http://www.nugoo.com/club/read_elite1.php?id=171"><FONT size=3>　</FONT>转贴</A></P>
<P><FONT size=3>第五讲 中国贪官文化<BR><BR>　　 　写下标题，同学们可能就有疑问了：贪污是文化吗？我说，可能吧，因为在中国，贪污早成为一种文化现象了，再不客气点儿，我们甚至可以推断说，贪污文化是中国传统文化之一。<BR><BR>　　一、 寻找“贪”字早期的仙迹<BR>　　其一、“徇财曰贪，玷官曰墨”。见于宋代《册府元龟》卷307《外戚部.贪黩序》。<BR>　　其二、“贪以败官为墨”，见于《左传.昭公十四年》。<BR>　　其三、“贪夫徇财，烈士徇名”，见于《史记.屈原贾生列传》<BR>　　其四、“贪人败类”。见于《诗经. 大雅.桑柔》。<BR>　　从这些最早的有关贪的定义里，可以看出，贪官是以谋求财产为标志的，谓之“循财”。“玷官”是“有污点的官”，我觉得叫“脏官”最合适不过了，至于“墨”，其原意是指“贪污不廉洁”，可叫作“赃官”。这里我们就可以下定义了，贪官，是以追求财产为目的的官员，其表面是黑的，其本质是肮脏的。问题是这么一种肮脏东西自古就有，延续到今天，居然层出不穷，越涌越多，导致我们不得不把它列为文化现象之一种来进行研究了。<BR><BR>　　二、 贪官始于何时？<BR>　　其一、始于“汉时”。见顾炎武《日知录集释》卷13《除贪》。<BR>　　其二、“西周时已有贪污受贿的记载”。见刘泽华，王兰仲《论古代中国社会中的贪污》，载《天津社会科学》1988年第3期。<BR>　　其三、认为自“殷商以降，跟着私有财产制度和阶级国家的成立，贪污遂成为统治阶级的职业”。见翦伯赞《贪污列传序》，载《新华日报》1945年9月2日版。<BR>　　其四、贪官大约在原始社会晚期尧舜时期即产生，迄今已有五千年的历史了。 见周怀宇《贪官传》序。<BR>　　有关贪官起源时间，就这么四种说法.也许我这么一种排列方法很让人泄气：华夏文明有多悠久，那贪污历史也就有多悠久，华夏五千年文明史，伴随着五千年的贪污史！<BR><BR>　　三．传统贪污之手法<BR>　　贪污不外是贪钱，贪权，贪色这三样，现在的贪官不成器，在这方面也没有创新能力，时至今日,仍是钱，权，色三字。至于贪污手法，古今似乎也没什么大变化。这里，拣关键的说几种。<BR>　　其一、买官卖官<BR>　　现代国人比较实在，买官卖官就叫买官卖官，一点也不含糊，可古代比较文雅，不这么叫，客气地叫作“赀选”，“赀”，指财货，“纳赀”，指向封建政府交纳金钱或财物，拜官授爵。故“赀选”又叫“卖官鬻爵”。而国家政府，就是个大卖主。<BR>　　秦时，纳粟授爵。西汉文帝时，为了培养民众对于抵抗匈奴的爱国情操，政府“令边民入粟边”，拜爵，同时，又颁布纳赀钱可为官的法令。中国的卖官制从此大兴。更奇怪的是，这种卖官制始建的初衷竟是为了反贪：西汉初，中下级官吏俸禄不高，恐家贫者为吏，必贪，故也。按当时的行情，交钱十算(十万钱)乃得为官，有市籍的商人，不得为官，遂造成“贾人有钱不得为吏，廉士无赀又不得为官”的局面。景帝时，鉴于廉士寡欲易足，赀算四得为官，也就是说，皇家卖官打了折扣－四折，算是优待廉士们。《史记.司马相如列传》里说，司马相如“以赀为郎”，中国史料向来不屑于数字的精确，所以，一代名人司马相如到底用多少钱换来一“郎”之职，景帝给他打了几折，我们就不得而知了。至于汉代有名的清官张释之，居然也是“以赀为骑郎”，后升至廷尉，相当于现在的最高人民法院院长。卖官去当清官，可见古人为人民服务之觉悟甚高。<BR>　　武帝后期，自由民主之风甚炽，大开卖官之范围。东汉中后期，卖官几成国家财政主要收入。汉灵帝一代明君，在售官方面做到了公开透明，童叟无欺，在京城皇宫宫门外，公开贴榜，标价出售。《文献通考.选举八》载：崔烈出钱五百万买了个司徒，灵帝后悔打折太低了，说，我真有点后悔，太便宜了。《资治通鉴.卷58》载：钜鹿太守司马直是个清官，灵帝因“以有清名”而减价，让他出三百万钱升官。吴思给司马直算了一笔帐:太守相当于现在的省委书记兼省长，俸禄每年两千石，时价二千万，皇帝让司马直出钱三百万，便宜透了，打折不足二成。问题是，300万的钱相当于太守19年的工资总和，不打折，则相当于太守128年的工资总和。最后的结果是：司马直二折的钱也拿不出来，请辞，上不准，司马直自杀！<BR>　　到了清朝，　赀选改称捐纳。雍正时期担任过兵部尚书，刑部尚书，直隶总督的李卫，就是康熙年间捐纳出身的。详情参见《清史稿.李卫传》。乾隆时，每年卖官收入300万两白银，子比父强，嘉庆时则达到400万两。<BR>　　其二、买法卖狱<BR>　　在中国办案，靠的似乎不是律师的专业本事，而是非专业之外的交情，比如他给你办案，向你吹的，不是他自己的法律知识和辩才，而是他跟法官的交情。而这交情，一靠熟，二靠钱，我把它总结为买法卖狱。如果不信，请看方苞的《狱中杂记》。清朝文学家方苞蹲过中央级的监狱，遂成《狱中杂记》之名篇。篇中说：犯人临刑前，有人会找你谈心。如果是凌迟处死，刽子手可以先刺你的心，也可以先卸你的胳膊腿儿。如果是绞刑，可以一上架就断气，也可以绞上它个两三回。总之，一切全看你的意思了。意思够了，就给你来个痛快的死刑，意思不够，叫你生不如死，　死又不得好死。看了方苞的文章，你就会明白，电影武打里的死刑犯临刑前跟刽子手说的那一句“哥们儿，来点痛快的”，竟然全是虚的。如果没有银子打点，你临死找痛快，没门儿。马克思主义的传播者李大钊就是被缢了三次才死成的。　维新人士谭嗣同“死得其所，快哉快哉”的走上了刑场，他却不知，他的家人为了他能全尸，费了多大的周折。谭受的是“斩刑”，斩刑也有诸多讲究，一刀下去，头滚老远，痛快是痛快了，可家人不愿看见人首分离的惨象。如果一刀下去砍不死，需要再补一刀两刀的，更不是个意思了。最高级的斩法是，一刀下去，头断皮连，人即咽气。后人再出钱找人，用专业手法把死者的头与脖子缝到一块才好下葬。问题是，要想得到如此斩法，需重重的下贿钱，否则刽子手不干！<BR>　　一个社会，若出现上述两种贪污现象，整座大厦就完了。大家靠山吃山，靠水吃水，各种贪污小伎俩层出不穷，更关键的是，似乎也用不着什么伎俩，只要当个官就行，直接往家拿就是了。试举一例，淮军统领卫汝贵，临上朝鲜作战前，领饷22万，老小子一点也不含糊，先往家里送了8万。放我，顶多拿2万，一下子拆走三分之一强，老小子久在官场，贼胆当然比咱大多了。<BR>　　<BR>　　四、古代中国是如何反贪的<BR>　　<BR>　　其一、尧舜时期，中国即开始反贪了。要说明这个问题，我们得澄清三个侧面：其一，那时候是否有官员？其二，是否有反贪条例？其三，是否有贪官落马的事实？当然，如果能找到尧舜时期就有反贪局的史例就更好了。<BR>　　众所周知，尧舜时期的社会组织是一种松散的部落联盟，即我国原始社会中行将崩溃瓦解的父系社会晚期。其时生产力相对提高，产品有了剩余，占有剩余产品的私有制已逐步形成，为了维护这一制度，国家机器胚胎开始形成，氏族中的贵族阶层联合起来，设立百官,统称为“百姓”。《尚书.尧典》上有“平章百姓”的记载，含义就是“处理百官事务”，同时还记载制订了“五刑。尧用舜作自己的辅佐大臣，舜修订并放宽了“五刑”，用“流”放代替死刑，同时在“五刑”中确立“官刑”，说明当时对官员有了专门的约束。不服从“官刑”，就要受到处罚，怎么处罚，《尚书.尧典》记载说：鞭作官刑。孙星衍解释其含义为：在官有禄者，过则加之鞭笞。其实不用解释大家也能猜个八九不离十，不外是打屁股罢了，估计跟明朝的“廷杖”差不多。《左传.文公十八年》里记载，春秋时鲁国史官太史克讲述了尧帝时有一个反贪故事：缙云氏有不才子，贪于饮食，冒货贿，侵欲崇侈，不可盈无。聚敛积安，不知纪极，不分孤寡，不恤穷匮，天下之民以比三凶，谓之“饕餮”，舜臣尧，宾于四门，流四凶族，浑敦，穷奇，梼杌，饕餮，投诸四裔，以御魑魅。这话翻译过来，就是这个缙云氏不才子太不象话了，贪侈过分，既不“三讲”，也不够“三代表”，就被流放到边远地方打鬼去了。<BR>　　舜为帝时，也处置了一个贪官，名叫伯封。《左传.昭公二十八年》里这样描述他：实有豕心，贪婪无餍，忿类无期，谓之封豕，有穷后羿灭之。这话翻译过来就有意思多了，说伯封贪得象猪。不过，时至今日，拿贪官比作猪，实是对人家猪类的一种侮辱，对不起了，猪们！<BR>　　禹建夏，由法官皋陶作《禹刑》，也叫《夏刑》，里面仍有惩贪条例。春秋时鲁国大夫叔向处罚贪官羊舌鲋时，援用的就是夏刑，说：昏，墨，贼，杀，皋陶之刑也，请从之。最后叔向是这样给羊舌鲋定罪的：贪以败官为墨，羊舌鲋被论“墨”罪，杀，弃尸于市。<BR>　　其二、殷商时不任用贪官。商朝初建，继承古代“鞭作官刑”，制订《官刑》。《尚书.伊训》载：制官刑，儆于有位…敢有殉于货色，桓于游败，…卿士有一于身，家必丧。这话翻译过来更有意思了，苦口婆心的，跟咱们现在的政府反贪一个腔调，连哄带吓：贪财，贪色，贪出国游玩，身为官者，占其一，就把一个原本幸福的家庭给毁了！<BR>　　盘庚是最注重反贪的一位人民领袖，《尚书.盘庚》载盘庚一段话：兹予有乱政同位，具乃贝玉，作丕刑于朕孙。朕不肩好货，敢恭先生鞠人谋人之保居，叙钦！今我既羞告尔于朕志若否，罔有弗钦。无总于货宝，生生自庸，式敷民德，永肩一心。盘庚的话翻译过来是这样的：我不任用贪财之人，那些为人民服务为人民谋幸福能让人民安居乐业的干部，我将按贡献的大小依次任用。今天我把自己的主张告诉你们，就是希望你们听“党”的话，不要贪恋身外之物，要努力为人民服务，认真贯彻落实“三个代表”的精神，紧紧团结在以我为核心的皇中央周围，以德治国，与时俱进。<BR>　　其三、西周出现惩贪法。周穆王时期，吕候制《吕刑》，内有“五刑”，“五罚”，“五过”，“五疵”。“五疵”里就有两条有关贪污的，一是“唯货”，二是“唯赇”。“唯货”是贪，“赇”也是贪，因为“赇”字可以理解为“求贝”，当然，“赇”也可能是早期的贿赂，因为“赇字”也可以理解为“以贝相求”。<BR>　　其四、春秋时贪污泛滥。上梁不正下梁歪。周王任用贪官，各诸候国君也以身作贼，带头贪污，下面小官小吏竞相效尤，贪风甚炽。《诗经》里的名篇，如《硕鼠》《伐檀》等，皆有刺贪之意，约相当于现在的民谣，一句话，政府反贪不力，民谣即兴，古今一理。<BR>　　其五、封建社会反贪。<BR>　　汉代开始惩治官吏的经济职务犯罪，有两条刑律：主守盗，受赇。前者，利用职务盗窃国家物资人；后者，惩治官吏枉法受贿行为。从行政制度上，汉文帝规定“官吏以饮食免”，相当于现在中央政府禁止大吃大喝之类的红头文件，用意相同，唯一的区别是，现在的官吏可以四菜一汤的小吃小喝，而文帝的规定就严多了，上级官吏吃下级官吏一顿饭，免！汉元帝时规定：坐赃者，皆禁锢不得为吏，意味着贪官一但事发　，政治生命从此结束，尚没有出现如今易地为官的变通之法。到了东汉时，规定更严酷：赃官子孙，三代不得为官。<BR>　　宋代重视反贪，赵翼云：宋以忠厚开国，凡罪罚悉从轻减，独于赃吏最严。王安石也说：今朝廷之法所尤重者，独贪吏耳。行政上，宋设反贪局，时称武德司，皇城司。神宗时，更是重禄重法，一边给公务员增加工资，一边加大法制建设，两手齐抓，不过，也没发现有什么效果。到了元代，官吏赃罚，轻则打屁股，重则处死。明代，由于朱元璋同志出身贫苦，了解劳动人民的不容易，所以，反贪决心最大，力度也最强：赃至六十两以上者，枭首示众，仍剥皮实草…官府公座旁各悬一剥皮实革之袋，使之触目惊心。元璋同志还经常在地方官上任之间，与之谈心，告诉他们如何对待低工资，如何反贪拒腐防变，可谓是语重心长和譪慈祥。为反贪，元璋同志甚至不惜始创特务政治，让特务们监督官员，残联同志－太监们也参与了反贪，太监是皇上最后的武器，太监不好色，没有老婆，没有儿女，一人吃饱全家不饥。但效果还是不甚理想，元璋同志就有点不耐烦：我想清除贪官污吏，奈何早上杀了，晚上又有犯的，今后犯赃的，不分轻重都杀了！元璋同志忘了，老子云：“官”不畏死，奈何以死惧之？元璋同志当皇帝当到第18个年头，终于发出了如下感叹：朕自即位以来，法古命官，布列华夷，岂期擢用之时，并效忠贞，任用俱久，俱系奸贪。（参见《明朝小史》卷二）。皇帝不明白，为什么自己提拔重用的人，当官久了，都成奸贪之人了。他整不明白，我们更不明白了。洪武二十五年，元璋同志颁行《醒贪简要录》，这东西虽然无缘得见，但估计跟我们一度流行的，政府提倡官员们携妻观看的《生死抉择》《大雪无痕》相类似，也就是给正在贪污的同志们提个醒，没别的意思。<BR>　　英明如雍正，乾隆，也对反贪无可奈何，无奈中，始创养廉银。养廉银制是年羹尧提出的，但年同志是个大大的贪官，这个大家都知道的。如今，我们一直嚷嚷着给公务员加薪，估计内里也有个养廉的意思，当然，给公务员重发养廉银的呼声私下里也有。只是大家忽略了一个前提条件：人性的欲望是无限制的。<BR>　　于是乎，古代反贪，出现了以下几种怪现象：第一，越反越贪。据有关人士查史料，有关贪污之记载，远古至先秦，78起。秦汉至唐末五代，460起。宋代包黑子云：赎货暴政，十有六七。宋末，更是廉吏什一，贪吏十九。明代，《明史》载：贪官污吏遍布内外。清初，林起龙奏称：今贪官污吏遍天下。当今，老百姓编的名谣也挺好玩的：把当官的挨个儿枪崩，肯定有冤枉的；隔一个枪崩一个，肯定有漏网的。第二，越贪越狂。东汉汉桓帝的弟弟勃海王刘悝向宦官王甫行贿五千万钱。敢接皇帝弟弟的贿赂钱，够狂；明代隆庆皇帝登基前三年，达不到皇上的“例有赐给”，不得不向权贵严世蕃馈赠银子1500两。敢接皇子的贿赂钱，更狂了；清代年羹尧事败抄家时，抄出现银百十万两。有人计算，当时省级大员年俸150两银子，年家的现银就相当于7333个省级大员的年俸收入，也够狂的。至于和珅，财产多到没法计算的地步，大家只约摸知道：和珅跌倒，嘉庆吃饱。至于嘉庆吃撑着了没，大家也不得而知，后来梁启超给统计出一个数字：和珅家产八亿两，相当于清政府十年的财政收入，和大人简直是狂贪无边了。第三，贪中反贪。现代也有人提醒，要警惕用腐败的方式反贪，其实贪中反贪古已有之，我们再警惕也没用。仅举一例：山东巡抚陈祖辉，贪。乾隆令浙江巡抚王亶望前去反贪。王反着反着，自己就私吞了一部分。事露，再派和珅前去反贪，和珅又私吞了王家一部分财产，并猎获王家绝色少妾吴卿怜居为己有，改用一句歌词，可谓是“贪污着你的贪污，腐败着你的腐败”。<BR>　　下面我们分析一个问题，封建统治者反贪决心与力度不可谓不大，为什么贪污却不可遏止呢？按我的看法，有以下几种原因：<BR>　　其一、端坐于金字塔顶端的最高统治者及其家族，本身就是一个最大的贪污群体。皇家的排场，奢侈与权威，对下层官员构成一种致命的威胁，同时也可以说是一种致命的诱惑。否则项籍与刘邦不会在看到始皇的仪仗后，一个脱口而出“彼可取而代也”，一个悄悄的立志“大丈夫生当如此也”。总之，皇家集团的存在，恰好构成了贪官的榜样。领袖说过：榜样的力量是无穷的，这话太正确了。历史上的贪官惩而不绝，前仆后继，皇家的示范作用不可低估！<BR>　　其二、庄子云：窃钩者诛，窃国者候。<BR>　　这话也太正确了。皇家与它手下庞大的官僚集团，同属一个窃国团伙，两下里联合统治，剥削人民。遗憾的是，大盗小偷之间各层次经常出现分赃不均的情况，比如《史记.萧相国世家》载：汉五年，既杀项羽，定天下，论功行封。群臣争功，岁余功不决。看看，打完天下后，兄弟们光争功就争了一年多。当然了，以后的和平日子里，分赃争斗的主要表现形式，当为贪污与反贪。总之，皇家统治比较强大的时候，贪污有所收敛；皇家统治比较薄弱的时候，贪污比较嚣张。新王朝初期较好，王朝末世最糟。<BR>　　其三、专制制度与官僚体制，是造成贪污不止的组织与技术原因。西哲云：有多大的权力，就有多大的腐败。吴思更是感叹：恶政下，皇上也是冤大头。也就是说，制度与体制的原因，导致皇帝也无可奈何。朱元璋有此体会，康熙更是黑天白夜的为此发愁。打一个比方，肉是臭的，却不想让它生虫，成吗？<BR>　　其四、中国封建社会，没有确立个人财产私有与私有财产神圣不可侵犯的原则，这导致有钱阶层缺少扩大再生产的动力与保障，至于有权阶层，更是今朝有酒今朝醉。社会之财，缺少理性的使用与法律的保障，它除了供有权有钱阶层醉生梦死疯狂消费之外，似乎无其它用处。德国社会学家马克斯.韦伯曾分析过新教伦理与资本主义精神的内在因果关系：清教徒不反对合理的获取财富，只反对非理性的使用财产－当消费的限制与获利活动的自由结合在一起的时候，产生的一个不可避免的后果就是资本的积累。很不幸，中国的封建体制恰恰是将消费的无限制与权力活动的自由结合到了一起，其后果就是不可避免的贪污！<BR>　　其五、统治阶级对官僚集团推行以德治国之教化，但历史证明，这种教化是失败的。马克斯.韦伯认为：历史上每个统治集团都希望使自己的统治具有合法性，他们追求合法性的手段有两种，一种是通过强制手段，一种是通过意识形态的调整与灌输。中国封建社会的统治者兼用两种手腕，先用武力夺取政权，或者说夺取政权的时候，就搞出诸多“篝火狐鸣鱼腹丹书”之类的君权神授来，至不济，也要搞个出生时“天降流星，祥云绕梁”的把戏。象刘邦那样的无赖，居然也是刘大妈在野地里神龙附体搞出来的。这把戏多了，傻瓜都不信了，何况读书读到死的官僚集团？皇家是什么东西，官僚们心知肚明，所以，当皇家号召官僚们“武官不惜死，文官不爱钱”时， 我不知道，官僚们是如何在肚里冷笑不已的，我只知道，大家伙谁也不傻，导致上层统治者的道德呼唤，撞到了历史的厚墙之上，我们只听到了空洞的回声！<BR>　　其六、某种程度上，最高统治者希望手下有点小小的贪心，否则，统治者就寝食难安了。仅举一例，《史记.萧相国世家》载：汉高祖刘邦在前线灭黥布的时候，后方仅靠萧何一人。萧何把后方的政治军事做得非常好，刘邦这无赖反而不放心了，“数使使问相国何为”。萧何因为刘邦在外统军，就全力安抚百姓，甚至把自己的全部家产捐出佐军。一门客对萧何说：坏了，老大要怀疑你了。你身为相国，功第一，还一直这么做好事，得民心，皇上能放心你吗？这幕僚建议萧何做些问舍求田自贱其名的事儿。司马迁惜字如金，只说“相国从其计，上乃大说”，但我们不难想象，肯定有人给刘邦告密，说萧何侵占民田，霸占民房，刘邦这小无赖一听，估计俩小眼儿马上笑成了一条缝儿：好啊，萧何原来只是个贪官，并无“彼可取而代之”“大丈夫生当如此”之类的意思。嘿嘿。放到现在，我们一些单位在搞张榜捐款的时候，也有类似的微妙。比如现在流行的摊派性质的捐款，书记捐五百，科长就只敢捐三百二百的，捐多了，什么意思嘛，想当书记还是咋的？所以，偶而贪污一下，反而是在向上级表忠心：看看，哥们儿胸无大志，只图个吃喝，绝无二心，领导你就放心吧！一句话，有时候你不贪污还不行，愣要当什么清官好官，领导往哪里摆？<BR><BR>　　五、古今贪官对比<BR>　　赖昌星红楼案发后，顿使人有今夕何夕之恍惚：古今贪污，居然惊人的相似。但是有心总结一下，会发现，古代贪官更不容易：<BR>　　其一、古代贪官不象现在的贪官，从小接受了唯物主义的思想教育，相反，他们只有一个唯心主义，信鬼神，信因果报应，所以，要他们伸出罪恶的手来贪污，是需要一定的勇气的－“我不下地狱谁下地狱？”<BR>　　其二、古代不流行纸币，贪官们要贪，总是些金银珠宝类的东西，这些东西，比起现在的存折，支票，股票来，那是笨重多了，既无法藏到卧床的铁栏杆里，也无法匿到烟酒盒里，总之，古代当贪官，风险也太大了。<BR>　　其三、古代法律野蛮落后，不讲理。哪象现在，法律文明，且具人情味儿，往往是一人贪污，幸福全家。而古代呢，一人贪污，全家没收不说，弄不好，还株连九族，所以，古代要想贪污，不下狠心是不行的。<BR>　　其四、古代贪官根本不知华夏之外，尚有其它文明国度，所以他们不会脚踩两只船，不会一家两制，不会一人在国内贪污，全家在国外定居，至不济，也要提前办好撤退的护照，一有风吹草动，敢紧脚底抹油－溜之乎也。古代贪官，搂着大堆的金山银山，不知逃向何处，不知奔向何方，又没有洗黑钱的可能，很悽惶的。<BR>　　其五、古代贪官缺少表演才能，更无机会借助现代高科技手段制造清廉魔术。比如成克杰，在中央电视台“东方之子”节目中，一提灾区百姓，那是声泪俱下：看到灾区人民受苦受难，我真不好受啊，这些人也是爹娘生的，也是有血有肉啊，我也是爹娘生的，也是有血有肉啊，他们好苦啊…我要书写一些老百姓永远不会忘怀，认为我没偷懒，正为努力为他们作贡献的历史，当然，我绝不会书写相反的历史。这镜头，若让古代贪官得知，他们当会脸红不已的：一提老百姓，眼睛就出水，这功夫咋学的呀！<BR>　　其六、古代贪官口才不怎么样，也不机伶。一代巨贾兼贪官胡光墉，事发后也只会怅然逝去，既不会糟踏老百姓－说什么放松了对自己的要求，把自己混同为一般的老百姓了，好象老百姓都是大贪似的；更不会糟踏人家资产阶级－说什么自己受了资产阶级腐朽生活方式的影响。总之，古代贪官要想忏个悔，找个堕落的借口，不如现代贪官容易。<BR>　　当然，古今贪污也有类同之处，比如一犯一窝，古今类似。乾隆1781年，王亶望一案，同案犯70人，处死22人。现代，沈阳慕绥新一案，跌倒16人。还有，河南一个小小的卢氏县，一下子双规80名干部，其中，全县19个乡镇党委书记无一幸免，全部一锅端了。只不过，现在流行人道人权，现代贪官们被处死的机会远远小于古代贪官了。<BR>　　六、我的看法<BR>　　其一、人性的原因。关于人之初，性本善还是性本恶，作为哲学命题，我们争论两千多年了，可是作为政治命题，我们却一厢情愿地认定人之初，其性本善的，所以我们的所有政治及其相关建设都是基于这么一个前提而成立的，导致我们古有“敬德保民”，现有“以德治国”。也就是说，所谓的“以德治国”，绝对不是什么新鲜玩艺儿了，我们古代的帝王就用它当过尿布了，现在还拿它做尿布，我们能闻到一股股千年的尿馊味儿，如果你闻不到，可能是你感冒了啊。更何况，老圣人也曾经有过怀疑的，说：吾未见好德如好色者也！并且进一步说：食色，性也！荀子认为，人之初，性本恶，只有通过教育，才能走向善。而韩非子干脆认为，人再怎么教育，人性还是恶的，所以他老兄搞的是恶狠狠的“法制”。善恶论争论几千年了，这里我不想陷于争论的泥沼，我有我自己的说法：人之初性本贪！中国改革基金会国民经济研究所所长樊纲先生在2002中国企业领袖年会上提出：我们不否定道德说教，但是作为经济学者，我们首先注重的是制度。而且我们制度的设计和制度的建设一定要以人道德不好为出发点，要以人之初性本恶为出发点。当然我不是假定人之初性本恶。<BR>　　樊纲不想假定人之初性本恶，但随后却说出了这样一句话：人的本性是贪婪的。马克思曾这样概括资本的特性：一旦有适当的利润，资本就胆大起来，如果有10%，就被到处使用，有20%的利润，它就活跃起来，有50%的利润，它就铤而走险，有100%的利润，它就敢践踏人间一切法律，有200%的利润，它就敢犯任何罪行，甚至敢冒绞首的危险。资本的背后是人，资本的特性，说穿了就是人性。<BR>　　人性是贪婪的，而贪官，却是大大发扬了人之初的本性。所谓的人之初，一是指人类的幼年，二是指人的幼年。我们的贪官当是两种幼年病的综合－第一是还没有进化完整；第二是还没有长大。去年我曾写篇杂文，当然没地儿发表，只能发到网上，题目就是“要把贪官当孩子”，说的也是这么个意思。三岁以下的孩子没有你我观念，见什么东西都以为是他的，特别是在商场里。三岁以下的孩子撒尿不找厕所，以为处处都是厕所，理直气壮地随地便溺。我们的贪官，便都是三岁以下的孩童了，如果按时下流行的说法-政府是爹党是妈来讲，这些贪官，确实需要其爹娘来管教了，否则，永远长不大，永远不进化，也不是个事儿。<BR>　　其二、制度与体制的原因。众所周知，美国建立三权分立的政体是基于这样一个前提：人性是恶的，不相信某一个政党，也不相信人民，将权力交给一个机构或一群人，只会导致完全的暴政，有多大的权力，就有多大的暴政，对掌握权力的人，应该深怀戒心。而中国封建社会恰恰相反，所有制度建设，都基于人性善这一前提，把希望寄托到读书人的忠孝贤良，寄托到帝王的英明决断。现在，中国人民又把希望寄托到一个政党的良心上，而这一个政党的又把希望下放，寄托到全体党政干部的良心上。这种寄托，导致对专制制度与官僚体制温情的默许与浪漫的幻想，而贪污，又是专制与官僚体制下的必然伴随物。<BR>　　其三、社会的原因。一般的看法是，中国社会是一个不道德的社会，但是组成分子，每一个人都可能是道德的。也就是说，道德的人构成了不道德的社会。这种不道德的社会中，最常见的形式是“不道德的家族主义”，西方学者认为，不道德的家族主义会引起腐败，促使人们偏离普世主义和行善的规范。也有人从另一方面说，中国人只讲私德，不讲公德。也就是说在他自己的亲友圈里，在他的私人圈子里，他是道德的，守信的，颇富人情味的；可一旦越出了这个圈子，他就可能不道德，不守信，甚至没有人情味。比如一个人对朋友慷慨大方，于私，他可能是个很好的朋友；但是于公，他却不是个合格的公民，因为这哥们儿老在偷税漏税。试举一个例子，韩信当年落魄时，曾受一漂母饭恩，发达后，韩信给漂母送去千金。打一个比方，如果这漂母是个生意人，或者是个包工头，韩信肯定会给她拉点活儿的。不信看胡雪岩，当钱庄伙计时，挪银五百两给落魄仕人王有龄，王用这些银子进京活动，一活动，就任了浙江省的粮台总办，从此与胡雪岩官商勾结，胡的红顶商人生涯从此起步。王死后，左宗棠本想查办胡，可两人一见钟情，竟成了好友。就连骂胡“确系坏种”的李鸿章后来也改变了看法，认为胡“救灾恤邻，慷慨好义”“为近时所罕见”，甚至要求政府准许“赏给匾额一方”以资鼓励。中国谚语云：受人滴水之恩，当以涌泉相报。又云：解衣衣我，推食食我，死人之事。太可怕了，一衣一饭之恩，需要的时候，就要为恩人奉献自己的性命了。举一个例子，常胜将军吴起曾经为一个士兵亲吸毒疮口上的脓汁，依现在的看法，你会觉得吴起犹如共党干部，爱兵如爱子。可是那士兵的娘却不这么看，听说这事后就开始哭，哭得死去活来。别人劝她：你儿子遇到了这么好的将军，你应该引以为荣才是，何以失声痛哭？老太太说：你们有所不知。我儿子的父亲，当年也曾由吴起将军亲自吸吮过脓汁，不久出战，想对将军的恩情有所报答，奋力抗敌，有进无退，终于战死了。如今吴起将军又这样对我儿子，我儿子肯定活不长了，我是为我儿子哭的呀！同志们，明白了吧？我这人老是不愿意对人太好，否则大家都掂着脑袋来跟我交朋友，那我不是要人家的命吗？叫我如何承受？这是开玩笑啊。总之，中国人身处的环境，是一个人情亲情乡情友情之网，没有一定的定力，你是摆脱不掉的。也许正由于中国是一个人情社会，最高统治者才怂恿出一个所谓的大义灭亲思想，大义灭亲大约来源于孔子。当春秋时晋国的叔向为自己的异母弟－贪官羊舌鲋定罪时，远在鲁国的孔子听了，赞扬说：治国制刑，不隐于亲！这一点，恰于西方相反，西方社会没有人情，但法律却基于人性之常情，认为亲人必袒护亲人，所以，西方社会不倡导大义灭亲，法律里便也没有包庇罪。<BR>　　讲到这里我就感觉，我们中国是一个很奇怪的社会：我们中国人最讲人情，可由中国人组成的这个社会却泠漠无情；我们中国人最讲亲情，可法律却提倡大义灭亲。贪官最遭老百姓忌恨，可贪官周围的人却喜欢他赞扬他；清官最遭老百姓喜欢，可清官周围的人却恨他恨得牙痒。有时候我都想，让一个骂贪官骂得最狠的百姓与贪官结了亲家，那么，随后会发生什么事情呢？<BR>　　有人说，中国的贪官，是有着群众基础的。此话值得我们深思。<BR>　　其四、管理方面的原因。曾有人说，中国百姓是世界上最无能的主人，管不好自己的财产，老被仆人偷。这一点，军阀孙传芳都看穿了。民国时期，也提倡人民公仆来着，而孙传芳反对这种提法，说：现在做官的自称是人民公仆。凡是仆人没一个好东西，不是赚主人的钱，就是勾搭主人的姨太太，我不是公仆，我是父母。天下父母，没有不爱子女的，爱民如爱子才是，才能真正为人民谋福利，做好事！老孙说得有趣，但是主人看不好仆人却是真的。而政府作为管家，在管理仆人时，也常常出现漏洞。朱元璋时代，也有自己的反贪局，当时叫监察御史，但大家都知道，那是聋子的耳朵，摆设！<BR>　　我经常跟人开玩笑，说，民国时期某军阀，三不知：不知自己多少兵，不知自己多少钱，不知自己多少姨太太。而我们的政府竟然也是三不知：不知自己多少人民－古代是逃人丁税，现在是逃避计划生育罚款；不知自己多少钱－帐上有数字，但实际钱在哪儿？银行都是呆死帐，行长更有卷资外逃的，帐上有的钱都是空的；不知自己多少贪官－政府知道自己多少官员，但永远不知道自己多少贪官，就跟军阀不知道自己多少姨太一样！<BR>　　一个俄国人，有60万卢布就要受到怀疑；一个美国人，有2000美元，就要说清楚－出具资金来源报告。后来放宽到1万美元。而中国，直到现在仍没有类似的规定。2000年4月，中国开始实名储蓄制，但贪官也会变通，国家能搞一国两制，贪官就会搞一家两制。公职人员不得经商，但公职人员的家属总能经商吧，所以，连云港的副市长<BR>　　鹿崇友，其80岁的父亲与70岁的母亲可以合资开个化工厂，可怜鹿老头，估计是没孙子，否则他那市长儿子也不舍得搬老子下水这么老当益壮的。<BR>　　其五，文化的原因。美国学者西摩.马丁.利普塞特和他的助手加布里埃尔在《腐败，文化及市场》一文中指出：腐败的程度往往是沿着文化界线而变更。最腐败的国家包括印度尼西亚，俄罗斯，以及若干拉美国家和非洲社会。在北欧和前英国殖民地的一些新教社会，腐败程度最低。儒学社会大都居于中间。讲到这里我长出一口气，美帝国主义学者眼中，好歹我们不是腐败最严重的。那么中国文化与贪污腐败之间的逻辑关系到底如何？特别是中国文化丰富多彩，三教九流的，这需要好好的梳理一番，同学们若有兴趣，不妨研究一下。这里我简单谈一下自己的看法。我认为，中国人选择贪污与腐败，其背后的终极原因乃是人的价值观在起决定作用。第一，家族价值观的影响。可以说，2500年前的柏拉图就看出了家庭在社会中的力量，所以他提出，要建立一个平等的共产的社会，必须废除家族联系，甚至家庭本身。孩子们一出生就应该交给公共机构养育，而不知其父母是谁。这话好象专门是针对咱们中国这个传统的儒学社会的，因为儒家特别强调家族观念。而家族主义在西方学者眼里是不道德的，虽然中国曾有过“外举不避仇，内举不避亲”的千古美谈，但那仍免不了作秀的嫌疑，比如人家袁世凯立自己的儿子为太子也可以被人称颂为“内举不避亲的”。西方学者甚至认为，意大利的黑手党乃是不道德的家族主义的一个极端的例子。以此类推，你会发现，中国封建社会中，大都是这种家族模式，《红楼梦》中，王，贾，薛，史等大家族，蒋光正时代蒋宋孔陈等大家族，都是强强联合。但是这种联合，之所以说它不道德，乃是由于这种家族主义，充其量只是个人及个体生存的有效手腕，但却无助于社会的前进，甚至是社会发展的障碍。所以我要说，中国的每一个大家族，其本质特征可能跟黑社会一个性质，当然这需要证明，同学们感兴趣，不妨做点工作。第二，个人价值观的影响。罗伯特.默顿在其《社会理论与社会结构》一书中提出了腐败的“手段－目的模式”，他认为，腐败是由动机促成的行为，来源于社会压力，结果则是违背规范。他强调，所有的社会制度都规定有自己文化上的目标，即目的。人作为社会行为者应力图达到这些目的。问题是，怎么达到这些目的，社会没有给出相应的体制规范，或者说，即使给出了，这些体制规范也都是疲软无力的，比如封建社会的反贪措施，这就导致大家共同拒绝遵守表面上的冠冕堂皇的游戏规则，进而衍生出一种私下里共认的游戏规则，吴思把它称作“潜规则”，在这种社会里，大家只认同个人的政治成就与经济成就，科举制时代，人们侧重前者；现在的时代，人们更侧重后者。侧重前者，买官卖官流行；　侧重后者，贪污贿赂盛行。如今，我们过分渲染强调个人的经济成就，导向有点偏差。大里说，它是不发达社会的一种心态，现在的经济发达国家，已富裕的公民由原先的物质主义者转变为后物质主义者，也就是说，他们更追求音乐，艺术和文学的享受。小里说，它会导致个人价值观的畸形发展，比如笑贫不笑娼，笑清不笑贪的社会心态。现在的大学生也比以往更加躁动不安，因为媒体与社会过分渲染了商界精英的成就与价值，大家更多的考虑如何奔向这个目标，手段的合法与否，似乎已不在考虑范围。第三，宗教与哲学的原因，严格意义上来讲，中国没有宗教。宗教的三大标志是：人格神的崇拜与敬仰；完备的宗教仪式；终极关怀的托咐。宗教的根本特质是终极关怀，人是什么，人从何处来，又将归向何处去。中国宗教对这一切，闭口不谈。而中国哲学中，也没有人关心这些问题。尼采曾讥笑中国的孔儒哲学是庸俗的道德把戏，黑格尔甚至这样认为：所谓的中国哲学并不是真正的哲学，在世界哲学史上无足轻重。孔子哲学只是一种“道德哲学”一种常识道德，这种常识道德我们在哪里都找得到，在哪个民族里都找得到，可能还要好些。这是毫无出色之点的东西，孔子只是一个实际的世间智者。在他那里，思辨的哲学是一点也没有的，只有一些善良的，老练的，道德的教训。两位洋老兄对中国哲学评价如此之低，原因何在？同学们若有兴趣，不妨研究一下。不过我有一个主意，大家不妨看一些有关西方传教士来中国传教的历史资料，以及一些教案的内在原因。其实，中西冲突中，一般包含两个认知层面：政治的和文化的。遗憾的是，我们一般的史学教学，只侧重天于前者，侧重于道德评价，而忽略后者，忽略文明本身内在发展的历史逻辑。所以，我希望同学们有一个全方位的文明视角，基于这个视觉，去考察文化与贪污，宗教与廉洁的内在关系，可能会有新的发现。这方面我只有零星的看法，但尚不系统，有待于同学们自己发掘。<BR>　　其六、成本的原因。德国社会学者马克斯.韦伯认为，中国之所以贪污严重，乃是因为中国官员当官成本太高。韦伯没有详细分析中国官员当官都需要付出哪些成本，但是我们不妨给官员们算一下。1、从时间上来讲，中国官员需要寒窗十年，甚至不止十年。有些人一辈子都挤不进官场里去，比如蒲松龄，十九岁就考中秀才，一直考到七十二岁，也没有考上个举人，曾写诗自叹：“数卷残书，半窗寒烛，冷落荒斋里”。这个大才子一辈了学优不仕，只好与自己书中的鬼们打交道去了。还有洪秀全，屡试不中，就反了。如果清廷知道他考不上就要反，可能提前给他一个七品官当当呢。而按照秀全同志日后当天王时的作派，我们倒可以断定，这哥们不当官则可，一当准是个大贪。2、从读书苦的程度来讲，中国书生之苦当是天下第一，这方面，头悬梁锥刺骨的苏秦可谓是榜样。读书本是享受，却愣被这帮哥们鼓捣成了苦行僧一般，“学海无涯苦作舟”，完了，这小舟怕是永远驾不出去了。3、当官也苦啊。走进官场，那只是万里长征的第一步。如何在官场那乌泥堆里站稳脚跟，才是问题的关键。龚自珍倒是科场得意，20多岁就在北京做官，可官场学问，敢情比书里的学问难多了，龚大才子玩不转，最后的选择是弃官归里，回家时就雇了两辆车，一辆拉自己，一辆拉自己心爱的书。你说才子都回家了，其他官员还挺着干什么？按吴思的考证，林则徐那时也有灰色收入呢。4、按我的意思，当官最苦的不是科考，而是心灵的代价，轻里说，尊严丧失，重里说，人不再是人。一句话，在中国官场上混，上级面前没有点装孙子的本事，却想在官场里继续混下去，或提拔上去，永远没戏。你说当官要付出这么高昂的代价，哥们图的是啥？<BR>　　其七、心理的原因。中国封建社会里，一切都可能，一切又都不可能，总之，事物的发展没个谱。这样的环境下，国人当然没有安全感。老百姓没有安全感，皇帝老儿也没有，皇帝老儿手下的官员更没有，不管你有钱没钱，有权无权，大家都没有安全感。很可惜，国人与皇帝都没有足够的理想与清醒，打造一个人人安全的体制与社会氛围，这一点，到刘少奇时代没有做到，到现在的孙志刚时代仍没有做到。难怪贪官们把人生当作了梦靥，并在这梦靥中迅速的走向灭亡。尼采那疯子曾说过这样一句话：人要么永不做梦，要么梦得有趣；要么永不清醒，要么清醒得有趣。中国古代的贪官，做梦都是发财，梦得无趣，但往往梦没做完，小命玩完！是他们不清醒吗？非也，正是由于他们清醒的看到了自己的未来，所以他们才疯狂的贪污，生命不息，贪污不止，很无趣，可是当清官有趣吗？那将是我们下一个课题了。<BR></P></FONT>]]></description>
</item><item>
<title><![CDATA[女性文化--中国传统文化讲义之四]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=torrent&amp;id=6635</link>
<author>torrent</author>
<pubDate>2005/6/18 2:10:08</pubDate>
<description><![CDATA[<A><FONT size=3>　</FONT></A> 
<P><FONT size=3>看了e刀居的&lt;中国传统文化&gt;。非常精彩，但不全，不过瘾。搜来其续</FONT></P>
<P><FONT size=3><A href="http://blogger.org.cn/blog/blog.asp?subjectid=64&amp;name=胡e刀">e刀居相关文章</A></FONT></P>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD vAlign=top height=90>第四讲　　中国女性文化<BR>　　<BR>　　（一）对女人普遍看法不好<BR>　　对女人看法不好，似乎是个世界性的普遍现象。中国的孔家老二在这方面带了一个头，率先表了态：唯女子与小人为难养也,近<BR>　　之不逊,远之则怨。总之，男人自己觉得还挺委屈，对待女人，似乎咋也不是。莎士比亚还算有点绅士风度，说：女人，你的名字叫弱者。莎士比亚可能是同情女人，可是这话总给女人一个心理暗示，让她们错以为，自己天生就是弱者，不太妙。托尔斯泰是个老滑头，说得更幽默一点儿，当然也有点北京式的损味，他说，如果让他发表对女人的真实看法，除非他一只脚已经踏入坟墓，说完后又立即跳进棺材，把盖子盖上。这老家伙，现实生活中是否惧内咱不得而知，但损女人的手腕比较高，有点象国家收容站的同志对待三无或非三无人员，打死你，你表皮则无伤。至于尼采，神经有点问题，对待女人，便有点浑不拎，直通通地说：你去女人哪里吗？别忘了带你的鞭子！分析尼采这老兄话语背后的意思，估计是这么两种：其一，尼采取高高在上之姿态，犹如孔家老二一样，看不起女人；其二，尼采是个小可怜儿，在女人面前，是个容易受伤的男人，就由爱生恨，变成怨男一个了，其心理，跟中国传统女人骂自己的爱人为“冤家”，乡下村妇骂自己老头为“你这个挨千万的”一个意思。其实，学者们说了这么多，都不如咱中国百姓的民间俗语说得妙：女人是猫科动物。猫科动物是什么特性，大家都知道，只有两种发展前途：一种是猫咪，顺从听话，但有爪子，也会抓人！一种是老虎，女老虎，就不是抓人那么简单了，而是直接吃人了。前几年流行的那首歌曲，老和尚和小和尚下山，歌词我忘了，但那也是直接把女人比作老虎的。<BR>　　还有人曾经这样天真的假设过：如果全球的执政者都改为女人的话，那么世界大战可能不会发生。没想到当即有人反对：如果全球的执政者都改作女人的话，那么天天会发生世界大战，地球可能早玩儿完了。如果说对女人看法普遍不好乃是历史与现实生活验证了女人天性多事的话，那么中国哲学的早熟导致我们恰是反着来，事先就知道女人是麻烦，所以，老早就开始压抑女性，把女性的危险与麻烦降至最低！<BR><BR>　　（二）女性的黄金时代<BR>　　<BR>　　历史上女性的黄金时代，大概只能推到母系社会了。之所以说是黄金时代，并不是说女性压迫男性，就象后来的男性压迫女性一样，而是基于男性女性基本平等而言。黑格尔分析男女两性关系体现在三个层次：一是法学领域，即婚姻；二是自然领域，即性；三是美学领域，即情感。那么，如果人之初无所谓婚姻与情感，我们只把焦点定位在自然领域，那么我们会发现，男女关系基本上是平等自由的。《列子.汤问》中说：男女杂游，不聘不媒。《汉书》记载了“桑间濮上”之现象：卫地有桑间濮上之阻，男女亦亟聚会，声色生焉。《汉书》还谈到了燕地民俗：燕地，宾客相过，以妇待宿；嫁取之夕，男女无别，反以为荣。《史记》所记载的现象，更有点类似现代美国一度流行的嬉皮士作风：州闾之会，男女杂坐，行酒稽留，六搏投壶，相引为曹，握手无罚，目眙不禁。前有坠珥，后有遗簪，日暮酒阑，合尊促坐，男女同席，履舄交错，杯盘狼藉，堂上烛灭…罗襦襟解，微闻香泽。当然，《汉书》与《史记》描述这个，大都是基于猎奇或者讥刺之姿态，但是从这些母系社会遗留下来的古风里，我们不难从其侧面发现，那时的男女毕竟是自由平等的。尽管基于人类现有的羞耻心与道德要求，这种自由平等不是多么文明，但是随后发生的文明则是以牺牲女性自由与价值为前提的，所以，我们不得不说，这种文明，让女人付出的代价太大。<BR>　　母权制被推翻了，女性的黄金时代就过去了。为此，恩格斯同情地说：母权制的被推翻，乃是女性的具有世界历史意义的失败。丈夫在家中也掌握了权柄，而妻子则被贬低，变成丈夫淫欲的奴隶，变成生孩子的简单工具了。社会一但变成男人的社会，那么男女关系的三个层次－婚姻，性，情感，便同时成为男人主宰的领地，女人身处其中，其真实身份便沦落为奴隶，工具和乞者了。<BR>　　直到如今，我们读起古籍中的男女自由恋爱场面，还感觉唇词留香。比如《诗经》里的一些句子：有女怀春，吉士诱之。再比如：静女其殊，俟我于城隅。每一个爱情场面，都是优美奔放，健康自然，我猜张谋子拍红高梁的那个“野合”场面，就是跟《诗经》学的，或者说，是莫言跟《诗经》学的，两个人复活古风，但后生小子还以为跟西方学的，有点冤哪。<BR><BR>　　（三）女性角色之定位<BR>　　中国传统文化的一大特性，就是把各种类型的社会文化、社会行为和宇宙秩序牵强附会到一起，宇宙秩序人际化，人际关系宇宙化，谓之天经地义。女性学者谭正壁认为：中国古来一切思想的源泉，完全出在一本《易经》上，关于两性的关系，《易经》是这样说的：乾道成男，坤道成女；辟户谓之乾，阖户谓之坤；乾，健也，坤，顺也；乾，天也，故称呼父，坤，地也，故称呼母。一句话，男女关系天地化，天罩着地，给大地地以阳光和雨露，地当然不能反天了。导致男女关系的主轴便是：男性是施恩者，女性是受恩者。前者是恩人，后者只能报恩不已了。后来社会意识又把这一中心思想扩大化，那么男性女性角色便定位了，大致对应关系如下：<BR>　　男　　　　　　女<BR>　　父　　　　　　母<BR>　　乾　　　　　　坤<BR>　　天　　　　　　地<BR>　　日　　　　　　月<BR>　　阳　　　　　　阴<BR>　　外　　　　　　内<BR>　　动　　　　　　静<BR>　　攻　　　　　　守<BR>　　刚　　　　　　柔<BR>　　强　　　　　　弱<BR>　　<BR>　　在这么一副男女关系对应图中，中国传统女性的标准形象跃然纸上。女性天生就应柔弱，女人的价值就体现在围绕着大太阳和小太阳旋转，女性的社会角色，就是贤妻良母。当然了，如果小女人给人当第三者了，那么她连月亮都不是，只能是星星了，被人总称为小星。<BR>　　学者易中天认为：贤妻良母是对女性的单方面要求，是夫妻间的不平等条约，如果不加分析地一味赞美，无疑是赞美这种不平等关系。周恩来同志1942年在《论贤妻良母与母职》一文中也指出：只要保持这个旧的固定名词，便先陷入男性社会的立场。周恩来同志说得对，但是这里我想指出的是，周与邓的夫妻关系，或者说，邓在家庭里的所作所为，恰是一个标准的贤妻良母，尽管没有人在她身上用这个旧的词语，但是，中国打天下的英雄们，身边何尝不是一个又一个的贤内助呢？中国的女英雄也不少，可是中国的女英雄哪个能升到主席的位子上去？就一个宋国母，好象还是走的丈夫的后门，而且，更多的是一个摆设。至于江青，先不说她人怎么样，单说延安时代，高层男人们开会，合谋不给她一个夫人身份的闹剧，就足以让后人耻笑不已了。一个政府，其元首身边的一个小女人足以对整个国家的正常运作构成威胁，那么我们是应该歧视这个女人，还是应该警惕政府体制之不足？打一个不恰当的比喻，让江青给华盛顿或者给克林顿当生活秘书去，能耐再大，顶多又一版本的莱温斯基的故事，又能怎么着？文革过去后，某些史者还想把国人的思维引导到指责“江妲己”的层面，脸皮真够厚的，我们笑得满地找牙也没人赔我们！<BR>　　社会层面上，男性在成全贤妻良母方面，可谓是推波助澜，功不可没。人前人后，称呼自己的女人为：戝内，内人等。乡间更是叫得绝，直呼女人为：屋里的，床上的，炕上的。<BR>　　这里罗嗦这么多，是想说明，由于给女人定位不正，导致女性在历史与现实中的尴尬处境。标准化吧，是牺牲品；非标准化，又不是好人，咋也不是。比如那顾大嫂，发起怒来，提井栏砸老公的头，打祝家庄，小娘们更是一刀一个人头，咋看咋象个二百五；还有孙二娘，丈夫不敢杀的客人，她敢，伙计扛不动的行货，她上。二百五就二百五吧，可是你看作者如何妖魔化丑化这些女人：前者是胖面腰肥；后者是棒槌般的手脚，辘轴般的腰。虽说是文学形象，但男性作者的笔法实在让人不敢恭维。社会中女性若如此形象，更是永垂史冊了。比如宋代龙丘居士陈慥的婆娘，在苏东坡的戏谑下，是这样一个形象：龙丘居士也可怜，谈空说有夜不眠。忽闻河东狮子吼，拄杖落手心茫然。苏东坡本是戏说龙丘居士之可怜，可是现在人的记忆中，早没有陈老兄的记忆了，只记住一个河东狮吼。<BR>　　所以，我挺同情杨玉环同志，苏妲己同志，褒姒同志，还有那个江青同志。如果长得差点，顶多误一个男人，一不小心，嫁个皇帝，就成千金也不笑的误国妖后了。<BR><BR>　　（四）传统女孩子的素质教育<BR>　　女孩子的地位底，不是出生才开始的待遇，而是自打娘胎里就注定了的。殷商卜辞中即有“贞，有子”“不嘉，有女”的字样，前者的意思是“太好了，是个儿子”，后者的意思是“大事不好，是个女婴！”<BR>　　其次，中国传统社会，男曰儿，女曰婴，我们现在所谓的弃婴，其实其文本初意乃是专指抛弃女孩儿。学者们推论，杀婴弃婴至少在春秋战国时就已出现，韩非子曾提及当时人“产男则相贺，产女则杀之”。如果站这个角度看，我们现在社会的重男轻女（据我所知，局部乡下已经出现男女比例不协调的问题了，希望引起有关方面的重视）似乎不应该是计划生育引起的后果，而只能是中国人的传统意识。当然了，农民没有退休金，老来衣食无保障，以及计划生育等可能加助了这种传统意识的重兴。另外，从字源的角度，我们可以看出，婴字的构成是两贝加一女，一般人认为，两贝是女子珠上的项链串珠，但我觉得，它更可能跟中国女孩子俗称“赔钱货”的说法有某种关联，当然，这需要去考证。不过，这些小玩艺儿不搞也罢。<BR>　　其三，周代，中国就有了所谓的弄璋之喜与弄瓦之喜。《诗经.小雅.斯干》中说：乃生女子，载寝之地，载之衣裼，载弄之瓦；乃生男子，载寝之床，载衣之赏，载弄之璋。其泣喤喤，朱韨（通用字，原字打不出来）斯皇，家室君王。这话翻译过来就甚没意思了。总之，生个女孩，就把你扔地上，随便用一个布片包上，那叫弄瓦之喜；如果生个男孩，那就了不得了，让他穿漂亮的衣服，放到床上，小家伙哭声响亮插云宵，一看就是穿官家礼服的大人才，咋看咋象家里的小皇帝。所以，生男孩，叫弄璋之喜。<BR>　　女孩子一出生，就给你以瓦片的待遇。但既是瓦片，也不能由着你破瓦破摔，你得接受诸多素质教育。这项素质教育简称闺媛礼。<BR>　　闺，意指女子居室的房门。传统文本所谓的闺女，乃是指门里面的女人。这个门，还不是家庭的大门，而是女孩子自己卧室的房门，我把它称作二门。因为俗语里比喻女孩子安静本分，常用语是“大门不出，二门不迈”。所谓的媛，其本义是美女，美好。闺媛二字合于一处，单从文本上就反映了传统女性美的标准。<BR>　　中国的闺媛礼始于周代，主要是对女孩子进行道德教育的素质教材，其目的就是培养女孩子能成为合格的女人。《礼记. 内则》记载了周代的妇德标准，为闺媛礼的发展奠定了基础。到了秦代，女子的贞节问题备受重视，人民领袖秦始皇同志于日理万机中抽出时间，多次刻石提及此事，如在泰山刻石上说：男女礼顺，慎遵职事，昭隔内外，靡不清静。在各界领袖的关心下，到了汉代，闺媛礼终于完善。前汉，后汉，各出一位流传千古的女子教育专家。前汉出个刘向，作《烈女传》；后者班昭，作《女诫》。特别是后者，应该算是中国最早的妇联主席了。汉代之后，对女人的素质教育不断加强，巩固，各种家范家规类的素质教材不断出版，后人整理为《女儿经》《女论语》之类，内容丰富，范围广泛，堪称女式百科全书了，下面分类简介一下。<BR>　　第一， 男女授受不亲的男女有别之礼。<BR>　　<BR>　　男女之别，并不是一出生给你个瓦片与美玉就完事了那么简单，而是在日常生活中，瓦片与美玉必需做到“阶级斗争年年讲，月月讲，日日讲，时时讲，分分讲，秒秒讲”的高度。《礼记.曲礼》中规定如下：男女不杂坐，不同枷，不同巾栉，不亲授，叔嫂不通问，诸母不漱裳。外言不入于梱，内言不出于梱。女子许嫁，缨。非有大故不入其门，姑姊妹女子已嫁而返，兄弟弗与同席而坐，弗与同器而食。翻译过来，大致意思是，男女不能杂坐一处，不共用衣服架子，不共用梳洗用具，不亲手递交东西，小叔子与嫂嫂不能互相问候，不得让庶母给自己洗下衣（中国古代上衣下裳，分得很清的，不象咱们现在，一律衣裳了，上下不分，不成体统的），外面的事不得传入闺女内室，内室的言谈也不要说出去。女子定婚，脖子上要带个此货已定的彩带标志。没有大事，比如地震杀人啦什么的，不要进入女孩子的房门。已出嫁的女子回娘家，不能与兄弟同席坐，同盘子吃饭，火锅更是不能吃了，呵呵。<BR>　　　宋代以后，男女授受不亲规定更严格。《司马氏书仪》规定：凡为宫室，必辨内外，深宫固门，内外不共事。不共浴堂，不共厕，男治外事，内治内事，男子昼无故，不处私室，妇人无故，不窥中门。有故出中门，必拥蔽其面；男子夜行以烛。男仆非有缮修，及有大故，不入中门，入中门，妇人必避之。不可避，亦必以袖遮其面。女仆无故不出中门，有故出中门，亦必拥蔽其面。看看这规定，就明白古代男人之不易了，一门心思要把老虎们关到内笼里去，比动物园的园长还要费心。当然，同学们私下里可能有疑问，这能执行下去吗？单说司马光他家吧，如何不共浴堂不共厕的？我猜他家可能是有男女厕所与男女澡堂的，好歹他是当官的，家当厚实点，可对于老百姓，可能就惨了。我觉得，这么一种高标准，也只是希望罢了，犹如咱们现在的三讲三只表希望官员们都变作青官一样，当真就不好玩了。当然了，司马光可能是以身作贼的，比如他砸缸救小朋友的壮举，我就一直怀疑，为什么他不用手从缸口往上拉，而是费力吧叽的用石头砸呢？怀疑的结果，我猜可能那缸里的小朋友是个女孩子，而司马光本人，可能接受革命教育早了点，有点类似放牛的王二小！这里开个玩笑啊。<BR>　　男女之别，我们的祖先在搞建筑时也充分考虑到了。古代家庭营造房屋时，一般分这内室外室两部分，男子居外，女子居内，男不入，女不出。我觉得，美国人聪明，认为总统是靠不住的，可我们中国人更聪明，认为女人是靠不住的，男女更是不能碰面的，一碰面可能就坏事的，阿Q同志就是这么认定的：呸，凡男人与女人在一起，就一定不会有什么好事。所以，男子盯女人五秒钟就算非礼，而女人，干脆不能看男人。象潘金莲，武二一进门，这厢就高喊叔叔回来了，真是不要脸哪。不过，中国传统社会还有个不成文的规定：长嫂如母（比如包老黑和其嫂嫂）。那潘金莲勾搭武二，更是不成体统了。早先的时候，我老是纳闷：《西厢记》何以在明清被视作黄书？后来一学习这些闺媛礼的素质教材，才明白，那西厢可是黄大了。至于黛玉偷看黄书，堪称早期女革命家了，宝钗偷看黄书却装着没看过，相当于敌后武工队了！<BR>　　第二， 惟务贞洁之贞操礼<BR>　　　贞操，是中国传统社会衡量一个闺中女子品行的最基本也最关键的标准。对少女的贞洁的重视，正如对于集权的重视，也是始于始皇同志的秦帝国。在此之前，男女尚有部分恋爱自由，参看《诗经》。始皇同志关心女人贞洁问题，汉代更是关心，贞节女人，会象现在的劳动模范三八红旗手一样，戴红花，上国家光荣榜，谓之“表贞女”。西汉刘向苦心，编《烈女传》，闺女贞洁遂成当时时代的主旋律。范晔在《后汉书》里首创“烈女传”体例，从此，历朝历代史书都跟着来，这旋律，一下子旋了两千年。　<BR>　　当然，反叛式的白卷英雄也有，但却　犹如孔先生盘子里的茴香豆，多乎哉？不多也。这其中，卓文君同志表现得不错，跟司马相如私奔了，成千古美谈。晋朝的的贾午也不错，把皇帝老儿晋武帝赐给她老爹的香袋送给了自己的相好韩寿，遂成“偷香”之美谈。而且，魏晋时的中国女人，似乎掀起了一场世界上最早的女权运动，魏晋名　士们带头冲击礼教，女人在后头也摇起了小旗，贞洁观受到了冲击，女人在社交方面也很活跃，但是由于只限于贵族女人名士之妻，犹如教材上评价那辛亥革命：脱离人民群众，最后导致失败！<BR>　　魏晋女人的活跃，掩盖不住主旋律之背景音乐－西晋裴頠作《女史箴》，曰：膏不厌鲜，女不厌清，玉不厌洁，兰不厌馨。一句话，女人就是男人桌上的一道小菜，图的就是新鲜和清洁！<BR>　　隋唐时期，皇室宫廷生活奢侈糜烂，宫妓流行。上层社会的风流韵事，犹如毛泽东时代下层百姓的学雷锋做好事，那是层出不穷哪。唐高宗敢娶爹的妃子，　唐玄宗就敢抢儿媳妇。如果说，长孙皇后作《女则》还算以身作则的话，那面首众多的武则天同志发布《内训》号召别人都守节就堪称以身作贼了。唐代最重要的一本关于闺媛礼的著作是宋若华的《女论语》，号召大家能依了其书死学死用，就会成贤妇，独美千古。<BR>　　　宋代，理学家提出“存天理，灭人欲。女子守贞，寡妇守节，严打形势越来越紧张。程颐先吓唬女人：饿死事极小，失节事极大。回头又吓唬男人：若取失节者以配身，是己失节也。这下就坏菜了，面临着男人们集体约好都不娶你的危险，女人们谁敢不老实？不老实也得装老实，如那宝钗似的。<BR>　　第三， 女性之美仪<BR>　　　传统女性之美，可用柔、顺、轻、怯四字概括。王夫人之相中宝钗，估计就是根据这个标准要求的。黛玉除轻字符合标准外，其它三个方面都难以及格。现代的女孩子，见了老鼠就夸张的叫唤，不害怕也要叫唤，假装胆小，实在是心底里想向传统美女的标准靠近，而中国男孩子，平日表现不了自己的威风，一般在老鼠面前是很风光的。有些小家子气的男生，干脆用毛毛虫代替老鼠来唬女孩，侧面却是要证明自己的雄风的。<BR>　　传统中国女人以胆小为美，跟中国第一任妇联主席的班昭倡导有关。她在《女诫》中说：“阴以柔为用，女以弱为美”、“生女如鼠，犹恐如虎”。<BR>　　唐代的《女论语》更是不厌其烦地告诫女孩子：行莫回头，语莫掀唇，坐莫动膝，立莫摇裙，喜莫大笑，怒莫高声。到了宋代，审美情趣更加趋向病态。南唐后主李煜同志给自己的舞女窅娘做莲花座，窅娘同志“以帛缠足”，在莲花座上起舞，“屈上作新月状”，端的漂亮极了。引得女孩子纷纷效仿，到了明代，缠足遂由时尚上升为道德规矩，女子人人缠足，不缠就嫁不出去，当然也有穷家女儿破瓦破摔坚决不缠的，可能是为了干活劳作之方便。至于元璋同志的元配夫人马皇后，更是由于没有缠足而被时人戏称作“马大脚”。大脚就大脚吧，反正人家一不小心嫁给了一位开国皇帝，可无聊之人不甘心，非得讽刺一下这大脚，灯謎上画个马，马上一女人，大脚，怀里抱个西瓜，以影射淮西马氏大脚为乐，元璋同志也不傻，一看就雷霆震怒。文人们敢如此漫画皇后同志，估计不是吃了豹子胆，而是背后那根以德治国的小棍子撑的。<BR>　　有人说，中国与美国的生活目标是一样的，都是为了生活。只不过达到生活的方式不一样。美国为了生活，不断的改造思想，而中国为了思想，却是不断的改造生活。要我说，一句话可概括，人家削履适足，我们是削足适履。缠足即是一例。总之，中国女人除了精神的不幸外，从此有了肉体的痛楚，女人，正犹如她的三寸金莲，都成了男性把玩和欣赏的艺术玩具。当然，缠足不光光是为了女性美，《女儿经》里说：为甚事，缠了足，不因好看如弓曲，恐她轻走出房门，千缠万裹来拘束！明白了吧，还是怕女孩子都学卓文君，见个男人就跟人私奔呢。<BR>　　第四， 无才是德的妇德礼<BR>　　女子无才便是德，是明末后在社会上普遍流行的谚语，它反映了整个社会对妇女道德的期望和要求，是对妇女才华与能力的否定，这句话，可以说是对古代妇德的高度概括。班昭在《女诫》中说：妇德，不必明才绝异也。班圣人这么一倡导，导致女孩子才华被人视作不幸，仅举一例。唐朝女道士李冶五六岁时，作《咏蔷薇》一诗，内有“经时未架却，心绪乱纵横”之句，其父一看，却不象现在的父亲一样，大呼孩子神童，同时牵着孩子上有关部门要求测量智商，以期证明自己一不小心生了个神童，恰恰相反，其父“大恚”，曰：此女狡黠非常，恐为失行妇人。而李冶也没有辜负父亲的期望，长大后成女道士。唐时的女道士，好多都是半文半娼式的，比如众所周知的鱼玄机。<BR>　　女孩子不需要聪明，更不需要才华，笨笨的反而好。聪明至少要装傻，不笨也得装笨，比如花袭人与宝钗。可惜的是，有些女孩子，本来傻得可以，却要装聪明，本来笨得要命，却要装作不笨，比如晴雯与黛玉。如此，她的们命运就很不一样了。<BR>　　女子嫁人之前要守的妇德比较简单。一是孝亲，二是持家。所谓的孝亲，《女论语》交待：女子在堂，敬重爹娘。每每早起，先问安康。寒则烘火，热则扇凉。饥则进食，渴则进汤。所谓的持家，《礼记.内则》教导：女子10岁学纺织，操持家务等。司马光在其《居家杂仪》中把这项工作往前提了一下，要求女子：六岁时习女红之小者，十岁后习女红之大者。所谓的女红，主要指各种家务活，后世主指刺绣等巧线活。我觉得这么伟大的人物，还时不时的操心小女人之女红，同志日理万机，也不容易啊。<BR>　　<BR>　　（五）为人妻之后要守的妇礼<BR>　　第一，三从四德之礼。《礼记》首先确立了妇女“三从”的理论基础：妇人从人者也，幼从父兄，嫁从夫，夫死从子。《孔子家语》交待：女子顺男子之教，而长其礼者也，是故无专制之义而有三从之道。如此，就确立了女人的从属地位。班昭则犹如现在的人民日报特约评论员，对四德作了具体的发挥与解释：其一，妇德－，不需要才能出众，幽娴贞静，守节整齐，行已有耻，动静有法。其二，妇言－不必利言善辩。择词而说，不道恶语，时然后言，不厌于人。其三，妇容－不必颜色美丽，洗净尘秽，服饰鲜洁，沐浴以时，身不垢辱。其四，妇功－不必功巧过人，专心纺织，不好嬉笑，洁齐酒食，而奉宾客。<BR>　　第二，夫死无再嫁之礼。<BR>　　上古时代，礼制即要求女人从一而终，比如《礼记.郊特牲》规定：一与之齐，终身不改，故夫死不嫁。但这只是道德要求，犹如政府号召我们学雷锋，我们要是愣不学，那政府也拿我们没办法。春秋时期，女人改嫁尚是自由的，比如孔子的儿媳妇，伯鱼的妻，也就是子思的娘，不但改嫁，而且走的是涉外婚姻，嫁卫国去了。晋国公子重耳流亡前对其妻说：待我二十五年不来而后嫁。虽然二十五年的等待有点长，但是能如此许诺的，也不愧为伟丈夫了。到了秦朝，改嫁就没有恁自由了，生了儿子的寡妇不得再嫁，《史记. 秦始皇本纪》里云：有子改嫁，倍死不贞。汉代老儒董仲舒《春法决狱》中言：夫死无男有改嫁之道也。老董如果还算有点人味的话，那班昭同志就没了，曰：夫有再娶之义，妇无再嫁之礼。故曰夫者天也，天固不可逃，夫固不可违，行违神祇，天则罚之。礼义有衍，夫则薄之。故事夫如事天。与孝子事父，忠臣事主同也。看看小圣人这话，说得多精彩。女人事夫，犹如忠臣事主。无独有偶，何清涟女士在其文章《中国妇女地位变化的社会环境分析》中提到80年代北大外语系一个女生的豪言壮语：为丈夫补袜子的妻子，她的价值绝对不亚于一个女总统！读到这个细节，我以为班圣人她复活了呢。<BR>　　不过，中国的道德似乎向来只对傻瓜有效，据《中华新报》载，1918年，北京尚有一姓唐的妇人在丈夫死后九十八天内，先后投水、绝食、服毒九次寻死殉夫，功夫不负有心人，最终获得成功。如果说这事儿是爱情闹的，那还会成为千古美谈，问题是，女人把这当作自己的最高道德境界了。另外，我怀疑，道德更多的是上对下扯的幌子，上层的同志们可能根本不当回事儿，比如，汉武帝的祖母嫁过三回，蔡文姬同志也是三回，至于汉代名想陈平，则是自己妻子的第六个男人了。再比如，东汉光武帝的姐姐刚做了寡妇，就看中了朝中大臣宋弘，央求弟弟刘秀给自己拉拉，没想到宋弘象头倔牛，拉不过来，说：贫戝之交不可亡，糟糠之妻不下堂。拒绝了。皇姐带头当第三者，插足别人家庭，百姓要是学会了，那还了得？至于唐宫室，公主改嫁的就不少，太平公主即是一例。南朝宋之山阴公主，更是跟哥哥讨价还价：你女人数千，缘何我只有一个男人？其哥一听，不好意思了，一下子给妹妹批发三十个面首。<BR>　　更没意思的是刘向，其作《列女传》，本意是在劝喻汉成帝及其后宫的淫乱，但是却被政府推行于下。犹如老蒋时代，军匪混战不已，百姓苦不堪言，他老兄却倡导“新生活运动”，说什么饭前便后要洗手，也不想想大家有饭吃没有。更犹如现在，上层官员贪污不止，政府却愣给百姓弄个什么“公民道德建设歌”叫大家齐唱，简直是不要脸到家了，中国传统的道德建设，经常给人一种老妓女给良家女做政治思想工作的嫌疑！<BR>　　不过这工作做得还很有成效，到了宋代，由于程颐，朱熹师徒的不断努力，终于创造了天下奇迹：从朝廷到民间，都将寡妇　再嫁视作奇耻大辱。到了元明两代，政府更是四处造就宣传表扬守节明星，守寡二十年以上的被树为“大牌寡妇”，不但上光荣榜，还给予外资企业待遇－免税，原话叫“旌表门闾，免除本家差役”。到了清代，政府对寡妇守节的表扬再创高峰。象祥林嫂那样，不愿改嫁贺老六，成亲当天碰头求死没有成功只磕了一点皮的，就不值得表扬一回了。象元代冯姓寡妇，乳房长疮，坚决不给医生看，最终病死之类的，才够格称作女英雄。总之，宋元明清时代，天下形势，不是小好，而是大好，贞女烈妇，犹如雨后春笋，层出不穷，数不胜数。《明史》中留名的，万人之多，明星有三百人。《古今图书集成》中收录的明代烈女节妇有三万六千多人。前仆后继跟党走，死得其所，死得光荣！<BR>　　第三，七出三不出之礼。<BR>　　七出三不出之礼，是有关古代中国女人被休之问题的。主动权完全在男家手里。<BR>　　《礼记.大戴礼》曰：妇有七去。不顺父母，去；无子，去；淫，去；妒，去；有恶疾，去；多言，去；盗窃，去。<BR>　　其一，所谓的不顺父母，字面上看，是不顺从父母，但是我们也可以理解为父母看不顺眼。如焦母之对刘兰芝：此妇无礼节，举动自专由，吾已久怀忿，汝岂得自由！最终结果，焦仲卿扭不过老娘的。因为《礼记》里有规定：子甚宜其妻，父母不悦，出；子不宜其妻，父母曰是善事我，子行夫妇之礼焉，没身不衰。这话翻译过来，很简单：男人喜欢妻，但是老娘不喜欢，休掉；男人不喜欢妻，但是老娘喜欢，男人就跑不掉，得终身行夫妇之伦。这例子就太多了。《后汉书》载：东汉时，姜诗的母亲喜饮江水，姜诗妻需到江边打水，来回十来里的路，有一回遭遇大风，误了姜母喝水，姜母告诉儿子，姜诗大怒，休妻。鲍永妻着急，在婆婆面前骂一条狗，鲍永觉得妻不象话，休妻。我怀疑鲍永妻同着婆婆的面，骂老狗之类的，被人听来，有影射之嫌，也就是说，国家搞文字狱，那家里也没闲着，跟着搞呢。至于近代，也有不少名人可作例子。比如老蒋不喜欢毛福梅，但老娘喜欢，所以美龄同志第五者插足，也只能插走第三者姚怡诚，第四者陈洁茹，福美同志作为第二者，那是谅谁也插不走的。同样的例子还有鲁迅同志之妻，朱安女士。总之，古代社会，聪明的媳妇首先跟婆婆搞好关系，才能风雨不动安如山，唐婉没做到，珍妃也没做到。<BR>　　其二，无子，去。孟子云：不孝有三，无后为大。对于中国传统女人，生子多，那是劳动模范，开国元勋，生子少，那是事业不景气。尽生女孩那样的赔钱货，更是相当于企业连年亏损的厂长，由婆婆与丈夫组成的董事会当然要撤你的职。当然，也有补救的办法：借贷丈夫。具体说来，就是主动给丈夫纳妾。<BR>　　其三，淫，去。原先我以为，所谓的淫，就是指潘金莲那样勾搭外人的妇人，当然合应上道德法庭。现在才知道，所谓的淫，不但指对外，而且也指对内。也就是说，妻子不能对丈夫有过多的房事要求，或者说，妻子在丈夫面前，也得做出圣女的样子。比如孟子就曾因为妻子在卧室内裸体走动而意欲休她，最后在老娘的教导下才罢休。这就导致传统中国女人不知道如何做女人才好，正经，还是不正经？真正经，还是假正经？不正经，还是假不正经？总之，挺有意思的，这里我想用班家两位圣女作例子。第一个叫班婕妤，第二个，就是班昭。前者是后者的姑奶奶。先说前者，成帝特别喜欢她，游于后宫，欲与她同辇，没想到小女人一本正经，辞曰：观古代图画，圣贤的皇帝，都有名臣在旁，只有三代的末主，才亲近女嬖。现在要妾同车，岂不和他们一样吗？史料中没有说成帝什么反应，只一句“成帝止”，但我想，丫头这么理正辞严，成帝可能很扫兴的。后来，成帝迷上了赵飞燕姐妹，也就把她给忘脚后跟了。班姑娘最后卷入许皇后与赵飞燕争宠的漩涡中，差点没了小命。思及飞燕声势威赫，便退而自保，自请供养皇太后于长信宫。作诗自赋，内有“神眇眇兮密靓处，君不御兮谁为荣。俯视兮丹墀，思君兮履綦；仰视兮云屋，双涕兮横流。”相传班婕妤还作过一首《怨诗》：新裂齐纨素，蛟洁如霜雪，裁成合欢扇，团团似明月，出入君怀袖，动摇微风发。常恐秋节至，凉飙夺炎热，弃捐箧笥中，恩情中道绝！没了皇帝的宠爱，丫头也挺痛心的，只是早知今日，何必当初？后宫老虎数千，自己又想扮演一个不吃腥的老虎，容易吗？不过，落个圣人名号，也算值得。至于班家第二位圣人班昭，却完全是因了著有《女诫》一书，这丫头比她的姑奶奶还要绝，认为丈夫对于妻子，是恩人的关系。妻子不能跟丈夫玩笑，免得容易引起侮夫之心。我不知道她丈夫曹世叔如何的守着一位不跟丈夫开玩笑的女人过日子，我只知道，她小姑子曹丰生曾坚决反对她的观点，可惜文已不传。可见，历史就是统治者及其帮凶阉割思想的过程。<BR>　　其四，妒，去。也就是说，女人不能吃醋，而反对丈夫纳妾就是吃醋。据说，吃醋的典故来自于唐管国公任瓌。太宗以功赐二侍子，任拜谢，不敢归。太宗召其妻，赐酒，谓之曰：妇人妒忌，合当七出。若能改行无妒，则毋饮其酒，不尔，可饮之。没想到任夫人对曰：妾不能改妒，请饮其酒，遂饮之。比醉归，与其家共死诀，其实非鸩也，乃是醋。从此，妒妇与醋妇成为同义词。晋，谢太傅安，妻颇妒，欲置姬妾而不敢，兄子辈微达其意，因方便，称《关睢》《螽斯》有不忌之德。夫人知以讽己，乃顾问云：此诗是谁所撰？答曰：周公。夫人答曰：周公是男子，想为之耳，若使周姥撰诗，当无是言。壮哉，谢安妻。真是不愧为宰相夫人，反驳得精彩极了。而谢安最终也没得讨上妾，当然，嫖妓还是可以的。<BR>　　汉魏六朝，妒妇们妒性强烈，夫们夫可奈何。刘宋时，明帝的尚书右丞相荣彦远，被醋妻打得脸上都带伤了，明帝可怜自己的臣下，问：我为治之，如何？荣：听圣旨。结果，明帝赐药杀之。大臣刘休的妻也妒，明帝亲自赐妾给刘休，并打刘休妻二十大板。问题是，皇帝不能天天管臣下的家务事，精力有限，也管不过来，只好叫虞通之写个党的基础知识读本，名曰《妒妇记》，以期给妇人们做好政治思想工作。<BR>　　当然，女人吃醋吃成功的也不少。除了谢安妻以外，卓文君同志，管道昇同志，都成功了。　文君年老时，相如动了纳妾之念，文君一听，气坏了，作《白头吟》，赌气说“闻君有两意，故来相决绝”，相如吓得不敢再纳妾。而管道昇，乃是大书法家赵孟 的夫人。赵书法家有了纳妾之念，就作词给夫人：我为学士，你做夫人。岂不闻王学士有桃叶、桃根，苏学士有朝云暮云？我便多娶几个吴姬越女无过分，你年纪已过四旬，只管占住玉堂春！<BR>　　管道昇一看，作词回：你侬我侬，忒煞情多。情多处热如火。把一块泥，捻一个你，塑一个我，将咱两个，一齐打破，用水调和，再捻一个你，再塑一个我。我泥中有你，你泥中有我，与你生同一个衾，死同一个椁。管道昇不愧是大政治家管仲的遗族后代，就这么三下两下的捏了几个小泥人儿，就把丈夫纳妾的念头给捏没了，功夫自是了得。只可惜，会这么捏泥人的中国女人并不多，所以，女人们只好把醋意深深的埋心底。比如风情万种的王熙凤同志，因贾琏在外头胡混，吃了那么一回醋，就受到了上级领导贾母同志的强烈批评：什么要紧的事儿，小孩子们年轻，馋嘴猫儿似的，哪里保得住呢？这都是我的不是，叫你多喝了几杯酒，又吃起醋来了。总之，醋是不能随便吃的。轻者挨批评，重者休家去。<BR>　　其五，多言，去。女人切忌多嘴。《女论语》交待：是非休习，长短休争，从来家丑，不出外传，莫学愚妇，不问根源，秽言污语，触突尊贤。司马光更是吓唬大家：长舌厉阶，画地成狱；妒悍相残，身攒百镞。<BR>　　其六，有恶疾，去。到底什么是恶疾，现在也没有个说法。我估计可能是麻风病或者羊羔疯之类的病吧。<BR>　　其七，盗窃，去。女人被训得天性胆小，又是小脚，又是不出门的，这盗窃功夫，估计也没几个人会，也找不出例子来，大家知道就行了。<BR>　　至于三不去，也就是女人在三种情况下不得被休，算是对女人的一种额外保护吧，具体如下。《大戴礼》曰：妇有三不去，有所娶无所归，不去；与更三年丧，不去；前贫后富，不去。<BR>　　这就是所谓的七出三不出，作为一种道德礼教，它形成于汉代，唐代时，变作了法律。《唐律疏义》《元典章》《清律》都把它纳入了法律条款中。<BR>　　第五， 婆媳之礼。<BR>　　在中国的传统家庭中，婆媳关系大概是最难处的一种关系。俗语说：丑媳妇最怕见公婆。说得也是。按我的评价，感觉新媳妇一过门，公婆就先给她一个下马威的。《仪礼.士昏礼》载：婚礼第二天早上，拜见公婆，媳妇要给公公婆婆端饭，公公婆婆象征性的吃一下，媳妇儿要端过来他们的剩饭，也象征性的吃一下，这一象征不要紧，象征着媳妇儿一进门就是个吃剩饭的地位和待遇。至于其它礼节，更是详之又详：公婆走动，要跟着，公婆洗脸，要端水，公婆吃饭，要奉坐席，问清公公婆婆脚往哪个方向伸。公婆叫，则轻声嗳。公婆面前行走，要庄重，俯身拱首而行，不打吠嗝，不打喷嚏，不哈欠，不伸懒腰。站时不得偏倾一足，身体斜靠，不能流口水，不能淌鼻涕，公婆不让回自己的房间，不得私自回，有事，请示公婆……<BR>　　 《女诫》更是规定：姑云不尔而是，固宜从令，姑云尔而非，犹宜顺命，勿得违戾是非，争分曲直。一句话，婆婆就是核心，婆婆不是也是，是更是是，不得与婆婆辩论，要二话不说地旋转在以婆婆为核心，以丈夫为半径的圈圈之内。<BR>　　（六）最后的综述<BR>　　如果说中国男性遭受忠孝义三根锁琏的话，那中国传统女性还要多遭受一重，那就是来自夫权的压迫。也许是大家急于解放自己了，所以，我们现在看到的现象并不容乐观。<BR>　　第一：解放后女性解放之变种。典型的代表就是文化大革命中，不爱红装爱武装的女红卫兵，形象实在是不雅。如果说女红卫兵是政治变形的产物，那么二十世纪八十年代流行的假小子则同样让人感叹。美籍作家赵浩生曾在《中国青年报》上哀叹：中国最大的悲哀就是没有女人了！女性解放，不是从一个极端走向另一个极端，更不是马列式的革命斗争，怕就怕，中国传统女性美的精华没有继承，西方现代女性的糟粕却学来了。中国前一阵子流行宝贝，上海宝贝带个头，北京宝贝，成都宝贝蜂拥而上，特别是北京宝贝，分明还是个孩子，却…这事儿不说也罢。<BR>　　第二，传统的回归。与假小子横行的现象相反的是，某些方面也出现了对于传统女性的呼唤，以及局部的回归。影视与政府主流舆论掀起了一股一股的军嫂热，凯丽扮演的刘慧芳之形象传入千家万户。何清涟的文章更是举例说明88级北大历史系的一些女生一进校门，就开始考虑把自己培养成家庭主妇。北大的女生部部长干脆宣布：女生部的宗旨就是要把北大的女生培养成未来的贤妻良母。也就是这么一种情况下，北大外语系的那位女生才说出了“给自己丈夫补袜子的妻子，其价值绝对不亚于一个女总统！”的豪言壮语。我不知道现在这位女生是不是正在给自己的丈夫袜子，但是我认为，女总统也可以给自己的丈夫补袜子啊，新西兰的女总统可以这样表白：给自己丈夫补袜子的女总统，其价值绝对不亚于一个妻子！我不知道，为什么国人总易走极端？宝贝不好，那刘慧芳也好不到哪里去啊！<BR>　　第三．当代中国女性之地位<BR>　　据研究者发现，当代中国女性之地位，并没有随着经济改革而上升，相反，在激烈的市场竞争中，出现了劣化趋势。根据七项指标测量，在世界160个国家中，我国妇女地位排名第132位。这七项指标是：<BR>　　1、 妇女就业率<BR>　　2、 对待男婴女婴的态度<BR>　　3、 男女青少年入学比例<BR>　　4、 男女青年就业比例<BR>　　5、 妇女在国家机构重要领导岗位上的职务比例<BR>　　6、 妇女在家庭中的地位<BR>　　7、 妇女个人财产在社会财富中的比例<BR>　　<BR>　　七项指标，只有第一项领先，占世界第一，其它六项均不理想。依我看，第二条第五条可能最差，以后依然如此。<BR>　　如此环境中，中国女性怎么办？也许可以套用那句老话：娜拉出走后怎么办？<BR>　　最后给大家出一个作业题：为什么反人性的东西，比如缠足，比如一夫多妻，能够在中国这样一个所谓的文明古国里长久通行？题目自定，字数不限。</TD></TR></TBODY></TABLE>]]></description>
</item><item>
<title><![CDATA[设计模式（四人帮版）翻译（3）]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=torrent&amp;id=6626</link>
<author>torrent</author>
<pubDate>2005/6/17 15:21:47</pubDate>
<description><![CDATA[<A><FONT size=2>　</FONT></A><FONT size=2> </FONT>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center" align=center><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>设计模式描述</FONT></SPAN></B></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center" align=center><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="FONT-SIZE: 14pt"><?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><o:p></o:p></SPAN></B><FONT size=2>&nbsp;</FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>我们怎样来描述设计模式呢？采用图形概念？图形概念虽然很重要并且很有用，但并不够。它们仅仅简单的表达了类和对象的关系，这是设计过程的最终产品。为了设计重用，我们还必须记录决策过程、替代方案、及实现费用等。另外，具体的实例也很有用，这对设计活动的理解很重要。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>我们用统一的格式来描述设计模式，每一模式都按以下的模版分成多个部分。每部分的模版使用统一的信息结构，便于设计模式的学习、比较和使用。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt; mso-char-indent-count: 1.71"><FONT size=2><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">模式名和分类（</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Pattern Name and Classification</FONT></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></B></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><FONT size=2><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">模式名简洁的表达模式的本质。好的命名非常重要，因为它将成为你的部分设计术语（词汇）。模式的分类反映了我们在</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Section1.5</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中介绍的想法。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt; mso-char-indent-count: 1.71"><FONT size=2><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">意图（</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Intent</FONT></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></B></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>对如下问题的简短回答：这个设计模式能做什么？其基本原理和意图是什么？它针对哪类特殊的设计问题？</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt; mso-char-indent-count: 1.71"><FONT size=2><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">另称为（</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Also Known As</FONT></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></B></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>这个模式的其它名称（如果有的话）</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt; mso-char-indent-count: 1.71"><FONT size=2><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">动机（</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Motivation</FONT></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></B></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>设计问题以及类和对象在这个模式中怎么解决这个问题的情景演示。这个情景能帮助你理解对该模式的更高的抽象描述。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt; mso-char-indent-count: 1.71"><FONT size=2><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">适用性（</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Applicability</FONT></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></B></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>该模式可应用于那种情况？该模式可能遭遇的糟糕设计及你怎么才能识别这种情形？</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt; mso-char-indent-count: 1.71"><FONT size=2><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">结构（</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Structure</FONT></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></B></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><FONT size=2><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">基于对象模型技术（</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">OMT</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）的对该模式的图形表示，也使用交互图来表示对象的请求顺序和协作。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt; mso-char-indent-count: 1.71"><FONT size=2><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">参与者（</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Participants</FONT></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></B></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>参与该模式的类和对象以及其职责。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt; mso-char-indent-count: 1.71"><FONT size=2><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">协作（</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Collaboration</FONT></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></B></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>参与者为了完成各自的职责该如何协作。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt; mso-char-indent-count: 1.71"><FONT size=2><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">后果（</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Consequences</FONT></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></B></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>模式达成目标的程度、应用该模式的结果和费用、系统结构允许你改变其中的一个方面吗，是哪方面？</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt; mso-char-indent-count: 1.71"><FONT size=2><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">实现（</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Implementation</FONT></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></B></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>实现该模式时要注意的前提和技术，有什么缺陷？是否有与语言相关的特性？</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt; mso-char-indent-count: 1.71"><FONT size=2><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">例程（</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Sample Code</FONT></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></B></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><FONT size=2><SPAN lang=EN-US><FONT face="Times New Roman">C++</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">和</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Smalltalk</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的例程演示如何实现该模式</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt; mso-char-indent-count: 1.71"><FONT size=2><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">已知应用（</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Known Uses</FONT></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></B></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>已发现的实际系统中的该模式的例子。至少包括两个不同领域的例子。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt; mso-char-indent-count: 1.71"><FONT size=2><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">相关模式（</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Related Patterns</FONT></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></B></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>哪些设计模式与此模式紧密相关、有什么重要的不同？该模式应当与哪个模式一起应用。</FONT></SPAN></P>]]></description>
</item><item>
<title><![CDATA[访问"乱闪blog"中的问题]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=torrent&amp;id=6613</link>
<author>torrent</author>
<pubDate>2005/6/16 23:42:59</pubDate>
<description><![CDATA[访问热门blog首位--乱闪blog时，点击上方的“隐藏左栏”等选项，会自动跳转到我自己的管理界面，不知是否添加了代码，没仔细看]]></description>
</item><item>
<title><![CDATA[设计模式（四人帮版）翻译（2）]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=torrent&amp;id=6601</link>
<author>torrent</author>
<pubDate>2005/6/16 21:55:22</pubDate>
<description><![CDATA[<A><FONT size=2>　</FONT></A><A><FONT size=2>　</FONT></A><FONT size=2> </FONT>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center" align=center><FONT size=2><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="FONT-SIZE: 14pt"><FONT face="Times New Roman">Smalltalk</FONT></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的</SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="FONT-SIZE: 14pt"><FONT face="Times New Roman">MVC</FONT></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">设计模式</SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="FONT-SIZE: 14pt"><?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><o:p></o:p></SPAN></B></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><FONT size=2><SPAN lang=EN-US><FONT face="Times New Roman">MVC</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">方式通常在</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Smalltalk</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中用于建立用户接口。通过对</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">MVC</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中蕴藏的设计模式可以帮你理解我们所说的“模式”的含义。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><FONT size=2><SPAN lang=EN-US><FONT face="Times New Roman">MVC</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">包括三类对象，</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Model</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">是应用对象、</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">View</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">为其屏幕表示、</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Controller</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">定义了对用户输入的处理（反应）方式。在应用</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">MVC</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">方式以前，通常将这三个对象的功能合到了一起，应用</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">MVC</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">分离了它们，为设计提供了灵活性和可重用性。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><FONT size=2><SPAN lang=EN-US><FONT face="Times New Roman">MVC</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">通过在</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">view</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">和</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">model</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">之间建立</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Subscribe/Notify</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">协议，分离了</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">view</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">和</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">model</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">对象。</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">View</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">对象必须保证它的表示反应了</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">model</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">对象的状态，当</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">model</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">对象的数据改变时，</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">model</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">对象通知（</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Notify</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">view</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">对象，作为对这一行为的反应，每个</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">view</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">对象得到了一个做出更新的机会。这种方式使得可以将多个</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">view</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">对象为一个</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">model</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">对象提供不同的表示。你也可以为</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">model</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">对象建立新的</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">view</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">对象，而不用重新编写</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">model</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。下图演示了一个</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">model</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">和三个</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">view</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">：</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN lang=EN-US><?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" /><v:shapetype id=_x0000_t75 coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f"><v:stroke joinstyle="miter"></v:stroke><v:formulas><v:f eqn="if lineDrawn pixelLineWidth 0"></v:f><v:f eqn="sum @0 1 0"></v:f><v:f eqn="sum 0 0 @1"></v:f><v:f eqn="prod @2 1 2"></v:f><v:f eqn="prod @3 21600 pixelWidth"></v:f><v:f eqn="prod @3 21600 pixelHeight"></v:f><v:f eqn="sum @0 0 1"></v:f><v:f eqn="prod @6 1 2"></v:f><v:f eqn="prod @7 21600 pixelWidth"></v:f><v:f eqn="sum @8 21600 0"></v:f><v:f eqn="prod @7 21600 pixelHeight"></v:f><v:f eqn="sum @10 21600 0"></v:f></v:formulas><v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"></v:path><o:lock v:ext="edit" aspectratio="t"></o:lock></v:shapetype><v:shape id=_x0000_i1025 style="WIDTH: 396pt; HEIGHT: 222.75pt" type="#_x0000_t75" alt=""><v:imagedata src="file:///C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\msohtml1\01\clip_image001.png" o:href="../My%20Documents/Design%20Patterns%20CD/Design%20Patterns%20CD/hires/Pictures/mvc.gif"><FONT size=2></FONT></v:imagedata></v:shape></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><FONT size=2><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">从表面看，这一例子反应了一个将</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">view</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">和</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">model</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">分离的设计。然而，这种设计适合一类更通用的问题：减少对象之间的藕和性，这样，当一个对象改变时，将不会影响到另外的对象，甚至不需要知道另外的对象的实现细节。这种更通用的模式将在</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Observer</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">模式中来描述。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><FONT size=2><SPAN lang=EN-US><FONT face="Times New Roman">MVC</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">方式的另一个特点是，</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">view</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">对象是可嵌套定义的。例如，</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">button</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的控制板可由一个包含嵌套</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">button view</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">对象的复杂</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">view</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">对象来实现；对象观察器的用户接口可由能重用于调试器的嵌套</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">view</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">对象组成。</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">MVC</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">方式采用</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">CompositeView</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">类（</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">View</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的子类）来支持嵌套</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">view</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，其行为与</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">view</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">对象的行为一致，可用于</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">view</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">对象能使用的任何场合。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><FONT size=2><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">于是，我们又可以把这种对待</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">composite view</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">就像处理其一个组件的方式看成一种设计（方式）。同样的，这种设计可抽象出另一类更通用的问题（的解决方式）：我们在某种情形下将对象分成组，并且处理一个组就像对待对象个体。这种方式我们用</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Composite</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">设计模式来描述。它允许你建立类的层次，在这一层次下，有些子类定义原始对象（如</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Button</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">），而其它的类可以定义合成对象（</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">CompositeView</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">），合成对象可将原始对象装配成更复杂的对象。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><FONT size=2><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">同样，</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">MVC</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">也可改变视图类（</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">view</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）对用户反应的方式，而不用改变其可视化表示。你可能想改变其对键盘响应的方式，如，使用弹出菜单代替命令键。</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">MVC</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">将这种反应机制封装为控制对象（</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Controller</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）。控制器有一个类层次，易于实现从一个已存在的控制器建立出一个变种</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">—</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">一种新的控制器。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><FONT size=2><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">视图（</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">view</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）对象通过某一控制器对象的实例（</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">instance</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）来实现特定的响应策略。为了实现不同的策略，可以简单的使用不同的控制器实例来替换当前的实例。甚至可以在运行时来改变视图的控制器，以改变视图对象对用户输入的响应（策略）。例如，一个</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">view</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">对象可置为</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">disabled</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，即对用户的输入不做任何响应。要达到这一目的，仅仅只需让控制器忽略所有</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">input</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">事件。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><FONT size=2><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">这种视图</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">—</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">控制器关系即是</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Strategy</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">设计模式的一个典型例子。所谓</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Strategy</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">即这样一个对象，它表示了一种算法。这在你想要替换算法（无论是静态替换还是动态替换）时特别有用，而这样的算法可能有许多的变量、或者拥有复杂的数据结构。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><FONT size=2><SPAN lang=EN-US><FONT face="Times New Roman">MVC</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中也使用了别的设计模式，例如，使用</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Factory Method</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">模式来描述视图的默认控制器类；采用</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Decorator</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">模式来为视图增加滚动条等。但在</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">MVC</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中的主要模式是前述的</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Observer</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">、</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Composite</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">、和</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Strategy</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">设计模式。</SPAN></FONT></P>]]></description>
</item><item>
<title><![CDATA[设计模式（四人帮版）翻译（1）]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=torrent&amp;id=6597</link>
<author>torrent</author>
<pubDate>2005/6/16 18:00:15</pubDate>
<description><![CDATA[<A><FONT size=2>　</FONT></A><A><FONT size=2>　</FONT></A><FONT size=2> </FONT>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center" align=center><FONT size=2><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">介绍</SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="FONT-SIZE: 14pt"><?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><o:p></o:p></SPAN></B></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>面向对象软件的设计是困难的，而可重用的面向对象软件的设计则更难。首先必须找出目标对象，按照合适的粒度规入类，并为类定义接口和层次，及在类之间建立合适的关系。设计必须能解决当前的问题，而且要有一定的通用性以满足未来的需求，尽量的避免重新设计。有经验的设计人员将告诉你，在最先的设计中没有良好定义的情况下，要得到一个可重用的灵活的设计是多么的困难。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>富有经验的设计人员能做出好的设计，然而新手在可能的选择中犹豫不决，并常常导致采用他们以前用过的非对象技术。新手们要花很长的时间才能学会好的对象程序设计。显然，有经验的设计人员拥有新手们所不拥有的东西，是什么呢？？</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><FONT size=2><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">专业设计人员所拥有的第一个优势是，不（必）用</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">first</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">原则来解决每一个问题，他们可以采用以前用过的解决方案。当发现一个好的解决方案时，他们一次又一次的使用它。这种经验也是使他们成为专家的原因之一。其结果是，你能够在很多面向对象系统中发现重复出现的类模式和通信对象，这些模式解决了某类特定的设计问题，并使得面向对象的设计变得更加灵活、优雅、最终可重用。熟悉这些模式的设计者可以立即将其应用到设计中而不需要重新发现它们。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>象小说家和剧作家就常常任用老的模式如悲剧英雄、浪漫小说等等。同样的，设计者们也经常采用一定的模式如用对象表示状态、装饰对象以添加特征等等。一旦你掌握了设计模式，就能够自动的运用许多设计决策。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>我们都知道设计经验的重要性。你是否有过这样的经历，在你设计的过程中碰到了一个似曾相识的问题，如是你搅尽脑汁去回忆是在什么情况下、在什么地方、用什么方法解决的。如果你能回忆起其细节，你就能够重用过去的经验来解决它。然而，我们对这种过去软件设计的经验并没有作出良好的记录以利其他人也能够重用它。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>本书的目的就是记录在面向对象软件过程当中的经验，我们称之为设计模式。对每一种设计模式系统的命名、解释和评估，目标是来捕获人们能够有效应用的设计经验的具体形式。为了达到此目的，我们文档化了一些最重要的设计模式。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><FONT size=2><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">设计模式使得重用成功的设计和架构更为容易。其</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Expression Proven</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">方法使得其在新系统中的应用更为容易。设计模式能够帮助你选择那些可重用的设计。通过对类、对象交互及其深层次意图的详细说明，设计模式甚至能提高现有系统的可维护性和文档质量。简言之，设计模式能帮助更快的作出正确的设计。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>本书中并未给出新的或未证明的设计模式，这里的设计模式都是那些在不同的系统中多次应用的设计，而大多数这样的设计以前都没有文档化过。它们以前仅在面向对象研究团体中流传，或是成功的面向对象系统中的一些元素，这对于新手来说，每一种方式都不不易学习到。虽然这些设计方法都不是新的，我们以一种新的和可学习的方式来得到它们：作为具有一致格式的一类设计模式。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>限于篇幅，本文仅给出专家所知的部分设计模式，不包括那些处理同步、分布式系统和实时系统中的设计模式，也不包括那些针对特定应用领域的设计模式；这里也并不会教你如何建立用户接口、如何写设备驱动、如何处理面向对象数据库。以上所说的领域具有自己独特的模式，值得将来有人为之分类编写。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p><FONT face="Times New Roman" size=2>&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center" align=center><FONT size=2><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">什么是设计模式？？</SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="FONT-SIZE: 14pt"><o:p></o:p></SPAN></B></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><FONT size=2><SPAN lang=EN-US><FONT face="Times New Roman">Christopher Alexander</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">说过，每一种设计模式都是在讨论一类一次一次重复发生的问题，而规定对这类问题的解决方案的核心部分，。。。。。</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Alexander</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">所说的模式是在建筑领域，但其对于面向对象设计模式同样适用。在我们的讨论环境中，不过是用对象和接口代替了墙和门窗，但两类设计模式的核心都是针对各自领域中的某类问题的解决方案。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>通常，一个模式具有四个关键要素：</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt; mso-char-indent-count: 1.71"><FONT size=2><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">模式名（</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">pattern name</FONT></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）</SPAN></B><FONT face="Times New Roman"> </FONT><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">我们用其来规定一类设计问题、对该类问题的解决方案和结果。通过对模式命名扩大了设计词汇，容许我们在设计时采用更高一层的抽象，使得对设计的考虑和交流更为容易。对模式的好的命名是我们工作的难点之一。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt; mso-char-indent-count: 1.71"><FONT size=2><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">问题（</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">problem</FONT></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）</SPAN></B><FONT face="Times New Roman"> </FONT><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">描述了何时使用模式。它解释了问题及其应用环境，可能是对特定设计问题的描述如如何用对象来表示算法，亦可能是对类和对象结构的描述如某种固定的设计中出现的类和对象的结构。有时，问题（）也可以包括条件列表，。。。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt; mso-char-indent-count: 1.71"><FONT size=2><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">解决方案（</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">solution</FONT></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）</SPAN></B><FONT face="Times New Roman"> </FONT><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">解决方案描述了很多基本元素，包括组成设计的元素、以及它们之间的关系、职责和协作。解决方案中不包括具体的设计和实现，因为模式必须应用于不同的环境。取而代之的是，模式提供对某类设计问题和怎样布置这些元素的抽象描述。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt; mso-char-indent-count: 1.71"><FONT size=2><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">后果（</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">consequences</FONT></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）</SPAN></B><FONT face="Times New Roman"> </FONT><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">应用模式的结果和费用的评估。实际上，它是对模式的评估，软件的设计通常关心时间和空间的耗费，后果（）也是选择语言和具体实现的依据之一。由于重用是面向对象的目的之一，模式的后果（）也包括任用该模式在灵活性、可扩展性和轻便性方面的影响。列出后果（）可帮助你更好的理解和评估一个模式。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=2>个人观点影响着对某个设计是不是模式的判断，某人的模式可能只是另一个人的元构建块。本书中我们将模式浓缩为某一级别的抽象，本书的设计模式不包括诸如链表、哈希表一类的可在类中实现和编码的设计，也不包括那些复杂的、针对整个应用或子系统的设计。本书所说的模式是在某一环境中用来解决一种通用设计问题的，类和对象之间通信的描述。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><FONT size=2><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">设计模式的命名、抽象描述、以及其设计结构的核心因素的识别，都有助于可重用的面向对象设计。设计模式致力于识别参与的类和实例、它们的角色和协作关系、以及各自的职责。每一个设计模式关注着特定的面向对象设计问题。设计模式描述了何时应用、再有设计约束时能否应用、以及其应用的后果和费用的评估。由于我们必须最后实现设计，设计模式可以用</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">C++</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Smalltalk</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">代码来演示。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 17.95pt; mso-char-indent-count: 1.71"><FONT size=2><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">编程语言的选择非常重要，因为它影响着我们的观点。我们的模式基于</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">C++/Smalltalk</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">语言，这种选择决定了某模式实现的难易。例如，如果我们选择过程语言，我们的设计模式中可能包括类似“继承”、“封装”、“多态”等模式。类似的，我们讨论的有些模式可能为某种语言所直接支持，例如，</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">CLOS</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中有很多方法就实现了我们所讨论的</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Visitor</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">模式。实际上，</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">C++</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">和</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Smalltalk</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">也有很多不同之处，这意味着某个模式可能用某种语言实现起来比另外一种要容易。（例如</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Iterator</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">模式）</SPAN></FONT></P>]]></description>
</item>
</channel>
</rss>