﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-AntSoul-随笔分类-CoreJava</title><link>http://www.blogjava.net/antsoul/category/20417.html</link><description>它总是在行走，行走，永远的行走……


行走是它生存的恒久姿态和最佳造型。


它似乎有一双不知疲倦的脚。


———我说的是蚂蚁。
</description><language>zh-cn</language><lastBuildDate>Wed, 04 Apr 2007 16:15:16 GMT</lastBuildDate><pubDate>Wed, 04 Apr 2007 16:15:16 GMT</pubDate><ttl>60</ttl><item><title>Creational Pattern学习之Simple Factory</title><link>http://www.blogjava.net/antsoul/archive/2007/03/31/107608.html</link><dc:creator>antsoul</dc:creator><author>antsoul</author><pubDate>Sat, 31 Mar 2007 02:53:00 GMT</pubDate><guid>http://www.blogjava.net/antsoul/archive/2007/03/31/107608.html</guid><wfw:comment>http://www.blogjava.net/antsoul/comments/107608.html</wfw:comment><comments>http://www.blogjava.net/antsoul/archive/2007/03/31/107608.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/antsoul/comments/commentRss/107608.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/antsoul/services/trackbacks/107608.html</trackback:ping><description><![CDATA[   <font size="2">Creational Pattern是对类的实例化过程的抽象化。一些系统在创建对象时，需要动态的决定怎么样创建对象，创建那些对象，以及如何组合和表示这些对象。Creational Pattern描述了怎么样构造和封装这些动态的决定。<br />    Creational Pattern分为类的创建模式和对象的创建模式两种。<br />    类的创建模式：     类的创建模式使用继承关系，把类的创建延迟到子类，从而封装了客户端将得到的哪些具体类的信息，并且隐 藏了这 类的实例是如何被创建和放到一起的。<br />    对象的创建模式： 对象的创建模式是把对象的创建过程动态的委派给另一个对象，从而动态地决定客户端将得到哪些具体的类的实例，以及这些类的实例是如何被创建和组合在一起的。<br />    Simple Factory是类的创建模式，又称为Static Factory Method模式，它是由一个工厂对象决定创造出哪一种产品类的实例。工厂模式负责将大量有共同接口的类实例化。工厂模式可以动态的决定哪一个类实例化，不必事先知道每次要实例化哪一个类。工厂模式有如下的几种形态</font>:<br />● Simple Factory 模式：又叫Static Factory Method.<br />● Factory Method模式：又称多态工厂（Polymorphic Factory）模式。<br />● Abstract Factory模式：又称工具箱（Kit或ToolKit）模式。<br />简单工厂模式涉及到工厂角色，抽象产品角色以及具体产品角色等三个角色：<br />● 工厂类（Creator）角色：担任这个角色的是工厂方法模式的核心，含有与应用紧密相关的商业逻辑。工厂类在客户端的直接调用下创建产品对象，它往往由一个具体的java类实现。<br />● 抽象产品（Product）角色：担任这个角色的是由工厂方法模式所创建的对象的父类，或它们共同拥有的接口。抽象产品可以由一个Java接口或Java抽象类实现。<br />● 具体产品（Concrete Product）角色：工厂模式所创建的任何对象都是这个角色的实例，具体产品角色由一个具体的Java类实现。<br />demo:<br /> 以农场为例子，农场公司专门向市场销售水果。农场得有专门的园丁来管理水果。<br />interface Fruti<br />{<br /> //水果的接口<br /> /**<br /> * 生长<br /> */<br /> void grow();  <br /> <br /> /**<br /> * 收获<br /> */<br /> void harvest(); <br /> <br /> /**<br /> * 种植<br /> */<br /> void plant(); <br />}<br />具体的水果:苹果，葡萄，草莓<br />Apple.java:<br />class Apple implements Fruit<br />{<br /> private int treeAge;   //苹果的树龄<br /> <br /> /**<br /> * 生长<br /> */<br /> public void grow()<br /> {<br />  log("Apple is growing......");<br /> }<br /> <br /> /**<br /> * 收获<br /> */<br /> pubic void harvest()<br /> {<br />  log("Apple has been harvested.");<br /> }<br /> <br /> /**<br /> * 种植<br /> */<br /> public void plant()<br /> {<br />  log("Apple has been planted");<br /> }<br /> <br /> /**<br /> * 辅助方法<br /> */<br /> public static void log(String str)<br /> {<br />  System.out.println(str);<br /> }<br /> <br /> /**<br /> * 树龄的取值方法<br /> */<br /> public int getTreeAge()<br /> {<br />  return this.treeAge;<br /> }<br /> <br /> /**<br /> * 树龄的赋值方法<br /> */<br /> public void setTreeAge(int treeAge)<br /> {<br />  this.treeAge = treeAge;<br /> }<br />}<br /><br />Grape.java<br />class Grape implements Fruit<br />{<br /> private boolean seedless;  //葡萄的籽<br /> <br /> /**<br /> * 生长<br /> */<br /> public void grow()<br /> {<br />  log("Grape is growing.....");<br /> }<br /> <br /> /**<br /> * 收获<br /> */<br /> public void harvest()<br /> {<br />  log("Grape has been harveted");<br /> }<br /> <br /> /**<br /> * 种植<br /> */<br /> public void plant()<br /> {<br />  log("Grape has been planted");<br /> }<br /> <br /> /**<br /> * 辅助方法<br /> */<br /> public static void log(String msg)<br /> {<br />  System.out.println(msg);<br /> }<br /> <br /> /**<br /> * 有无籽的取值方法<br /> */<br /> public boolean getSeedless()<br /> {<br />  return this.seedless;<br /> }<br /> <br /> /**<br /> * 有无籽的赋值方法<br /> */<br /> public void setSeedless(boolean seedless)<br /> {<br />  this.seedless = seedless;<br /> }<br />}<br /><br />Strawberry.java<br />class Strawberry implements Fruit<br />{<br /> /**<br /> * 生长<br /> */<br /> public void grow()<br /> {<br />  log("Strawberry is growing.....");<br /> }<br /> <br /> /**<br /> * 收获<br /> */<br /> public void harvest()<br /> {<br />  log("Strawberry has been harvested");<br /> }<br /> <br /> /**<br /> * 种植<br /> */<br /> public void plant()<br /> {<br />  log("Strawberry has been planted");<br /> }<br /> <br /> /**<br /> * 辅助方法<br /> */<br /> public static void log(String msg)<br /> {<br />  System.out.println(msg);<br /> }<br />}<br /><br />具体的园丁:<br />public class FruitGradener<br />{<br /> /**<br /> * 静态工厂方法<br /> */<br /> public static Fruti factory(String witch)throws BadFruitException<br /> {<br />  if(witch.equalsIgnoreCase("apple"))<br />  {<br />   return new Apple();<br />  }<br />  else if(withc.equalsIgnoreCase("Grape"))<br />  {<br />   return new Grape();<br />  }<br />  else if(witch.equalsIgnoreCase("Strawberry"))<br />  {<br />   return new Strawberry();<br />  }<br />  else<br />  {<br />   thow new BasFruitException("Bad fruit request");<br />  }<br /> }<br />}<br /><br />抽象产品角色的主要目的就是给所有的具体产品提供一个共同的类型，在最简单的情况下可以简化为一个标识接口。如:<br />public interface Product<br />{<br />}<br /><br />工厂类角色就是创建一个新的具体产品实例返回给调用者。如:<br />public class  Creator<br />{<br />   /**<br />   * 静态工厂方法<br />   */<br />    return new ConreteProduct();<br />}<br /><br />具体的产品就是实际的对象了，如:<br />public class ConreteProduct implemnts Product<br />{<br />    public ConcreteProduct(){}<br />}<br /><br />如果模式所产生的具体产品类彼此之间没有共同的商业逻辑，那么抽象产品可以由一个JAVA接口扮演，如果有共同的商务逻辑则应当使用抽象角色扮演。这样共同的逻辑都放到抽象类里去了，达到共享的目的。<img src ="http://www.blogjava.net/antsoul/aggbug/107608.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/antsoul/" target="_blank">antsoul</a> 2007-03-31 10:53 <a href="http://www.blogjava.net/antsoul/archive/2007/03/31/107608.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java接口与Java抽象类的区别</title><link>http://www.blogjava.net/antsoul/archive/2007/03/29/107131.html</link><dc:creator>antsoul</dc:creator><author>antsoul</author><pubDate>Thu, 29 Mar 2007 02:00:00 GMT</pubDate><guid>http://www.blogjava.net/antsoul/archive/2007/03/29/107131.html</guid><wfw:comment>http://www.blogjava.net/antsoul/comments/107131.html</wfw:comment><comments>http://www.blogjava.net/antsoul/archive/2007/03/29/107131.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/antsoul/comments/commentRss/107131.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/antsoul/services/trackbacks/107131.html</trackback:ping><description><![CDATA[
		<font size="2">        在Java语言中，可以定义一种抽象类型，并且提供这种这一抽象类型的各种具体实现。实际上Java给我们提供不只是一种机制而是两种让我们可以做到这一点。它们是Java接口和Java抽象类。二者的区别如下：<br />       (1) 两者最明显的区别在于，Java抽象类可以提供部分方法的实现，而Java接口不能。这是Java抽象类的有点也是优势。如果向一个抽象类加入一个新的具体的方法，那么所有的子类一下子就得到了这个新的具体的方法。如果向一个接口中加入一个新的方法，所有实现这个接口的类都不能全部成功的通过编译，因为它们没有实现这个新声明的方法。这就是Java接口的一个缺点了。<br />       (2) 一个抽象类的实现只能由这个抽象类的子类给出，那么，这个实现出在抽象类所定义出的继承的等级结构中，而由于Java语言限制多继承，因此抽象类作为类型定义工具的效果就大打折扣了。反之，任何一个实现了Java接口所规定的方法的类都可以具有这个接口的类型，而一个类可以实现多个接口。这也是两者最重要的区别之一。<br />      (3) 从代码重构的角度上看，将一个单独的Java具体类重构为一个Java接口的实现是很容易的。我们只需要声明一个接口，并将重要的方法添家到接口声明中，然后在具体的类定义语句后加上一个何时的implments就OK了。而为一个已有的具体类添加一个抽象类作为抽象类型却不是那么的容易了，因为这个具体类有可能已经有了一个超类，这样以来，这个新定义的抽象类只好继续向上移动，变成这个超类的超类，如此循环，最后这个新定义的抽象类必定处于整个等级类型结构的最上端，从而使得等级结构中的所有成员都受到影响。<br />      (4) Java接口是定义混合类型的理想工具。Mixin Type就是在一个类主类型之外的次类型。一个混合类表明一个类不仅具有主类型的行为，而且还具有其它的行为。比如Hashtabl类就具有多个类型。它的主类型为Map，这是一种Java聚集。而Cloneable接口则给出了一个次要类型，这个类型说明这个类是可以安全克隆的。同样，Serializable也是一个次要类型，它表明这个类是可以串行化的。</font>
<img src ="http://www.blogjava.net/antsoul/aggbug/107131.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/antsoul/" target="_blank">antsoul</a> 2007-03-29 10:00 <a href="http://www.blogjava.net/antsoul/archive/2007/03/29/107131.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Relation in Classes</title><link>http://www.blogjava.net/antsoul/archive/2007/03/28/107033.html</link><dc:creator>antsoul</dc:creator><author>antsoul</author><pubDate>Wed, 28 Mar 2007 09:34:00 GMT</pubDate><guid>http://www.blogjava.net/antsoul/archive/2007/03/28/107033.html</guid><wfw:comment>http://www.blogjava.net/antsoul/comments/107033.html</wfw:comment><comments>http://www.blogjava.net/antsoul/archive/2007/03/28/107033.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/antsoul/comments/commentRss/107033.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/antsoul/services/trackbacks/107033.html</trackback:ping><description><![CDATA[
		<p>Relation in Class<br /><br />Generalization(一般化)：<br />表示类与类之间的继承关系，接口与接口之间的继承关系或类对接口的实现关系。<br />Association(关联)：<br />类与类之间的连接，它使一个类知道另一个类的属性和方法。每个Association都有两个端点，每个端点都可以是一个角色，显示出关联的本质。Driver------------&gt;&gt;&gt;&gt;Car.<br />Aggregation(聚合)：<br />聚合是一种强烈的关联关系。它强调整体与个体的关系。区分关联与聚合的关键为逻辑关系。<br />Composition(合成)：<br />关联关系的一种，是比聚合关系还要强的关系。它要求普通的聚合关系中代表整体的对象负责代表部分对象的生命周期，合成关系不能共享。<br />Dependency(依赖)：<br />类与类之间的连接，依赖是单向的表示一个类依赖另一个类的定义。<br /><br /></p>
<img src ="http://www.blogjava.net/antsoul/aggbug/107033.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/antsoul/" target="_blank">antsoul</a> 2007-03-28 17:34 <a href="http://www.blogjava.net/antsoul/archive/2007/03/28/107033.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>设计模式之Proxy(代理)【转】</title><link>http://www.blogjava.net/antsoul/archive/2007/03/28/107025.html</link><dc:creator>antsoul</dc:creator><author>antsoul</author><pubDate>Wed, 28 Mar 2007 09:08:00 GMT</pubDate><guid>http://www.blogjava.net/antsoul/archive/2007/03/28/107025.html</guid><wfw:comment>http://www.blogjava.net/antsoul/comments/107025.html</wfw:comment><comments>http://www.blogjava.net/antsoul/archive/2007/03/28/107025.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/antsoul/comments/commentRss/107025.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/antsoul/services/trackbacks/107025.html</trackback:ping><description><![CDATA[
		<p>作者:banq<br />理解并使用设计模式,能够培养我们良好的面向对象编程习惯,同时在实际应用中,可以如鱼得水,享受游刃有余的乐趣.</p>
		<p>代理模式是比较有用途的一种模式,而且变种较多,应用场合覆盖从小结构到整个系统的大结构,Proxy是代理的意思,我们也许有代理服务器等概念,代理概念可以解释为:在出发点到目的地之间有一道中间层,意为代理.</p>
		<p>
				<b>设计模式中定义</b>: 为其他对象提供一种代理以控制对这个对象的访问.</p>
		<p>
				<b>为什么要使用Proxy?</b>
				<br />1.授权机制 不同级别的用户对同一对象拥有不同的访问权利,如Jive论坛系统中,就使用Proxy进行授权机制控制,访问论坛有两种人:注册用户和游客(未注册用户),Jive中就通过类似ForumProxy这样的代理来控制这两种用户对论坛的访问权限.</p>
		<p>2.某个客户端不能直接操作到某个对象,但又必须和那个对象有所互动.<br />举例两个具体情况: <br />(1)如果那个对象是一个是很大的图片,需要花费很长时间才能显示出来,那么当这个图片包含在文档中时,使用编辑器或浏览器打开这个文档,打开文档必须很迅速,不能等待大图片处理完成,这时需要做个图片Proxy来代替真正的图片.<br /><br />(2)如果那个对象在Internet的某个远端服务器上,直接操作这个对象因为网络速度原因可能比较慢,那我们可以先用Proxy来代替那个对象.<br /></p>
		<p>总之原则是,对于开销很大的对象,只有在使用它时才创建,这个原则可以为我们节省很多宝贵的Java内存. 所以,有些人认为Java耗费资源内存,我以为这和程序编制思路也有一定的关系.</p>
		<p>
				<b>如何使用Proxy?</b>
				<br />以<a href="http://www.jdon.com/dl/jive.zip">Jive论坛系统</a>为例,访问论坛系统的用户有多种类型:注册普通用户 论坛管理者 系统管理者 游客,注册普通用户才能发言;论坛管理者可以管理他被授权的论坛;系统管理者可以管理所有事务等,这些权限划分和管理是使用Proxy完成的.</p>
		<p>Forum是Jive的核心接口,在Forum中陈列了有关论坛操作的主要行为,如论坛名称 论坛描述的获取和修改,帖子发表删除编辑等.</p>
		<p>在ForumPermissions中定义了各种级别权限的用户:</p>
		<table cellspacing="3" cellpadding="3" width="80%" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">public class ForumPermissions implements Cacheable { 
<p>/**<br />* Permission to read object.<br />*/<br />public static final int READ = 0;</p><p>/**<br />* Permission to administer the entire sytem.<br />*/<br />public static final int SYSTEM_ADMIN = 1;</p><p>/**<br />* Permission to administer a particular forum.<br />*/<br />public static final int FORUM_ADMIN = 2;</p><p>/**<br />* Permission to administer a particular user.<br />*/<br />public static final int USER_ADMIN = 3;</p><p>/**<br />* Permission to administer a particular group.<br />*/<br />public static final int GROUP_ADMIN = 4;</p><p>/**<br />* Permission to moderate threads.<br />*/<br />public static final int MODERATE_THREADS = 5;</p><p>/**<br />* Permission to create a new thread.<br />*/<br />public static final int CREATE_THREAD = 6;</p><p>/**<br />* Permission to create a new message.<br />*/<br />public static final int CREATE_MESSAGE = 7;</p><p>/**<br />* Permission to moderate messages.<br />*/<br />public static final int MODERATE_MESSAGES = 8;</p><p>.....</p><p>public boolean isSystemOrForumAdmin() {<br />　　return (values[FORUM_ADMIN] || values[SYSTEM_ADMIN]);<br />}</p><p>.....</p><p>}</p></td>
						</tr>
				</tbody>
		</table>
		<p>因此,Forum中各种操作权限是和ForumPermissions定义的用户级别有关系的,作为接口Forum的实现:ForumProxy正是将这种对应关系联系起来.比如,修改Forum的名称,只有论坛管理者或系统管理者可以修改,代码如下:</p>
		<table cellspacing="3" cellpadding="3" width="80%" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">
										<p>public class ForumProxy implements Forum {</p>
										<p>private ForumPermissions permissions;<br />private Forum forum; <br />this.authorization = authorization; <br /><br />public ForumProxy(Forum forum, Authorization authorization,<br />ForumPermissions permissions)<br />{<br />this.forum = forum;<br />this.authorization = authorization;<br />this.permissions = permissions;<br />}<br /><br />.....</p>
										<p>public void setName(String name) throws UnauthorizedException,<br />ForumAlreadyExistsException<br />{<br />　　//只有是系统或论坛管理者才可以修改名称<br />　　if (permissions.isSystemOrForumAdmin()) {<br />　　　　forum.setName(name);<br />　　}<br />　　else {<br />　　　　throw new UnauthorizedException();<br />　　}<br />}</p>
										<p>...</p>
										<p>}<br /></p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>而DbForum才是接口Forum的真正实现,以修改论坛名称为例:</p>
		<table cellspacing="3" cellpadding="3" width="80%" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">
										<p>public class DbForum implements Forum, Cacheable {<br />...</p>
										<p>public void setName(String name) throws ForumAlreadyExistsException {<br /><br />　　....<br /><br />　　this.name = name;<br />　　//这里真正将新名称保存到数据库中 <br />　　saveToDb();</p>
										<p>　　....<br />}<br /></p>
										<p>
												<br />... </p>
										<p>}</p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>凡是涉及到对论坛名称修改这一事件,其他程序都首先得和ForumProxy打交道,由ForumProxy决定是否有权限做某一样事情,ForumProxy是个名副其实的"网关","安全代理系统".</p>
		<p>在平时应用中,无可避免总要涉及到系统的授权或安全体系,不管你有无意识的使用Proxy,实际你已经在使用Proxy了.</p>
		<p>我们继续结合Jive谈入深一点,下面要涉及到工厂模式了,如果你不了解工厂模式,请看我的另外一篇文章:<a href="http://www.jdon.com/designpatterns/designpattern_factory.htm" target="_blank">设计模式之Factory</a></p>
		<p>我们已经知道,使用Forum需要通过ForumProxy,Jive中创建一个Forum是使用Factory模式,有一个总的抽象类ForumFactory,在这个抽象类中,调用ForumFactory是通过getInstance()方法实现,这里使用了Singleton(也是设计模式之一,由于介绍文章很多,我就不写了,<a href="http://www-900.ibm.com/developerWorks/java/designpattern/singleton/index.shtml" target="_blank">看这里</a>),getInstance()返回的是ForumFactoryProxy.</p>
		<p>为什么不返回ForumFactory,而返回ForumFactory的实现ForumFactoryProxy?<br />原因是明显的,需要通过代理确定是否有权限创建forum.</p>
		<p>在ForumFactoryProxy中我们看到代码如下:</p>
		<table cellspacing="3" cellpadding="3" width="98%" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">public class ForumFactoryProxy extends ForumFactory { 
<p>　　protected ForumFactory factory;<br />　　protected Authorization authorization;<br />　　protected ForumPermissions permissions;</p><p>　　public ForumFactoryProxy(Authorization authorization, ForumFactory factory,<br />　　ForumPermissions permissions)<br />　　{<br />　　　　this.factory = factory;<br />　　　　this.authorization = authorization;<br />　　　　this.permissions = permissions;<br />　　}</p><p>　　public Forum createForum(String name, String description)<br />　　　　　　throws UnauthorizedException, ForumAlreadyExistsException<br />　　{<br />　　　　//只有系统管理者才可以创建forum <br />　　　　if (permissions.get(ForumPermissions.SYSTEM_ADMIN)) {<br />　　　　　　Forum newForum = factory.createForum(name, description);<br />　　　　　　return new ForumProxy(newForum, authorization, permissions);<br />　　　　}<br />　　　　else {<br />　　　　　　throw new UnauthorizedException();<br />　　}<br />}<br /></p></td>
						</tr>
				</tbody>
		</table>
		<p>方法createForum返回的也是ForumProxy, Proxy就象一道墙,其他程序只能和Proxy交互操作.</p>
		<p>注意到这里有两个Proxy:ForumProxy和ForumFactoryProxy. 代表两个不同的职责:使用Forum和创建Forum;<br />至于为什么将使用对象和创建对象分开,这也是为什么使用Factory模式的原因所在:是为了"封装" "分派";换句话说,尽可能功能单一化,方便维护修改.</p>
		<p>Jive论坛系统中其他如帖子的创建和使用,都是按照Forum这个思路而来的.</p>
		<p>以上我们讨论了如何使用Proxy进行授权机制的访问,Proxy还可以对用户隐藏另外一种称为copy-on-write的优化方式.拷贝一个庞大而复杂的对象是一个开销很大的操作,如果拷贝过程中,没有对原来的对象有所修改,那么这样的拷贝开销就没有必要.用代理延迟这一拷贝过程.</p>
		<p>比如:我们有一个很大的Collection,具体如hashtable,有很多客户端会并发同时访问它.其中一个特别的客户端要进行连续的数据获取,此时要求其他客户端不能再向hashtable中增加或删除 东东.</p>
		<p>最直接的解决方案是:使用collection的lock,让这特别的客户端获得这个lock,进行连续的数据获取,然后再释放lock.<br />public void foFetches(Hashtable ht){<br />　　synchronized(ht){<br />　　　　//具体的连续数据获取动作.. <br />　　} </p>
		<p>}<br /></p>
		<p>但是这一办法可能锁住Collection会很长时间,这段时间,其他客户端就不能访问该Collection了.</p>
		<p>第二个解决方案是clone这个Collection,然后让连续的数据获取针对clone出来的那个Collection操作.这个方案前提是,这个Collection是可clone的,而且必须有提供深度clone的方法.Hashtable就提供了对自己的clone方法,但不是Key和value对象的clone,关于Clone含义可以参考<a href="http://www-900.ibm.com/developerWorks/java/l-jpointer/index.shtml" target="_blank">专门文章</a>.<br />public void foFetches(Hashtable ht){<br /></p>
		<p>　　Hashttable newht=(Hashtable)ht.clone();</p>
		<p>}</p>
		<p>问题又来了,由于是针对clone出来的对象操作,如果原来的母体被其他客户端操作修改了, 那么对clone出来的对象操作就没有意义了.</p>
		<p>最后解决方案:我们可以等其他客户端修改完成后再进行clone,也就是说,这个特别的客户端先通过调用一个叫clone的方法来进行一系列数据获取操作.但实际上没有真正的进行对象拷贝,直至有其他客户端修改了这个对象Collection.</p>
		<p>使用Proxy实现这个方案.这就是copy-on-write操作.</p>
		<p>Proxy应用范围很广,现在流行的分布计算方式RMI和Corba等都是Proxy模式的应用.</p>
		<p>更多Proxy应用,见<a href="http://www.research.umbc.edu/%7Etarr/cs491/lectures/Proxy.pdf" target="_blank">http://www.research.umbc.edu/~tarr/cs491/lectures/Proxy.pdf</a></p>
		<p>Sun公司的 <a href="http://developer.java.sun.com/developer/technicalArticles/DataTypes/proxy/" target="_blank">Explore the Dynamic Proxy API</a><a href="http://java.sun.com/j2se/1.4/docs/guide/reflection/proxy.html" target="_blank">Dynamic Proxy Classes</a></p>
<img src ="http://www.blogjava.net/antsoul/aggbug/107025.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/antsoul/" target="_blank">antsoul</a> 2007-03-28 17:08 <a href="http://www.blogjava.net/antsoul/archive/2007/03/28/107025.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>设计模式之Singleton(单态)</title><link>http://www.blogjava.net/antsoul/archive/2007/03/28/107024.html</link><dc:creator>antsoul</dc:creator><author>antsoul</author><pubDate>Wed, 28 Mar 2007 09:06:00 GMT</pubDate><guid>http://www.blogjava.net/antsoul/archive/2007/03/28/107024.html</guid><wfw:comment>http://www.blogjava.net/antsoul/comments/107024.html</wfw:comment><comments>http://www.blogjava.net/antsoul/archive/2007/03/28/107024.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/antsoul/comments/commentRss/107024.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/antsoul/services/trackbacks/107024.html</trackback:ping><description><![CDATA[
		<p>
				<strong>单态定义</strong>:<br />Singleton模式主要作用是保证在Java应用程序中，一个类Class只有一个实例存在。 </p>
		<p>在很多操作中，比如建立目录 数据库连接都需要这样的单线程操作。</p>
		<p>还有, singleton能够被状态化; 这样，多个单态类在一起就可以作为一个状态仓库一样向外提供服务，比如，你要论坛中的帖子计数器，每次浏览一次需要计数，单态类能否保持住这个计数，并且能synchronize的安全自动加1，如果你要把这个数字永久保存到数据库，你可以在不修改单态接口的情况下方便的做到。</p>
		<p>另外方面，Singleton也能够被无状态化。提供工具性质的功能，<br /><br />Singleton模式就为我们提供了这样实现的可能。使用Singleton的好处还在于可以节省内存，因为它限制了实例的个数，有利于Java垃圾回收（garbage collection）。<br /><br />我们常常看到工厂模式中类装入器(class loader)中也用Singleton模式实现的,因为被装入的类实际也属于资源。<br /></p>
		<p>
				<strong>如何使用?</strong>
				<br />一般Singleton模式通常有几种形式:</p>
		<table cellspacing="3" cellpadding="3" width="100%" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">
										<p>public class Singleton {</p>
										<p>　　private Singleton(){}</p>
										<p>　　//在自己内部定义自己一个实例，是不是很奇怪？<br />　　//注意这是private 只供内部调用</p>
										<p>　　private static Singleton instance = new Singleton();</p>
										<p>　　//这里提供了一个供外部访问本class的静态方法，可以直接访问　　<br />　　public static Singleton getInstance() {<br />　　　　return instance; 　　<br />　　 } <br />} </p>
										<p> </p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>第二种形式:</p>
		<table cellspacing="3" cellpadding="3" width="100%" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">public class Singleton { 
<p>　　private static Singleton instance = null;<br /><br />　　public static synchronized Singleton getInstance() {<br /><br />　　//这个方法比上面有所改进，不用每次都进行生成对象，只是第一次　　　 　<br />　　//使用时生成实例！<br />　　if (instance==null)<br />　　　　instance＝new Singleton();<br />　　return instance; 　　} </p><p>} </p><p> </p></td>
						</tr>
				</tbody>
		</table>
		<p>使用Singleton.getInstance()可以访问单态类。</p>
		<p>上面第二中形式是lazy initialization，也就是说第一次调用时初始Singleton，以后就不用再生成了。</p>
		<p>注意到lazy initialization形式中的synchronized，这个synchronized很重要，如果没有synchronized，那么使用getInstance()是有可能得到多个Singleton实例。关于lazy initialization的Singleton有很多涉及double-checked locking (DCL)的讨论，有兴趣者进一步研究。</p>
		<p>一般认为第一种形式要更加安全些。<br /></p>
		<p>
				<strong>使用Singleton注意事项</strong>：<br />有时在某些情况下，使用Singleton并不能达到Singleton的目的，如有多个Singleton对象同时被不同的类装入器装载；在EJB这样的分布式系统中使用也要注意这种情况，因为EJB是跨服务器，跨JVM的。</p>
		<p>我们以SUN公司的宠物店源码(Pet Store 1.3.1)的ServiceLocator为例稍微分析一下：<br /><br />在Pet Store中ServiceLocator有两种，一个是EJB目录下；一个是WEB目录下，我们检查这两个ServiceLocator会发现内容差不多，都是提供EJB的查询定位服务，可是为什么要分开呢？仔细研究对这两种ServiceLocator才发现区别：在WEB中的ServiceLocator的采取Singleton模式，ServiceLocator属于资源定位，理所当然应该使用Singleton模式。但是在EJB中，Singleton模式已经失去作用，所以ServiceLocator才分成两种，一种面向WEB服务的，一种是面向EJB服务的。</p>
		<p>Singleton模式看起来简单，使用方法也很方便，但是真正用好，是非常不容易，需要对Java的类 线程 内存等概念有相当的了解。</p>
		<p>总之：如果你的应用基于容器，那么Singleton模式少用或者不用，可以使用相关替代技术。</p>
<img src ="http://www.blogjava.net/antsoul/aggbug/107024.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/antsoul/" target="_blank">antsoul</a> 2007-03-28 17:06 <a href="http://www.blogjava.net/antsoul/archive/2007/03/28/107024.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>设计模式之Factory</title><link>http://www.blogjava.net/antsoul/archive/2007/03/28/107011.html</link><dc:creator>antsoul</dc:creator><author>antsoul</author><pubDate>Wed, 28 Mar 2007 08:33:00 GMT</pubDate><guid>http://www.blogjava.net/antsoul/archive/2007/03/28/107011.html</guid><wfw:comment>http://www.blogjava.net/antsoul/comments/107011.html</wfw:comment><comments>http://www.blogjava.net/antsoul/archive/2007/03/28/107011.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/antsoul/comments/commentRss/107011.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/antsoul/services/trackbacks/107011.html</trackback:ping><description><![CDATA[
		<strong>
				<em>厂模式定义<span lang="EN-US">:提供创建对象的接口.</span></em>
		</strong>
		<p>
				<strong>
						<em>为何使用<span lang="EN-US">?</span></em>
				</strong>
				<span lang="EN-US">
						<br />工厂模式是我们最常用的模式了,著名的Jive论坛 ,就大量使用了工厂模式，工厂模式在Java程序系统可以说是随处可见。</span>
		</p>
		<p>为什么工厂模式是如此常用？因为工厂模式就相当于创建实例对象的<span lang="EN-US">new，我们经常要根据类Class生成实例对象，如A a=new A() 工厂模式也是用来创建实例对象的，所以以后new时就要多个心眼，是否可以考虑实用工厂模式，虽然这样做，可能多做一些工作，但会给你系统带来更大的可扩展性和尽量少的修改量。</span></p>
		<p>我们以类<span lang="EN-US">Sample为例， 如果我们要创建Sample的实例对象:</span></p>
		<p>
				<span lang="EN-US">Sample sample=new Sample();</span>
		</p>
		<p>可是，实际情况是，通常我们都要在创建<span lang="EN-US">sample实例时做点初始化的工作,比如赋值 查询数据库等。</span></p>
		<p>首先，我们想到的是，可以使用<span lang="EN-US">Sample的构造函数，这样生成实例就写成:</span></p>
		<p>
				<span lang="EN-US">Sample sample=new Sample(参数);</span>
		</p>
		<p>但是，如果创建<span lang="EN-US">sample实例时所做的初始化工作不是象赋值这样简单的事，可能是很长一段代码，如果也写入构造函数中，那你的代码很难看了（就需要Refactor重整）。</span></p>
		<p>为什么说代码很难看，初学者可能没有这种感觉，我们分析如下，初始化工作如果是很长一段代码，说明要做的工作很多，将很多工作装入一个方法中，相当于将很多鸡蛋放在一个篮子里，是很危险的，这也是有背于<span lang="EN-US">Java面向对象的原则，面向对象的封装(Encapsulation)和分派(Delegation)告诉我们，尽量将长的代码分派“切割”成每段，将每段再“封装”起来(减少段和段之间偶合联系性)，这样，就会将风险分散，以后如果需要修改，只要更改每段，不会再发生牵一动百的事情。</span></p>
		<p>在本例中，首先，我们需要将创建实例的工作与使用实例的工作分开<span lang="EN-US">, 也就是说，让创建实例所需要的大量初始化工作从Sample的构造函数中分离出去。</span></p>
		<p>这时我们就需要<span lang="EN-US">Factory工厂模式来生成对象了，不能再用上面简单new Sample(参数)。</span>还有<span lang="EN-US">,如果Sample有个继承如MySample, 按照面向接口编程,我们需要将Sample抽象成一个接口.</span>现在<span lang="EN-US">Sample是接口,有两个子类MySample 和HisSample .我们要实例化他们时,如下:</span></p>
		<p>
				<span lang="EN-US">Sample mysample=new MySample();<br />Sample hissample=new HisSample();</span>
		</p>
		<p>随着项目的深入<span lang="EN-US">,Sample可能还会"生出很多儿子出来", 那么我们要对这些儿子一个个实例化,更糟糕的是,可能还要对以前的代码进行修改:加入后来生出儿子的实例.这在传统程序中是无法避免的.</span></p>
		<p>但如果你一开始就有意识使用了工厂模式<span lang="EN-US">,这些麻烦就没有了.</span></p>
		<p>
				<strong>工厂方法<br /></strong>你会建立一个专门生产<span lang="EN-US">Sample实例的工厂:</span></p>
		<table style="WIDTH: 80%; mso-cellspacing: 2.2pt; mso-padding-alt: 2.25pt 2.25pt 2.25pt 2.25pt" cellspacing="3" cellpadding="0" width="80%" border="0">
				<tbody>
						<tr>
								<td style="PADDING-RIGHT: 2.25pt; PADDING-LEFT: 2.25pt; BACKGROUND: #cccccc; PADDING-BOTTOM: 2.25pt; PADDING-TOP: 2.25pt">
										<p>
												<span lang="EN-US">public class Factory{</span>
										</p>
										<p>　　<span lang="EN-US">public static Sample creator(int which){</span></p>
										<p>　　//getClass <span lang="EN-US">产生Sample 一般可使用动态类装载装入类。<br />　　if (which==1)<br />　　　　return new SampleA();<br />　　else if (which==2)<br />　　　　return new SampleB();</span></p>
										<p>　　<span lang="EN-US">}</span></p>
										<p>
												<span lang="EN-US">}</span>
										</p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>那么在你的程序中<span lang="EN-US">,如果要实例化Sample时.就使用</span></p>
		<p>
				<span lang="EN-US">Sample sampleA=Factory.creator(1);</span>
		</p>
		<p>这样<span lang="EN-US">,在整个就不涉及到Sample的具体子类,达到封装效果,也就减少错误修改的机会,这个原理可以用很通俗的话来比喻:就是具体事情做得越多,越容易范错误.这每个做过具体工作的人都深有体会,相反,官做得越高,说出的话越抽象越笼统,范错误可能性就越少.好象我们从编程序中也能悟出人生道理?呵呵.</span></p>
		<p>使用工厂方法 要注意几个角色，首先你要定义产品接口，如上面的Sample,产品接口下有Sample接口的实现类,如SampleA,其次要有一个factory类，用来生成产品Sample，如下图，最右边是生产的对象Sample：</p>
		<p>
				<img height="178" src="http://www.jdon.com/designpatterns/images/factory.jpg" width="526" />
		</p>
		<p>进一步稍微复杂一点，就是在工厂类上进行拓展，工厂类也有继承它的实现类concreteFactory了<b><i>。</i></b></p>
		<p>
				<span lang="EN-US">
						<strong>抽象工厂</strong>
						<br />工厂模式中有: 工厂方法(Factory Method) 抽象工厂(Abstract Factory).</span>
		</p>
		<p style="MARGIN-BOTTOM: 12pt">
				<span lang="EN-US">这两个模式区别在于需要创建对象的复杂程度上。如果我们创建对象的方法变得复杂了,如上面工厂方法中是创建一个对象Sample,如果我们还有新的产品接口Sample2.</span>
		</p>
		<p style="MARGIN-BOTTOM: 12pt">这里假设：Sample有两个concrete类SampleA和SamleB，而Sample2也有两个concrete类Sample2A和SampleB2</p>
		<p style="MARGIN-BOTTOM: 12pt">
				<span lang="EN-US">那么，我们就将上例中Factory变成抽象类,将共同部分封装在抽象类中,不同部分使用子类实现，下面就是将上例中的Factory拓展成抽象工厂:</span>
		</p>
		<table style="WIDTH: 80%; mso-cellspacing: 2.2pt; mso-padding-alt: 2.25pt 2.25pt 2.25pt 2.25pt" cellspacing="3" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td style="PADDING-RIGHT: 2.25pt; PADDING-LEFT: 2.25pt; BACKGROUND: #cccccc; PADDING-BOTTOM: 2.25pt; PADDING-TOP: 2.25pt">
										<p>
												<span lang="EN-US">public abstract class Factory{</span>
										</p>
										<p>　　<span lang="EN-US">public abstract Sample creator();</span></p>
										<p>　　<span lang="EN-US">public abstract Sample2 creator(String name); </span></p>
										<p>
												<span lang="EN-US">}</span>
										</p>
										<p>
												<span lang="EN-US">public class SimpleFactory extends Factory{</span>
										</p>
										<p>　　<span lang="EN-US">public Sample creator(){<br />　　　　.........<br />　　<span lang="EN-US"></span>　　<span lang="EN-US"></span>return new SampleA</span><span lang="EN-US"><br />　　}</span></p>
										<p>　　<span lang="EN-US">public Sample2 creator(String name){<br />　　　　.........<br />　　<span lang="EN-US"></span>　　<span lang="EN-US"></span>return new Sample2A</span><span lang="EN-US"></span><span lang="EN-US"><br />　　}</span></p>
										<p>
												<span lang="EN-US">}</span>
										</p>
										<p>
												<span lang="EN-US">public class BombFactory extends Factory{</span>
										</p>
										<p>　　<span lang="EN-US">public Sample creator(){<br />　　　　......<br />　　<span lang="EN-US"></span>　　<span lang="EN-US"></span>return new SampleB</span><span lang="EN-US"></span><span lang="EN-US"><br />　　}</span></p>
										<p>　　<span lang="EN-US">public Sample2 creator(String name){<br />　　　　......<br />　　<span lang="EN-US"></span>　　<span lang="EN-US"></span>return new Sample2B<br />　　}</span></p>
										<p>
												<span lang="EN-US">}</span>
										</p>
										<p>
												<span lang="EN-US">
												</span> </p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>
				<span lang="EN-US">从上面看到两个工厂各自生产出一套Sample和Sample2,也许你会疑问，为什么我不可以使用两个工厂方法来分别生产Sample和Sample2? </span>
		</p>
		<p>
				<span lang="EN-US">抽象工厂还有另外一个关键要点，是因为 SimpleFactory内，生产Sample和生产Sample2的方法之间有一定联系，所以才要将这两个方法捆绑在一个类中，这个工厂类有其本身特征，也许制造过程是统一的，比如：制造工艺比较简单，所以名称叫SimpleFactory。</span>
				<span lang="EN-US">
						<br />
				</span>
		</p>
		<p>在实际应用中，工厂方法用得比较多一些，而且是和动态类装入器组合在一起应用，</p>
		<p>
				<span lang="EN-US">
						<strong>举例</strong>
						<?XML:NAMESPACE PREFIX = O /?>
						<o:p>
						</o:p>
				</span>
		</p>
		<p>我们以<span lang="EN-US">Jive的ForumFactory为例，这个例子在前面的Singleton模式中我们讨论过，现在再讨论其工厂模式:</span></p>
		<table style="WIDTH: 97%; mso-cellspacing: 2.2pt; mso-padding-alt: 2.25pt 2.25pt 2.25pt 2.25pt" cellspacing="3" cellpadding="0" width="97%" border="0">
				<tbody>
						<tr>
								<td style="PADDING-RIGHT: 2.25pt; PADDING-LEFT: 2.25pt; BACKGROUND: #cccccc; PADDING-BOTTOM: 2.25pt; PADDING-TOP: 2.25pt">
										<p>
												<span lang="EN-US">public abstract class ForumFactory {</span>
										</p>
										<p>　　<span lang="EN-US">private static Object initLock = new Object();<br />　　private static String className = "com.jivesoftware.forum.database.DbForumFactory";<br />　　private static ForumFactory factory = null; </span></p>
										<p>　　<span lang="EN-US">public static ForumFactory getInstance(Authorization authorization) {<br />　　　　//If no valid authorization passed in, return null.<br />　　　　if (authorization == null) {<br />　　　　　　return null;<br />　　　　}<br />　　　　//以下使用了Singleton 单态模式<br />　　　　if (factory == null) {<br />　　　　　　synchronized(initLock) {<br />　　　　　　　　if (factory == null) {<br />　　　　　　　　　　　　...... </span></p>
										<p>　　　　　　　　　　<span lang="EN-US">try {<br />　　　　　　　　　　　　　　//动态转载类<br />　　　　　　　　　　　　　　Class c = Class.forName(className);<br />　　　　　　　　　　　　　　factory = (ForumFactory)c.newInstance();<br />　　　　　　　　　　}<br />　　　　　　　　　　catch (Exception e) {<br />　　　　　　　　　　　　　　return null;<br />　　　　　　　　　　}<br />　　　　　　　　}<br />　　　　　　}<br />　　　　}</span></p>
										<p>　　　　<span lang="EN-US">//Now, 返回 proxy.用来限制授权对forum的访问<br />　　　　return new ForumFactoryProxy(authorization, factory,<br />　　　　　　　　　　　　　　　　　　　　factory.getPermissions(authorization));<br />　　}</span></p>
										<p>　　<span lang="EN-US">//真正创建forum的方法由继承forumfactory的子类去完成.<br />　　public abstract Forum createForum(String name, String description)<br />　　throws UnauthorizedException, ForumAlreadyExistsException;</span></p>
										<p>　　<span lang="EN-US">....</span></p>
										<p>
												<span lang="EN-US">}</span>
										</p>
										<p>
												<span lang="EN-US">
												</span> </p>
										<p>
												<span lang="EN-US">
												</span> </p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>因为现在的<span lang="EN-US">Jive是通过数据库系统存放论坛帖子等内容数据,如果希望更改为通过文件系统实现,这个工厂方法ForumFactory就提供了提供动态接口:</span></p>
		<p>
				<span lang="EN-US">private static String className = "com.jivesoftware.forum.database.DbForumFactory";</span>
		</p>
		<p>你可以使用自己开发的创建<span lang="EN-US">forum的方法代替com.jivesoftware.forum.database.DbForumFactory就可以.</span></p>
		<p>在上面的一段代码中一共用了三种模式<span lang="EN-US">,除了工厂模式外,还有Singleton单态模式,以及proxy模式,proxy模式主要用来授权用户对forum的访问,因为访问forum有两种人:一个是注册用户 一个是游客guest,那么那么相应的权限就不一样,而且这个权限是贯穿整个系统的,因此建立一个proxy,类似网关的概念,可以很好的达到这个效果.  </span></p>
		<p>看看<span lang="EN-US">Java宠物店中的CatalogDAOFactory:</span></p>
		<table cellspacing="0" cellpadding="0" width="100%" bgcolor="#cccccc" border="0">
				<tbody>
						<tr>
								<td>public class CatalogDAOFactory { 
<p></p><p>　　/**</p><p>　　* 本方法制定一个特别的子类来实现DAO模式。<br />　　* 具体子类定义是在J2EE的部署描述器中。<br />　　*/</p><p>　　public static CatalogDAO getDAO() throws CatalogDAOSysException {</p><p>　　　　CatalogDAO catDao = null;</p><p>　　　　try {</p><p>　　　　　　InitialContext ic = new InitialContext();<br />　　　　　　//动态装入CATALOG_DAO_CLASS<br />　　　　　　//可以定义自己的CATALOG_DAO_CLASS，从而在无需变更太多代码<br />　　　　　　//的前提下，完成系统的巨大变更。</p><p>　　　　　　String className =(String) ic.lookup(JNDINames.CATALOG_DAO_CLASS);</p><p>　　　　　　catDao = (CatalogDAO) Class.forName(className).newInstance();</p><p>　　　　} catch (NamingException ne) {</p><p>　　　　　　throw new CatalogDAOSysException("<br />　　　　　　　　CatalogDAOFactory.getDAO: NamingException while <br />　　　　　　　　　　getting DAO type : \n" + ne.getMessage());</p><p>　　　　} catch (Exception se) {</p><p>　　　　　　throw new CatalogDAOSysException("<br />　　　　　　　　CatalogDAOFactory.getDAO: Exception while getting <br />　　　　　　　　　　DAO type : \n" + se.getMessage());</p><p>　　　　}</p><p>　　　　return catDao;</p><p>　　}</p><p>}<br /></p></td>
						</tr>
				</tbody>
		</table>
		<p>
				<br style="mso-ignore: vglayout" clear="all" />
		</p>
		<p>
				<span lang="EN-US">CatalogDAOFactory是典型的工厂方法，catDao是通过动态类装入器className获得CatalogDAOFactory具体实现子类，这个实现子类在Java宠物店是用来操作catalog数据库，用户可以根据数据库的类型不同，定制自己的具体实现子类，将自己的子类名给与CATALOG_DAO_CLASS变量就可以。</span>
		</p>
		<p>由此可见，工厂方法确实为系统结构提供了非常灵活强大的动态扩展机制，只要我们更换一下具体的工厂方法，系统其他地方无需一点变换，就有可能将系统功能进行改头换面的变化。</p>
<img src ="http://www.blogjava.net/antsoul/aggbug/107011.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/antsoul/" target="_blank">antsoul</a> 2007-03-28 16:33 <a href="http://www.blogjava.net/antsoul/archive/2007/03/28/107011.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>初学者如何开发出一个高质量的J2EE系统【转】</title><link>http://www.blogjava.net/antsoul/archive/2007/03/28/107007.html</link><dc:creator>antsoul</dc:creator><author>antsoul</author><pubDate>Wed, 28 Mar 2007 08:30:00 GMT</pubDate><guid>http://www.blogjava.net/antsoul/archive/2007/03/28/107007.html</guid><wfw:comment>http://www.blogjava.net/antsoul/comments/107007.html</wfw:comment><comments>http://www.blogjava.net/antsoul/archive/2007/03/28/107007.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/antsoul/comments/commentRss/107007.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/antsoul/services/trackbacks/107007.html</trackback:ping><description><![CDATA[        J2EE学习者越来越多，J2EE本身技术不断在发展，涌现出各种概念，本文章试图从一种容易理解的角度对这些概念向初学者进行解释，以便掌握学习J2EE学习方向。
<p>　　首先我们需要知道Java和J2EE是两个不同概念，Java不只是指一种语言，已经代表与微软不同的另外一个巨大阵营，所以Java有时是指一种软件系统的流派，当然目前主要是.NET和Java两大主流体系。</p><p>　　J2EE可以说指Java在数据库信息系统上实现，数据库信息系统从早期的dBase、到Delphi/VB等C/S结构，发展到B/S（Browser浏览器/Server服务器）结构，而J2EE主要是指B/S结构的实现。</p><p>　　J2EE又是一种框架和标准，框架类似API、库的概念，但是要超出它们。如果需要详细了解框架，可先从设计模式开始学习。</p><p>　　J2EE是一个虚的大的概念，J2EE标准主要有三种子技术标准：WEB技术、EJB技术和JMS，谈到J2EE应该说最终要落实到这三个子概念上。</p><p>　　这三种技术的每个技术在应用时都涉及两个部分：容器部分和应用部分，Web容器也是指Jsp/Servlet容器，你如果要开发一个Web应用，无论是编译或运行，都必须要有Jsp/Servlet库或API支持（除了JDK/J2SE以外）。</p><p>　　Web技术中除了Jsp/Servlet技术外，还需要JavaBeans或Java Class实现一些功能或者包装携带数据，所以Web技术最初裸体简称为Jsp/Servlet+JavaBeans系统。</p><p>　　谈到JavaBeans技术，就涉及到组件构件技术（component），这是Java的核心基础部分，很多软件设计概念（设计模式）都是通过JavaBeans实现的。</p><p>　　JavaBeans不属于J2EE概念范畴中，如果一个JavaBeans对象被Web技术（也就是Jsp/Servlet）调用，那么JavaBeans就运行在J2EE的Web容器中；如果它被EJB调用，它就运行在EJB容器中。</p><p>　　EJB（企业JavaBeans）是普通JavaBeans的一种提升和规范，因为企业信息系统开发中需要一个可伸缩的性能和事务、安全机制，这样能保证企业系统平滑发展，而不是发展到一种规模重新更换一套软件系统。</p><p>　　至此，JavaBeans组件发展到EJB后，并不是说以前的那种JavaBeans形式就消失了，这就自然形成了两种JavaBeans技术：EJB和POJO，POJO完全不同于EJB概念，指的是普通JavaBeans，而且这个JavaBeans不依附某种框架，或者干脆可以说：这个JavaBeans是你为这个应用程序单独开发创建的。</p><p>　　J2EE应用系统开发工具有很多：如JBuilder、Eclipse等，这些IDE首先是Java开发工具，也就是说，它们首要基本功能是可以开发出JavaBeans或Java class，但是如果要开发出J2EE系统，就要落实到要么是Web技术或EJB技术，那么就有可能要一些专门模块功能(如eclipse需要lomboz插件)，最重要的是，因为J2EE系统区分为容器和应用两个部分，所以，在任何开发工具中开发J2EE都需要指定J2EE容器。</p><p>　　J2EE容器分为WEB容器和EJB容器，Tomcat/Resin是Web容器；JBoss是EJB容器+Web容器等，其中Web容器直接使用Tomcat实现的。所以你开发的Web应用程序可以在上面两种容器运行，而你开发的Web+EJB应用则只可以在JBoss服务器上运行，商业产品Websphere/Weblogic等和JBoss属于同一种性质。</p><p>　　J2EE容器也称为J2EE服务器，大部分时它们概念是一致的。</p><p>　　如果你的J2EE应用系统的数据库连接是通过JNDI获得，也就是说是从容器中获得，那么你的J2EE应用系统基本与数据库无关，如果你在你的J2EE应用系统耦合了数据库JDBC驱动的配置，那么你的J2EE应用系统就有数据库概念色彩，作为一个成熟需要推广的J2EE应用系统，不推荐和具体数据库耦合，当然这其中如何保证J2EE应用系统运行性能又是体现你的设计水平了。</p><p>　　衡量J2EE应用系统设计开发水平高低的标准就是：解耦性；你的应用系统各个功能是否能够彻底脱离？是否不相互依赖，也只有这样，才能体现可维护性、可拓展性的软件设计目标。</p><p>　　为了达到这个目的，诞生各种框架概念，J2EE框架标准将一个系统划分为WEB和EJB主要部分，当然我们有时不是以这个具体技术区分，而是从设计上抽象为表现层、服务层和持久层，这三个层次从一个高度将J2EE分离开来，实现解耦目的。</p><p>　　因此，我们实际编程中，也要将自己的功能向这三个层次上靠，做到大方向清楚，泾渭分明，但是没有技术上约束限制要做到这点是很不容易的，因此我们还是必须借助J2EE具体技术来实现，这时，你可以使用EJB规范实现服务层和持久层，Web技术实现表现层；</p><p>　　EJB为什么能将服务层从Jsp/Servlet手中分离出来，因为它对JavaBeans编码有强制的约束，现在有一种对JavaBeans弱约束，使用Ioc模式实现的（当然EJB 3.0也采取这种方式），在Ioc模式诞生前，一般都是通过工厂模式来对JavaBeans约束，形成一个服务层，这也是是Jive这样开源论坛设计原理之一。</p><p>　　由此，将服务层从表现层中分离出来目前有两种可选架构选择：管理普通JavaBeans（POJO）框架(如Spring、<a href="http://www.jdon.com/jdonframework/index.htm" target="_blank">JdonFramework</a>)以及管理EJB的EJB框架，因为EJB不只是框架，还是标准，而标准可以扩展发展，所以，这两种区别将来是可能模糊，被纳入同一个标准了。　但是，个人认为：标准制定是为某个目的服务的，总要牺牲一些换取另外一些，所以，这两种架构会长时间并存。</p><p>　　这两种架构分歧也曾经诞生一个新名词：完全POJO的系统也称为轻量级系统(lightweight)，其实这个名词本身就没有一个严格定义，更多是一个吸引人的招牌，轻量是指容易学习容易使用吗？按照这个定义，其实轻量Spring等系统并不容易学习；而且EJB 3.0（依然叫EJB）以后的系统是否可称为轻量级了呢？</p><p>　　前面谈了服务层框架，使用服务层框架可以将JavaBeans从Jsp/Servlet中分离出来，而使用表现层框架则可以将Jsp中剩余的JavaBeans完全分离，这部分JavaBeans主要负责显示相关，一般是通过标签库（taglib）实现，不同框架有不同自己的标签库，Struts是应用比较广泛的一种表现层框架。</p><p>　　这样，表现层和服务层的分离是通过两种框架达到目的，剩余的就是持久层框架了，通过持久层的框架将数据库存储从服务层中分离出来是其目的，持久层框架有两种方向：直接自己编写JDBC等SQL语句（如iBatis）；使用O/R Mapping技术实现的Hibernate和JDO技术；当然还有EJB中的实体Bean技术。</p><p>　　持久层框架目前呈现百花齐放，各有优缺点的现状，所以正如表现层框架一样，目前没有一个框架被指定为标准框架，当然，表现层框架现在又出来了一个JSF，它代表的页面组件概念是一个新的发展方向，但是复杂的实现让人有些忘而却步。</p><p>　　在所有这些J2EE技术中，虽然SUN公司发挥了很大的作用，不过总体来说：网络上有这样一个评价：SUN的理论天下无敌；SUN的产品用起来撞墙；对于初学者，特别是那些试图通过或已经通过SUN认证的初学者，赶快摆脱SUN的阴影，立即开溜，使用开源领域的产品来实现自己的应用系统。</p><p>　　最后，你的J2EE应用系统如果采取上面提到的表现层、服务层和持久层的框架实现，基本你也可以在无需深刻掌握设计模式的情况下开发出一个高质量的应用系统了。</p><p>　　还要注意的是: 开发出一个高质量的J2EE系统还需要正确的业务需求理解，那么域建模提供了一种比较切实可行的正确理解业务需求的方法，相关详细知识可从UML角度结合理解。</p><p>　　当然，如果你想设计自己的行业框架，那么第一步从设计模式开始吧，因为设计模式提供你一个实现JavaBeans或类之间解耦参考实现方法，当你学会了系统基本单元JavaBean或类之间解耦时，那么系统模块之间的解耦你就可能掌握，进而你就可以实现行业框架的提炼了，这又是另外一个发展方向了。</p><p>　　以上理念可以总结为一句话：<br />J2EE开发三件宝: Domain Model（域建模）、patterns（模式）和framework（框架）。</p><img src ="http://www.blogjava.net/antsoul/aggbug/107007.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/antsoul/" target="_blank">antsoul</a> 2007-03-28 16:30 <a href="http://www.blogjava.net/antsoul/archive/2007/03/28/107007.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Liskov Substitution Principle</title><link>http://www.blogjava.net/antsoul/archive/2007/03/25/106252.html</link><dc:creator>antsoul</dc:creator><author>antsoul</author><pubDate>Sun, 25 Mar 2007 09:39:00 GMT</pubDate><guid>http://www.blogjava.net/antsoul/archive/2007/03/25/106252.html</guid><wfw:comment>http://www.blogjava.net/antsoul/comments/106252.html</wfw:comment><comments>http://www.blogjava.net/antsoul/archive/2007/03/25/106252.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/antsoul/comments/commentRss/106252.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/antsoul/services/trackbacks/106252.html</trackback:ping><description><![CDATA[
		<font size="2">LSP：如果对每一个类型为T1的对象的O1，都有类型为T2的对象O2，使得以T1定义的所有的程序P在所有对象O1都代换为O2时，程序P没有发生变化，那么类型T2是类型T1的子类型。换言，一个软件实体如果使用的是一个基类的话，那么一定适合与其子类，而且它根本不能察觉出基类对象与子类对戏的区别。</font>
		<br />eg:<br /><font size="2">假设有两个类，一个是Base类，一个是Sub类，并且Sub类是Base类的子类。那么有一个方法如果可以接受基类对象b的话：method(Base b),那么它必然也可以接受一个子类对象s，也即有：method(Sub s);LSP是继承复用的基石，只有当衍生类可以替换掉基类，软件单位的功能会收到影响时，基类才能真正被复用，而衍生类也能够在基类的基础上增加新的功能。LSP反之就不成立了。</font><img src ="http://www.blogjava.net/antsoul/aggbug/106252.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/antsoul/" target="_blank">antsoul</a> 2007-03-25 17:39 <a href="http://www.blogjava.net/antsoul/archive/2007/03/25/106252.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>OCP</title><link>http://www.blogjava.net/antsoul/archive/2007/03/25/106249.html</link><dc:creator>antsoul</dc:creator><author>antsoul</author><pubDate>Sun, 25 Mar 2007 09:26:00 GMT</pubDate><guid>http://www.blogjava.net/antsoul/archive/2007/03/25/106249.html</guid><wfw:comment>http://www.blogjava.net/antsoul/comments/106249.html</wfw:comment><comments>http://www.blogjava.net/antsoul/archive/2007/03/25/106249.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/antsoul/comments/commentRss/106249.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/antsoul/services/trackbacks/106249.html</trackback:ping><description><![CDATA[
		<font size="2">经典力学的奠基石是牛顿的三大定律。而OOD的奠基石是OCP。OCP是Bertrand Meyer提出的: Software entities should be open for extension , but close for modifaction 。在设计一个模块的时候；应当使这个模块可以在不被修改的前提下被扩展。换言，应当不必修改源代码的情况下，改变这个模块的行为。</font>
<img src ="http://www.blogjava.net/antsoul/aggbug/106249.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/antsoul/" target="_blank">antsoul</a> 2007-03-25 17:26 <a href="http://www.blogjava.net/antsoul/archive/2007/03/25/106249.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>你还在用if else吗？【转】</title><link>http://www.blogjava.net/antsoul/archive/2007/03/17/104436.html</link><dc:creator>antsoul</dc:creator><author>antsoul</author><pubDate>Sat, 17 Mar 2007 05:29:00 GMT</pubDate><guid>http://www.blogjava.net/antsoul/archive/2007/03/17/104436.html</guid><wfw:comment>http://www.blogjava.net/antsoul/comments/104436.html</wfw:comment><comments>http://www.blogjava.net/antsoul/archive/2007/03/17/104436.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/antsoul/comments/commentRss/104436.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/antsoul/services/trackbacks/104436.html</trackback:ping><description><![CDATA[
		<font size="2">本帖转自 </font>
		<a href="http://www.jdon.com/aboutme.htm">
				<font size="2">板桥里人</font>
		</a>
		<font size="2">  2006.1.11  文章 &lt;&lt;你还在用if else吗？&gt;&gt;<br /><br />面向过程设计和面向对象设计的主要区别是：是否在业务逻辑层使用冗长的if else判断。如果你还在大量使用if else，当然，界面表现层除外，即使你使用Java/C#这样完全面向对象的语言，也只能说明你的思维停留在传统的面向过程语言上。</font>
		<p>
				<strong>
						<font size="2">传统思维习惯分析</font>
				</strong>
		</p>
		<p>
				<font size="2">　　为什么会业务逻辑层使用if else，其实使用者的目的也是为了重用，但是这是面向过程编程的重用，程序员只看到代码重用，因为他看到if else几种情况下大部分代码都是重复的，只有个别不同，因此使用if else可以避免重复代码，并且认为这是模板Template模式。</font>
		</p>
		<p>
				<font size="2">　　他范的错误是：程序员只从代码运行顺序这个方向来看待它的代码，这种思维类似水管或串行电路，水沿着水管流动（代码运行次序），当遇到几个分管（子管），就分到这几个分管子在流动，这里就相当于碰到代码的if else处了。</font>
		</p>
		<p>
				<font size="2">　　而使用OO，则首先打破这个代码由上向下顺序等同于运行时的先后循序这个规律，代码结构不由执行循序决定，由什么决定呢？由OO设计；设计模式会取代这些if else，但是最后总是由一个Service等总类按照运行顺序组装这些OO模块，只有一处，这处可包含事务，一般就是Service，EJB中是Session bean。</font>
		</p>
		<p>
				<font size="2">　　一旦需求变化，我们更多的可能是Service中各个OO模块，甚至是只改动Service中的OO模块执行顺序就能符合需求。</font>
		</p>
		<p>
				<font size="2">　　这里我们也看到OO分离的思路，将以前过程语言的一个Main函数彻底分解，将运行顺序与代码其他逻辑分离开来，而不是象面向过程那样混乱在一起。所以有人感慨，OO也是要顺序的，这是肯定的，关键是运行顺序要单独分离出来。</font>
		</p>
		<p>
				<font size="2">　　是否有if else可以看出你有没有将运行顺序分离到家。</font>
		</p>
		<p>
				<strong>
						<font size="2">设计模式的切入口</font>
				</strong>
		</p>
		<p>
				<font size="2">　　经常有人反映，设计模式是不错，但是我很难用到，其实如果你使用if else来写代码时（除显示控制以外），就是在写业务逻辑，只不过使用简单的判断语句来作为现实情况的替代者。</font>
		</p>
		<p>
				<font size="2">　　 还是以大家熟悉的论坛帖子为例子，如ForumMessage是一个模型，但是实际中帖子分两种性质：主题贴（第一个根贴）和回帖（回以前帖子的帖子），这里有一个朴素的解决方案：<br />建立一个ForumMessage，然后在ForumMessage加入isTopic这样判断语句，注意，你这里一个简单属性的判断引入，可能导致你的程序其他地方到处存在if else 的判断。</font>
		</p>
		<p>
				<font size="2">　　如果我们改用另外一种分析实现思路，以对象化概念看待，实际中有主题贴和回帖，就是两种对象，但是这两种对象大部分是一致的，因此，我将ForumMessage设为表达主题贴；然后创建一个继承ForumMessage的子类ForumMessageReply作为回帖，这样，我在程序地方，如Service中，我已经确定这个Model是回帖了，我就直接下溯为ForumMessageReply即可，这个有点类似向Collection放入对象和取出时的强制类型转换。通过这个手段我消灭了以后程序中if else的判断语句出现可能。</font>
		</p>
		<p>
				<font size="2">　　从这里体现了，如果分析方向错误，也会导致误用模式。</font>
		</p>
		<p>
				<font size="2">　　讨论设计模式举例，不能没有业务上下文场景的案例，否则无法决定是否该用模式，下面举两个对比的例子：</font>
		</p>
		<p>
				<font size="2">　　第一.</font>
				<a href="http://www.jdon.com/jive/thread.jsp?forum=91&amp;thread=24681" target="_blank">
						<font size="2"> 这个帖子</font>
				</a>
				<font size="2">中举例的第一个代码案例是没有上下文的，文中只说明有一段代码：</font>
		</p>
		<table cellspacing="1" cellpadding="1" width="100%" bgcolor="#cccccc" border="0">
				<tbody>
						<tr>
								<td>
										<font size="2">main() { </font>
										<p>
												<font size="2">if（case A）{ </font>
										</p>
										<p>
												<font size="2">//do with strategy A </font>
										</p>
										<p>
												<font size="2">}else(case B){</font>
										</p>
										<p>
												<font size="2">//do with strategy B </font>
										</p>
										<p>
												<font size="2">}else(case C){ </font>
										</p>
										<p>
												<font size="2">//do with strategy C </font>
										</p>
										<p>
												<font size="2">}</font>
										</p>
										<p>
												<font size="2">} </font>
										</p>
								</td>
								<td>
										<font size="2"> </font>
								</td>
						</tr>
				</tbody>
		</table>
		<p>
				<font size="2">　　这段代码只是纯粹的代码，没有业务功能，所以，在这种情况下，我们就很难确定使用什么模式，就是一定用策略模式等，也逃不过还是使用if else的命运，设计模式不是魔法，不能将一段毫无意义的代码变得简单了，只能将其体现的业务功能更加容易可拓展了。</font>
		</p>
		<p>
				<font size="2">　　第二.在</font>
				<a href="http://www.jdon.com/jive/thread.jsp?forum=91&amp;thread=24333&amp;message=14484871#14484871" target="_blank">
						<font size="2">这个帖子</font>
				</a>
				<font size="2">中，作者举了一个PacketParser业务案例，这段代码是体现业务功能的，是一个数据包的分析，作者也比较了各种模式使用的不同，所以我们还是使用动态代理模式或Command模式来消灭那些可能存在的if else</font>
		</p>
		<p>
				<font size="2">　　由以上两个案例表明：业务逻辑是我们使用设计模式的切入点，而在分解业务逻辑时，我们习惯则可能使用if else来实现，当你有这种企图或者已经实现代码了，那么就应该考虑是否需要重构Refactoring了。<br /></font>
		</p>
		<p>
				<strong>
						<font size="2">if else替代者</font>
				</strong>
		</p>
		<p>
				<font size="2">　　那么实战中，哪些设计模式可以替代if else呢？其实GoF设计模式都可以用来替代if else，我们分别描述如下：</font>
		</p>
		<li>
				<font size="2">状态模式　<br />　　当数据对象存在各种可能性的状态，而且这种状态将会影响到不同业务结果时，那么我们就应该考虑是否使用状态模式，当然，使用状态模式之前，你必须首先有内存状态这个概念，而不是数据库概念，因为在传统的面向过程的/面向数据库的系统中，你很难发现状态的，从数据库中读取某个值，然后根据这个值进行代码运行分流，这是很多初学者常干的事情。参考文章:</font>
				<a href="http://www.jdon.com/artichect/state.htm" target="_blank">
						<font size="2">状态对象：数据库的替代者</font>
				</a>
				<br />
				<font size="2">　　使用传统语言思维的情况还有：使用一个类整数变量标识状态：<br /></font>
				<table cellspacing="1" cellpadding="1" width="100%" bgcolor="#cccccc" border="0">
						<tbody>
								<tr>
										<td>
												<p>
														<font size="2">
														</font> </p>
												<p>
														<font size="2">public class Order{</font>
												</p>
												<p>
														<font size="2">private int status;</font>
												</p>
												<p>
														<font size="2">//说明： </font>
												</p>
												<p>
														<font size="2">//status=1 表示订货但为查看 ；</font>
												</p>
												<p>
														<font size="2">//status=2 表示已经查看未处理；</font>
												</p>
												<p>
														<font size="2">//status=3 表示已经处理未付款</font>
												</p>
												<p>
														<font size="2">//status=4 表示已经付款未发货</font>
												</p>
												<p>
														<font size="2">//status=5 表示已经发货</font>
												</p>
												<p>
														<font size="2">} </font>
												</p>
										</td>
								</tr>
						</tbody>
				</table>
				<br />
				<font size="2">　　上述类设计，无疑是将类作为传统语言的函数来使用，这样导致程序代码中存在大量的if else。<br /><br /></font>
		</li>
		<li>
				<font size="2">策略模式　<br />　　当你面临几种算法或者公式选择时，可以考虑策略模式，传统过程语言情况是：从数据库中读取算法数值，数值1表示策略1，例如保存到数据库；数值为2表示策略2，例如保存到XMl文件中。这里使用if else作为策略选择的开关。 <br /><br /></font>
		</li>
		<li>
				<font size="2">command模式　<br />　　传统过程的思维情况是：如果客户端发出代号是1或"A"，那么我调用A.java这个对象来处理；如果代号是2或"B"，我就调用B.java来处理，通过if else来判断客户端发送过来的代码，然后按事先约定的对应表，调用相应的类来处理。<br /><br /></font>
		</li>
		<li>
				<font size="2">MVC模式　<br />　　MVC模式的传统语言误用和Command模式类似，在一个Action类中，使用if else进行前后台调度，如果客户端传送什么命令；我就调用后台什么结果；如果后台处理什么结构，再决定推什么页面，不过，现在我们使用Struts/JSF这样MVC模式的框架实现者就不必范这种低级错误。<br /><br /></font>
		</li>
		<li>
				<font size="2">职责链模式　<br />　　职责链模式和Command模式是可选的，如果你实在不知道客户端会发出什么代号；也没有一个事先定义好的对照表，那么你只能编写一个个类去碰运气一样打开这个包看一下就可以。与Command是不同在</font>
				<a href="http://www.jdon.com/AOPdesign/decorator.htm" target="_blank">
						<font size="2">AOP vs Decorator</font>
				</a>
				<font size="2">一文中有分析。<br /><br /></font>
		</li>
		<li>
				<font size="2">代理或动态代理模式　<br />　　代理对象可以是符合某种条件的代表者，比如，权限检验，传统面向过程思维是：当一个用户登陆后，访问某资源时，使用if else进行判断，只有某种条件符合时，才能允许访问，这样权限判断和业务数据逻辑混乱在一起，使用代理模式可以清晰分离，如果嫌不太好，使用动态代理，或者下面AOP等方式。<br /><br /></font>
		</li>
		<li>
				<font size="2">AOP或Decorator模式<br />　　<br />　　其实使用filter过滤器也可以替代我们业务中的if else，过滤器起到一种过滤和筛选作用，将符合本过滤器条件的对象拦截下来做某件事情，这就是一个过滤器的功能，多个过滤器组合在一起实际就是if else的组合。<br />　　所以，如果你实在想不出什么办法，可以使用过滤器，将过滤器看成防火墙就比较好理解，当客户端有一个请求时，经过不同性质的防火墙，这个防火墙是拦截端口的；那个防火墙是安全检查拦截等等。过滤器也如同红蓝白各种光滤镜；红色滤镜只能将通过光线中的红色拦截了；蓝色滤镜将光线中的蓝色拦截下来，这实际上是对光线使用if else进行分解。<br /><br /><img height="182" src="http://www.jdon.com/artichect/images/ifelse.gif" width="285" /><br />　　如图，通过一个个条件过滤器我们立体地实现了对信号的分离，如果你使用if else，说明你是将图中的条件1/2/3/4合并在一起，在同一个地方实现条件判断。<br />　　需要深入了解过滤器的实现细节和微小区别，请参考文章：</font>
				<a href="http://www.jdon.com/AOPdesign/decorator.htm" target="_blank">
						<font size="2">AOP vs Decorator</font>
				</a>
				<br />
				<p>
						<font size="2">
								<strong>OO设计的总结</strong>　　 </font>
				</p>
				<p>
						<font size="2">　　还有一种伪模式，虽然使用了状态等模式，但是在模式内部实质还是使用if else或switch进行状态切换或重要条件判断，那么无疑说明还需要进一步努力。更重要的是，不能以模式自居，而且出书示人。</font>
				</p>
				<p>
						<font size="2">　　真正掌握面向对象这些思想是一件困难的事情，目前有各种属于揪着自己头发向上拔的解说，都是误人子弟的，所以我觉得初学者读Thinking in Java（Java编程思想）是没有用，它试图从语言层次来讲OO编程思想，非常失败，作为语言参考书可以，但是作为Java体现的OO思想的学习资料，就错了。</font>
				</p>
				<p>
						<font size="2">　　OO编程思想是一种方法论，方法论如果没有应用比较，是无法体会这个方法论的特点的，禅是古代一个方法论，悟禅是靠挑水砍柴这些应用才能体会。</font>
				</p>
				<p>
						<font size="2">　　那么OO思想靠什么应用能够体会到了？是GoF设计模式，GoF设计模式是等于软件人员的挑水砍柴等基本活，所以，如果一个程序员连基本活都不会，他何以自居OO程序员？从事OO专业设计编程这个工作，如果不掌握设计模式基本功，就象一个做和尚的人不愿意挑水砍柴，他何以立足这个行业？早就被师傅赶下山。</font>
				</p>
				<p>
						<font size="2">　　最后总结：将if else用在小地方还可以，如简单的数值判断；但是如果按照你的传统习惯思维，在实现业务功能时也使用if else，那么说明你的思维可能需要重塑，你的编程经验越丰富，传统过程思维模式就容易根深蒂固，想靠自己改变很困难；建议接受</font>
						<a href="http://www.jdon.com/trainning/j2eearchitect.htm" target="_blank">
								<font size="2">专业头脑风暴培训</font>
						</a>
						<font size="2">。</font>
				</p>
				<p>
						<font size="2">　　用一句话总结：如果你做了不少系统，很久没有使用if else了，那么说明你可能真正进入OO设计的境地了。（这是本人自己发明的实战性的衡量考核标准）。</font>
				</p>
		</li>
<img src ="http://www.blogjava.net/antsoul/aggbug/104436.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/antsoul/" target="_blank">antsoul</a> 2007-03-17 13:29 <a href="http://www.blogjava.net/antsoul/archive/2007/03/17/104436.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>什么是OO思想?</title><link>http://www.blogjava.net/antsoul/archive/2007/03/17/104433.html</link><dc:creator>antsoul</dc:creator><author>antsoul</author><pubDate>Sat, 17 Mar 2007 05:17:00 GMT</pubDate><guid>http://www.blogjava.net/antsoul/archive/2007/03/17/104433.html</guid><wfw:comment>http://www.blogjava.net/antsoul/comments/104433.html</wfw:comment><comments>http://www.blogjava.net/antsoul/archive/2007/03/17/104433.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/antsoul/comments/commentRss/104433.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/antsoul/services/trackbacks/104433.html</trackback:ping><description><![CDATA[
		<font size="2">看见人家在谈OO思想，我很惶恐，也很迷惘，到底什么是地OO思想！怎么来培养自己的OO思想呢？<br /></font>
		<span class="tpc_content">
				<font size="2">OO思想简言之，我们谈的 想的 编的 做的 都是围绕一个个对象。怎么来培养自己的OO思想呢？</font>
				<br />
		</span>
<img src ="http://www.blogjava.net/antsoul/aggbug/104433.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/antsoul/" target="_blank">antsoul</a> 2007-03-17 13:17 <a href="http://www.blogjava.net/antsoul/archive/2007/03/17/104433.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一个有意思的面试题</title><link>http://www.blogjava.net/antsoul/archive/2007/03/17/104431.html</link><dc:creator>antsoul</dc:creator><author>antsoul</author><pubDate>Sat, 17 Mar 2007 05:06:00 GMT</pubDate><guid>http://www.blogjava.net/antsoul/archive/2007/03/17/104431.html</guid><wfw:comment>http://www.blogjava.net/antsoul/comments/104431.html</wfw:comment><comments>http://www.blogjava.net/antsoul/archive/2007/03/17/104431.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/antsoul/comments/commentRss/104431.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/antsoul/services/trackbacks/104431.html</trackback:ping><description><![CDATA[给定一个非负整数n,请用JAVA写一个程序打印其对应的二进制值。例如 n=25 其对应的二进制为: 11001<img src ="http://www.blogjava.net/antsoul/aggbug/104431.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/antsoul/" target="_blank">antsoul</a> 2007-03-17 13:06 <a href="http://www.blogjava.net/antsoul/archive/2007/03/17/104431.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一道面试题目</title><link>http://www.blogjava.net/antsoul/archive/2007/03/17/104419.html</link><dc:creator>antsoul</dc:creator><author>antsoul</author><pubDate>Sat, 17 Mar 2007 04:19:00 GMT</pubDate><guid>http://www.blogjava.net/antsoul/archive/2007/03/17/104419.html</guid><wfw:comment>http://www.blogjava.net/antsoul/comments/104419.html</wfw:comment><comments>http://www.blogjava.net/antsoul/archive/2007/03/17/104419.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/antsoul/comments/commentRss/104419.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/antsoul/services/trackbacks/104419.html</trackback:ping><description><![CDATA[
		<span class="tpc_content">一个整数，大于0，不用循环和本地变量，按照n，2n，4n，8n的顺序递增，当值大于5000时，把值按照指定顺序输出来。<br />例：n=1237<br />则输出为：<br />1237，<br />2474，<br />4948，<br />9896，<br />9896，<br />4948，<br />2474，<br />1237，<br /></span>
<img src ="http://www.blogjava.net/antsoul/aggbug/104419.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/antsoul/" target="_blank">antsoul</a> 2007-03-17 12:19 <a href="http://www.blogjava.net/antsoul/archive/2007/03/17/104419.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>致面向对象技术初学者的一封公开信【转】</title><link>http://www.blogjava.net/antsoul/archive/2007/03/17/104418.html</link><dc:creator>antsoul</dc:creator><author>antsoul</author><pubDate>Sat, 17 Mar 2007 04:01:00 GMT</pubDate><guid>http://www.blogjava.net/antsoul/archive/2007/03/17/104418.html</guid><wfw:comment>http://www.blogjava.net/antsoul/comments/104418.html</wfw:comment><comments>http://www.blogjava.net/antsoul/archive/2007/03/17/104418.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/antsoul/comments/commentRss/104418.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/antsoul/services/trackbacks/104418.html</trackback:ping><description><![CDATA[
		<font size="2">致面向对象技术初学者的一封公开信 <br />Alistair Cockburn 著（1996 年2 月），袁峰 译 <br /><br />介绍 <br /> 首先我要解释一下为什么会写这封公开信。这似乎已经成了一种习惯，但这个步骤还是需要的。过去6 年中， 我曾经无数次地在饭店、酒吧、旅店大厅等各种地方以同一种方式度过愉快而漫长的夜晚：和同样追求真理、光明和智慧的伙伴一起探讨面向对象的真谛。现在，我已经可以回答很多当年我遇到的问题。这些同样的问题也在困扰着我的一位新同事，在一家饭店里，我花了整整一个晚上和他讨论这些问题。结果第二天，他的同事又来问这些问题，并建议把我们的谈话内容记录下来，这样他可以拿去给他的同事看。考虑到还有很多和他的同事一样询问这些同样问题的人，我决定写下这篇文章。 <br />主要的问题是： <br />z 为什么只要稍有一点不是严格或纯面向对象的做法、说法，OO 专家就大惊小怪的？use case 并不是面向对象的，为什么还这么流行？而且，OO 建模似乎和数据建模非常相似？ <br />z 数据建模（data model）得到的模型和对象模型的结构部分会不会很像？流程建模（process model）和对象模型的行为部分呢？ <br />z 业务结构建模中为什么要用use case 和场景（scenario）? <br />OO 的新手们反复问这些问题，但实际上，只有在日常工作中坚持应用面向对象的思维进行工作，积累一定的经验，才能得到满意的答案。为什么只要稍有一点不是严格或纯面向对象的做法、说法，OO 专家就大惊小怪的？use case 并不是面向对象的，为什么还这么流行？而且，OO 建模似乎和数据建模非常相似？ <br />我想分三步来回答这个问题。 <br /><br />首先，我举我和Bob（著名的OO 专家）一起工作的例子， 当我们讨论OO 的时候，彼此都有一个共识，知道对方拥有面向对象工作的丰富经验并且是这项技术的坚定支持者。而且，对诸如对象识别（object identity）、多态、数据和行为的封装、实例职责、继承等对象技术都是手到擒来。因此，当我说：“明天对程序表单进行数据建模吧”，Bob 不会产生我要会因为关系表而放弃对象这样的误解，他知道我指的是在对象模型中体现出来的结构化特性进行建模。他知道我会说些什么，因此我使用或误用这些术语不会造成什么误解。但作为一个对象技术的初学者，如果Bob 发现你把数据和行为完全分离开了， 并且没有使用（ 或者说忽视了）对象识别或者多态等技术， 这时候， 如果你说“ 数据建模”，Bob 会像一堵墙一样逼近你，直到你明白该怎样改变。这样工作几个月，你会发现，你的模型（以及建模）中渐渐有了对象识别、多态、数据和行为的绑定，这时候再用“ 数据建模”这个词就不是那么危险了， 但Bob 还可能会担心你走回到老路上。换句话说， 他对你还不够信任， 因此，你不得不很小心地使用这些术语。 <br />就算一个对象模型可以分为“结构”和“行为”特性，我们也不会使用“对象建模”和“流程建模” 这种术语，以免引起混淆。事实上，为对象模型的“结构”特性建模可以看成是数据建模的特殊形式，只不过建模的对象不再是表，而是需要捕获的信息的结构。我们将它称为“ 概念数据模型”，而不是逻辑数据模型或物理数据模型。第二步，让我们考虑两个OO 使用者一起讨论的情况。如果其中一个家伙说到“流程建模”这样的词，肯定会让他的拍档琢磨半天：这家伙是说用标准数据流图作流程建模吗？如果这样的话，以后OO 实现的时候不是相当麻烦了吗？他是不是指模型的行为特性？是不是说在一个对象内部对流程进行建模？（如果这样的话，那会很有意思，因为很少有人这么做的。） 通过这个例子我们可以看到，这种谈话中使用“ 流程建模” 这种意图不明的词实在是太危险了，很容易就将交流变得非常困难。 <br />最后来说use case 和场景的问题，它们都是获取需求的主要手段，和实现技术无关。其好处是可以为设计时的讨论提供内容和范围。它们不是“面向对象”的，这是事实，它们类似于功能分解，这也是事实，而且这一点吓坏了很多人，但这些都无所谓。重要的是它们为设计提供了内容，在用来描述内部设计时，它们表现了系统的行为。Flow chart 、交互图、Petri 网、数据流图、use case 都可以用来描述系统的行为特性， 但各自用途不同，各有优劣。关键是要知道：对象不仅有数据，也有行为， 认识到这一点， 就可以大胆地去考虑怎样可以更好地捕捉、描述对象内部和对象之间的行为。 <br />数据建模（data model ）得到的模型和对象模型的结构部分会不会很像？流程建模（process model） 和对象模型的行为部分呢？根据我的经验，数据建模人员可以分为两种－一种是为存储的数据建模，而另一种是为系统或组织中的信息建模。这两者截然不同。前者讨论和思考所用的概念通常都很具体，比如说数据表。他们的模型和OO 建模者的模型大相径庭，而且他们并不愿意看到这些技术之间的相似性。在数据建模社区中，只有讨论逻辑数据模型或物理数据模型才不会受到攻击后者得到的是概念数据模型。根据我的经验，他们得到的模型和那些有经验的OO 建模者得到的模型非常相似。他们的工作更加类似于业务人员，而不是逻辑数据建模人员，这种说法可能会有助于理解概念数据模型和逻辑数据模型的区别。 <br />似乎有一套学问可以帮助人们比OO 建模人员更快地得到结果。我多次发现这样的事实：OO 建模人员花了三四次迭代才得到的模型，实际上和（概念）数据建模人员一个循环得到的模型是一样的。这个发现使我对数据建模人员充满了敬佩。事实上，在进行对象设计的时候，我有时就直接去把数据建模人员的产品拷贝过来看看， 从中来看我最后得到的模型大概会是什么样的。 <br />我曾经召开过数据建模人员和对象建模人员之间的会议。采取的方法是“ 一个听众的CRC 会议（CRC sessions for an audience）。四个经验丰富的OO 设计师坐在长桌一端，业务专家沿着长桌坐下，他们负责回答问题并纠正对业务的误解。接着是数据建模人员，长桌的另一头是其它有关人员。总的来说，屋里大概是十几个人，但谈话主要是在四个OO 设计师之间进行。 <br />讨论大概一个小时之后，OO 设计师可以得到对象设计的一部分。这时候，咨询数据建模人员，这个模型和他们已经得到的模型本质上是不是一样的。他们说，“是的”，重复这个过程两次以上，每次都询问数据建模人员同样的问题，除了使用的符号技术是不同的，例如：他们没有用继承，但在同样的地方有同样的占位符，在本质上，这个模型和他们的模型没有什么不同的。接着，我们分成几个小组，每个小组包括一个业务专家、一个数据建模专家和一个OO 专家，很快就剩下的设计达成一致，找出技术上一些小的不同之处，并且进行排序。一般情况都是这样的：要么数据建模人员考虑得更加合理，要么OO 建模人员考虑得更加合理，小组要做的是在他们的设计之间进行协调。 <br />从上面的这些经验可以看到，使用CRC 进行OO 建模得到的模型和概念数据建模得到的结果非常相似。另外，根据经验，基于逻辑（存储的信息）的关系建模和OO 建模是不同的。大多数情况下，区别是由于技术的不同导致的，例如，在OO 模型中可以自由地使用继承和多对多的关系。由于技术上的差异，两种建模人员之间不能很好地交流，这是最大的困难。 <br />数据建模部分的问题就说这么多吧。 <br /></font>
<img src ="http://www.blogjava.net/antsoul/aggbug/104418.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/antsoul/" target="_blank">antsoul</a> 2007-03-17 12:01 <a href="http://www.blogjava.net/antsoul/archive/2007/03/17/104418.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>空(标识)接口的重要性【转】 </title><link>http://www.blogjava.net/antsoul/archive/2007/03/15/104067.html</link><dc:creator>antsoul</dc:creator><author>antsoul</author><pubDate>Thu, 15 Mar 2007 10:06:00 GMT</pubDate><guid>http://www.blogjava.net/antsoul/archive/2007/03/15/104067.html</guid><wfw:comment>http://www.blogjava.net/antsoul/comments/104067.html</wfw:comment><comments>http://www.blogjava.net/antsoul/archive/2007/03/15/104067.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/antsoul/comments/commentRss/104067.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/antsoul/services/trackbacks/104067.html</trackback:ping><description><![CDATA[
		<font size="2">这是昨天我跟天意在一次闲聊中一次有起的讨论，标签接口真有那么重要吗？比如说很多初学者认为java.io.Serializable这样的接口，很多时候可用可不用，不用一样能执行对象系列化功能。<br /></font>
		<div class="postText">
				<p>
						<font size="2">　　为此，我们通过一个通俗而有趣的示例！这个示例是设计一个猎人，其持有一把智能猎枪，这就是说这把猎枪会自动识别人类，若发现瞄准的目标是人类，就不会开火，而其它的任何事物都通杀。<br />　　为此，我们使用了下面三个接口：<br />　　</font>
						<font size="2">
								<strong>一个用来表示万事万物的SomeThing<br /></strong>　　　　<br />　　public interface SomeThing {}　　</font>
				</p>
				<p>
						<font size="2">
								<strong>　　人类的接口：<br /></strong>　　public interface Humans extends SomeThing {}</font>
				</p>
				<p>
						<font size="2">　　</font>
						<font size="2">
								<strong>动物的接口：<br /></strong>public interface Animals extends SomeThing {}</font>
				</p>
				<p>
						<font size="2">
								<strong>然后是一系列的实现：</strong>
								<br />   <strong>中国人：</strong>      <br />public class Chinese implements Humans {}<br /><br />   <strong>日本人：</strong><br />public class Japanese {}</font>
				</p>
				<p>
						<font size="2">   </font>
						<font size="2">
								<strong>狗：<br /></strong>public class Dog implements Animals {}</font>
				</p>
				<p>
						<font size="2">
								<strong>妖怪(他很聪明,给自己帖上了人的标签)：<br /></strong>public class Monster implements Humans {}</font>
				</p>
				<p>
						<font size="2">下面这个程序的核心部分，</font>
						<font size="2">
								<strong>猎人类及客户端程序：<br /></strong>public class Hunter {<br />public void fire(Object target)<br />{<br /> if(target instanceof Humans)<br /> {<br />  System.out.println("这下完了，打中了一个人，该去坐牢了！");<br /> }<br /> else <br /> {<br />  System.out.println("恭喜你，打中了一只动物!");<br /> }<br />}<br />//智能的枪<br />public void intelligentFire(Object target)<br />{<br /> if(target instanceof Humans)<br /> {<br />  return;<br /> }<br /> System.out.println("开了一枪!"+target.getClass());<br /> //下面进行秒杀等相关处理<br /> //销毁他<br /> target=null;<br />}<br />public static void main(String[] args) {<br />Hunter hunter=new Hunter();<br />Object[] objects=new Object[]{new Dog(),new Japanese(),new Japanese(),new Chinese(),new Monster(),new SomeThing(){}};<br />for(int i=0;i&lt;objects.length;i++)<br /> hunter.intelligentFire(objects[i]);<br />}<br />}</font>
				</p>
				<p>
						<font size="2"> 运行程序，你会发现输出类似下面结果：</font>
				</p>
				<p>
						<font size="2">开了一枪!class springroad.demo.taginterface.Dog<br />开了一枪!class springroad.demo.taginterface.Japanese<br />开了一枪!class springroad.demo.taginterface.Japanese<br />开了一枪!class springroad.demo.taginterface.Hunter$1</font>
				</p>
				<p>
						<font size="2">　　由此可见，智能猎枪瞄准6个目标，开了4枪。只对Chinese、及Monster的实例没有开枪。因为这里讨论的是标签接口，虽然Humans没有任何方法，但从智能猎枪的角度来看，他就是通过这个标签来判断是否可以开火的。</font>
						<font size="2">
								<strong>他不用管也管不了目标的层次等级关系（比如Japanese肯定很非常鲜明等级结构)，即继承关系。他也管不了目标的来自于哪儿。比如，是用new操作符创建，还是从容器中取，或者是从网络某个地方加载一个。<br /></strong>　　</font>
						<strong>
								<font size="2">Hunter只是制订了一个简单的规则，你要想不让我的枪对你开火，你就必须在自己身上帖上一个Humans的标签。也就是说你必须遵守这个规则。<br />　　现在回过头来看，因为妖怪Monster真身应该是一条蛇或其它什么动物，但是他懂得Hunter制订的规则，于在巧妙的给自己帖上了一个Humans的标签，以致于欺骗了我们的智能猎枪。<br />　　而Japanese则自认为自己了不起，不按规则办事，我就不理你Hunter制订的规则，什么Humans标签，我就是不用。于是放到我们的程序中当然就只有挨杀的份了。</font>
						</strong>
				</p>
				<p>
						<font size="2">　　<strong>由此可见，空接口(标签接口)的重要性，在像本例中，给不给自己帖不标签，这是一个性命莜关的问题。其实在OO的世界中，空接口可以算是最高的层像。</strong><br /></font>
				</p>
		</div>
<img src ="http://www.blogjava.net/antsoul/aggbug/104067.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/antsoul/" target="_blank">antsoul</a> 2007-03-15 18:06 <a href="http://www.blogjava.net/antsoul/archive/2007/03/15/104067.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java SE 5.0新特性之一【静态导入】</title><link>http://www.blogjava.net/antsoul/archive/2007/03/12/103405.html</link><dc:creator>antsoul</dc:creator><author>antsoul</author><pubDate>Mon, 12 Mar 2007 14:18:00 GMT</pubDate><guid>http://www.blogjava.net/antsoul/archive/2007/03/12/103405.html</guid><wfw:comment>http://www.blogjava.net/antsoul/comments/103405.html</wfw:comment><comments>http://www.blogjava.net/antsoul/archive/2007/03/12/103405.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/antsoul/comments/commentRss/103405.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/antsoul/services/trackbacks/103405.html</trackback:ping><description><![CDATA[
		<font size="2">        最近JDK变化的速度真快，刚用上JDK1.4，马上就跳到Java SE5.0，这不刚用上5.0马上又出来6.0了，6.0暂时是用不上了，5.0较之前的版本有了新的变化，搞不好等到中国奥运的时候SUN为了表示祝贺也搞个JAVA SE8（呵呵，玩笑）,先把5.0的新变化了解了再说吧！<br />        5.0较之前的版本新增加了6个新的特性。包括范型，自动装箱，类型安全枚举等。今天想学习其中之一的静态导入吧！静态导入使得开发人员可以将一套静态方法和域放入作用域。它是关于调用的一种缩写，可以忽略有效的类名。比如说Math.abs(x)可以写成abs(x).为了静态的导入所有的静态域和方法，可以使用"import static java.lang.Math"。<br /><br /><br />比如说打印一句话,原始的写法:<br />System.out.println("this words is what i want to say!");<br />你导入静态包后可以这样写:<br />out.println("haha,i can do it like this!");<br /><br /></font>
<img src ="http://www.blogjava.net/antsoul/aggbug/103405.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/antsoul/" target="_blank">antsoul</a> 2007-03-12 22:18 <a href="http://www.blogjava.net/antsoul/archive/2007/03/12/103405.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Objects Clone</title><link>http://www.blogjava.net/antsoul/archive/2007/03/12/103331.html</link><dc:creator>antsoul</dc:creator><author>antsoul</author><pubDate>Mon, 12 Mar 2007 07:30:00 GMT</pubDate><guid>http://www.blogjava.net/antsoul/archive/2007/03/12/103331.html</guid><wfw:comment>http://www.blogjava.net/antsoul/comments/103331.html</wfw:comment><comments>http://www.blogjava.net/antsoul/archive/2007/03/12/103331.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/antsoul/comments/commentRss/103331.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/antsoul/services/trackbacks/103331.html</trackback:ping><description><![CDATA[
		<p>
				<font size="2">   有的时候我们为了获取对象的一份copy，可以利用Object类的clone方法来实现，要想实现克隆，我们必须在派生类中实现Cloneable interface并覆盖基类的clone()方法，并扩大访问权限为public,在派生类的clone()方法，调用super.clone()。<br /><br /> demo:<br />class StringTest<br />{<br /> public static void main(String[] args)<br /> {<br />  Professior p = new Professior("wangwu",50);<br />  Student s1 = new Student("zhangsan",18,p);<br />  Student s2 = (Student)s1.clone();<br />  s2.p.name = "lisi";<br />  s2.p.age = 20;<br />  <br />  System.out.println("s1.p.name="+s1.p.name+","+"s1.p.age="+s1.p.age);<br /> }<br />}</font>
		</p>
		<p>
				<font size="2">class Student implements Cloneable<br />{<br />  Professior p;<br />  String name;<br />  int age;<br /> <br /> public Student(String name,int age,Professior p)<br /> {<br />  this.name =name;<br />  this.age = age;<br />  this.p = p;<br /> }<br /> <br /> public Object clone()<br /> {<br />  Object o = null;<br />  try<br />  {<br />   o=super.clone();<br />  }<br />  catch(CloneNotSupportedException e)<br />  {<br />   System.out.println(e.toString());<br />  }<br />  return o;<br /> }<br /> <br /> public String toString()<br /> {<br />  return "name="+name+","+"age="+age;<br /> }<br />}</font>
		</p>
		<p>
				<font size="2">class Professior<br />{<br /> String name;<br /> int age;<br /> public Professior(String name,int age)<br /> {<br />  this.name = name;<br />  this.age = age;<br /> }<br />}<br /><br />Result:<br />D:\jcode&gt;java StringTest<br />s1.p.name=lisi,s1.p.age=20<br />通过结果看得出一个问题，当我们修改s2的Professior后，s1对象的Professior对象的值被修改了。不是有clone了2份copy吗？那怎么修改S1的值却影响了S2的值了，那是因为我们克隆的时候只是把Professior的引用复制了一份，而并没有实际在内存中给它分配到一块内存，所以我们clone的时候，其实是把同一个值给复制了2次，所以s1和s2操作的professior都是同一个对象，所以修改S1，必然就影响了S2的professior的值，那我们的本意并非如此，有没有办法解决呢？答案是肯定的。其实我们刚才所做的操作是一个浅克隆，当我们克隆的对象是引用类型的时候，可以用深克隆来实现。就如下面的Demo.<br />class CloneTest<br />{<br /> public static void main(String[] args)<br /> {<br />  Boss boss = new Boss("antsoul",25);<br />  Leader leader = new Leader("linda",30);<br />  Employee ep1 = new Employee("zhangsan",107,leader,boss);<br />    Employee ep2 = (Employee)ep1.clone();<br />    ep2.boss.name = "gll";<br />    ep2.boss.age = 60;<br />    System.out.println("ep1.leader.name="+ep1.boss.name);<br />    System.out.println("ep1.leader.age="+ep1.boss.age);<br /> } <br />}</font>
		</p>
		<p>
				<font size="2">class Employee implements Cloneable<br />{<br /> String name;<br /> int eid;<br /> Leader leader;<br /> Boss boss;<br /> <br /> Employee(String name,int eid,Leader leader,Boss boss)<br /> {<br />  this.name = name;<br />  this.eid = eid;<br />  this.leader = leader;<br />  this.boss = boss;<br /> }<br /> <br /> public Object clone()<br /> {<br />  Employee o = null;<br />  try<br />  {<br />   o = (Employee)super.clone();<br />  }<br />  catch(CloneNotSupportedException e)<br />  {<br />   System.out.println(e.toString());<br />  }<br />  o.leader = (Leader)leader.clone();<br />  o.boss = (Boss)boss.clone();<br />  return o;<br /> }<br />}</font>
		</p>
		<p>
				<font size="2">class Leader implements Cloneable<br />{<br /> String name;<br /> int age;<br /> <br /> Leader(String name,int age)<br /> {<br />  this.name = name;<br />  this.age = age;<br /> }<br /> <br /> public Object clone()<br /> {<br />  Object o = null;<br />  try<br />  {<br />   o = super.clone();<br />  }<br />  catch(CloneNotSupportedException e)<br />  {<br />   System.out.println(e.toString());<br />  }<br />  return o;<br /> }<br />}</font>
		</p>
		<p>
				<font size="2">class Boss implements Cloneable<br />{<br /> String name;<br /> int age;<br /> <br /> Boss(String name,int age)<br /> {<br />  this.name = name;<br />  this.age = age;<br /> }<br /> <br /> public Object clone()<br /> {<br />  Object o = null;<br />  try<br />  {<br />   o = super.clone();<br />  }<br />  catch(CloneNotSupportedException e)<br />  {<br />   System.out.println(e.getMessage());<br />  }<br />  return o;<br /> }<br />}<br /><br />这里有个疑问了，为什么我们要在派生类中over writte Object的clone()方法时，一定要调用super.clone()呢?<br />原因是: 在运行时刻，Object中的clone()识别出你要clone的是哪一个对象，然后为此对象分配内存空间，并进行对象的复制，将原始对象的内容一一复制到新的对象空间中去。</font>
		</p>
<img src ="http://www.blogjava.net/antsoul/aggbug/103331.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/antsoul/" target="_blank">antsoul</a> 2007-03-12 15:30 <a href="http://www.blogjava.net/antsoul/archive/2007/03/12/103331.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>集合框架学习(三)</title><link>http://www.blogjava.net/antsoul/archive/2007/03/10/103015.html</link><dc:creator>antsoul</dc:creator><author>antsoul</author><pubDate>Sat, 10 Mar 2007 10:02:00 GMT</pubDate><guid>http://www.blogjava.net/antsoul/archive/2007/03/10/103015.html</guid><wfw:comment>http://www.blogjava.net/antsoul/comments/103015.html</wfw:comment><comments>http://www.blogjava.net/antsoul/archive/2007/03/10/103015.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/antsoul/comments/commentRss/103015.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/antsoul/services/trackbacks/103015.html</trackback:ping><description><![CDATA[
		<p>┳ TreeSet (实现了SortedSet接口的类)<br /><font size="2">1.  TreeSet是依靠TreeMap来实现的。<br />2.  TreeSet是一个有序集合,TreeSet中的元素按照升序排列，缺省是按照自然排序，一位着TreeSet要实现Comparable接口。<br />3.  可以在构造TreeSet对象时，传递实现了Comparable接口的比较器对象。<br />demo<br /><br />import java.util.*;</font></p>
		<p>
				<font size="2">class TreeSetTest<br />{<br /> public static void main(String[] args){<br />   TreeSet ts = new TreeSet();<br />   <br />   ts.add(new Student("one",1));<br />   ts.add(new Student("two",4));<br />   ts.add(new Student("three",3));<br />   <br />   Iterator it = ts.iterator();<br />   while(it.hasNext()){<br />    System.out.println(it.next());<br />  }<br /> }<br />}</font>
		</p>
		<p>
				<font size="2">class Student implements Comparable<br />{<br /> private String name;<br /> private int num;<br /> <br /> //为了调用方便声明为static<br /> static class StudentComparator implements Comparator<br /> {<br />   public int compare(Object o1,Object o2){<br />    Student s1 =(Student)o1;<br />    Student s2 =(Student)o2;<br />    int result;<br />    <br />    result = s1.num &gt; s2.num ? 1 :(s1.num==s2.num ? 0 : -1);<br />    if(result == 0){ //student的num相同，比较name,因为name为String类型，它实现了Comparable&lt;String&gt; <br />      result = s1.name.compareTo(s2.name);<br />    }<br />    return result;<br />   } <br /> }<br /> <br /> public Student(String name,int num){<br />  this.name = name;<br />  this.num = num;<br /> }<br /> <br /> public int compareTo(Object o){<br />  Student s =(Student)o;<br />  return num &gt; s.num ? 1 : (num == s.num ? 0 : -1);<br /> }<br /> <br /> public String toString(){<br />  return "num="+num+" "+"name="+name;<br /> }<br />}</font>
		</p>
<img src ="http://www.blogjava.net/antsoul/aggbug/103015.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/antsoul/" target="_blank">antsoul</a> 2007-03-10 18:02 <a href="http://www.blogjava.net/antsoul/archive/2007/03/10/103015.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>集合框架学习（二）</title><link>http://www.blogjava.net/antsoul/archive/2007/03/10/103011.html</link><dc:creator>antsoul</dc:creator><author>antsoul</author><pubDate>Sat, 10 Mar 2007 09:35:00 GMT</pubDate><guid>http://www.blogjava.net/antsoul/archive/2007/03/10/103011.html</guid><wfw:comment>http://www.blogjava.net/antsoul/comments/103011.html</wfw:comment><comments>http://www.blogjava.net/antsoul/archive/2007/03/10/103011.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/antsoul/comments/commentRss/103011.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/antsoul/services/trackbacks/103011.html</trackback:ping><description><![CDATA[
		<p>§ LinkedList<br /><font size="2">1)  LinkedList是采用双向循环链表来实现的。<br />2)  利用LinkedList实现Stack,queen,double-ended queen。<br /><br /></font><font size="3">§ 数据结构<br /></font><font size="2"> 一般将数据结构分为为两大类：线性数据结构，非线性数据结构。线性数据结构有线性表，栈，队列，串，数组和文件；非线性数据结构有树和图。<br />1) 线性表<br />a. 线性表的逻辑结构是n个数据元素的有序队列:<br />     (a1,a2,a3,a4......an)<br />n为线性表的长度(n&gt;&gt;0), n=0 的表称为空表。<br />b. 数据元素呈线性关系。必存在唯一的称为“第一个”的数据元素；必存在唯一的称为“最后一个”的数据元素；除第一个   元素外，每个元素都有且只有一个前驱元素；除最后一个元素外，其它的每个元素都有且只有一个后继元素。<br />c. 所有数据元素在同一个线性表中必须是相同的数据类型。<br />d. 线性表按其存储结构可分为顺序表和链表。用顺序存储结构存储的线性表称为<strong><em>顺序表</em></strong>；用链式结构存储的线性表称为<strong><em>链表</em></strong>。<br />e. 将线性表中的数据元素依次存放在某个存储区域中,所形成的表称为线性表。一维数组就是顺序方式存储的线性表。<br /><br />2) Stack<br />a.  Stack也是一种特殊的线性表,是一种后进先出(LIFO)的结构。<br />b.  Stack是限定在表尾进行插入和删除的线性表，表尾称为栈顶(top),表头称为栈底(bottom)。<br />c.  Stack的物理存储可以顺序存储结构，也可以用链式存储结构。(即：可以用数组或链表实现) <br />actualize Stack:<br />import java.util.*;<br />class MyStack<br />{<br /> private LinkedList ll = new LinkedList();<br /> //要实现LIFO<br /> public void push(Object o){<br />  ll.addFirst(o);<br /> }<br /> public Object pop(){<br />  //出栈<br />  return ll.removeFirst();<br /> }<br /> public Object peek(){<br />  //查看栈顶元素，但是不移走<br />  return ll.getFirst();<br /> }<br /> public boolean empty(){<br />  //判断是否为空<br />  return ll.isEmpty();<br /> }<br /> <br /> public static void main(String[] args){<br />  MyStack ms = new MyStack();<br />  ms.push("one");<br />  ms.push("two");<br />  ms.push("three");<br />  ms.push("four");<br />  <br />  System.out.println(ms.pop());<br />  System.out.println(ms.peek());<br />  System.out.println(ms.empty());<br /> }<br />}<br /><br />3) Queen<br />a.  queen是限定所有的插入只能在表的一端进行，而所有的删除在表的另一端进行的线性表。<br />b.  queen中允许插入的一端称为队尾(Rear)，允许删除的一端称为队头(Front)。<br />c.   queen的操作是按先进先出(FIFO)的原则进行的。<br />d.   queen的物理存储可以用顺序存储结构，也可以用链式存储结构。<br /><br />actualize Stack:<br />import java.util.*;</font></p>
		<p>
				<font size="2">class MyQueen<br />{<br />   private LinkedList aa = new LinkedList();<br />   public void put(Object o){<br />      //添加元素<br />      aa.addLast(o);<br />   }<br />   <br />   public Object get(){<br />      //获得元素<br />      return aa.removeFirst();<br />   }<br />   <br />   public boolean empty(){<br />     return aa.isEmpty();<br />   }<br />   <br />   public static void main(String[] args){<br />      MyQueen mq = new MyQueen();<br />      mq.put("one");<br />      mq.put("two");<br />      mq.put("three");<br />      <br />      System.out.println(mq.get());<br />      System.out.println(mq.empty());<br />   }<br />}<br /><br />¤ ArrayList 与 LinkedList<br />a. ArrayList底层采用数组完成，而LinkedList则是以一般的双向链表(double-linked list)完成，其内每个对象，除了数据本身外，还有两个引用，分别指向前一个元素和后一个元素。<br />b. 如果我们经常在List的开始处增加元素,或则在List中进行插入和删除操作，我们应该使用LinkedList，否则的话，使用ArrayList则更快。<br /><br /><br /><font size="3">§ HashSet<br /></font>1.   实现Set接口的hash table,依靠HashMap来实现。<br />2.   应该为存放到散列表中的各个对象定义hashCode()和equals()。<br />3.   散列表又称哈希表。散列表算法的基本思想:<br />以节点的关键字为自变量，通过一定的函数关系(散列函数)计算出对应的函数值，以这个值作为该节点存储在散列表中的地址。<br />4.   当散列表中元素存放太满，就必须再散列，将产生一个新的散列表,所有元素存放到新的散列表中,原先的散列表将被删除。Jaav语言中，通过负载因子(load factor)来决定何时对散列表再进行散列。例如：如果负载因子是0.75,当散列表中有75%被存满，将进行再散列。<br />5.   负载因子越高(离1.0越近)，内存的使用效率越高,元素的寻找时间越长。负载因子越低(越接近0.0),元素的寻找时间越短，内存浪费越多。<br />6.   HashSet的缺省因子是0.75。<br /><br />HashSet demo:<br />import java.util.*;</font>
		</p>
		<p>
				<font size="2">class HashSetTest<br />{<br /> public static void main(String[] args){<br />  HashSet hs = new HashSet();<br />   <br />  hs.add(new Student("zhangsan",1));<br />  hs.add(new Student("lisi",2));<br />  hs.add(new Student("wangwu",3));<br />  hs.add(new Student("zhangsan",1));<br />  <br />  Iterator it = hs.iterator();<br />  while(it.hasNext()){<br />   System.out.println(it.next());<br />  }<br /> }<br />}</font>
		</p>
		<p>
				<font size="2">class Student<br />{<br />  String name;<br />  int num;<br /> <br /> public Student(String name,int num){<br />  this.name = name;<br />  this.num = num;<br /> }<br /> <br /> public int hashCode(){<br />  return num * name.hashCode();<br /> }<br /> <br /> public boolean equals(Object o){<br />  Student s =(Student)o;<br />  return num==s.num &amp;&amp; name.equals(s.name);<br /> }<br /> <br /> public String toString(){<br />  return num+":"+name;<br /> }<br />}</font>
		</p>
<img src ="http://www.blogjava.net/antsoul/aggbug/103011.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/antsoul/" target="_blank">antsoul</a> 2007-03-10 17:35 <a href="http://www.blogjava.net/antsoul/archive/2007/03/10/103011.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>集合框架的学习(一)</title><link>http://www.blogjava.net/antsoul/archive/2007/03/10/102982.html</link><dc:creator>antsoul</dc:creator><author>antsoul</author><pubDate>Sat, 10 Mar 2007 05:03:00 GMT</pubDate><guid>http://www.blogjava.net/antsoul/archive/2007/03/10/102982.html</guid><wfw:comment>http://www.blogjava.net/antsoul/comments/102982.html</wfw:comment><comments>http://www.blogjava.net/antsoul/archive/2007/03/10/102982.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/antsoul/comments/commentRss/102982.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/antsoul/services/trackbacks/102982.html</trackback:ping><description><![CDATA[
		<p>
				<font size="2">所谓框架就是一个类库的集合。集合框架就是一个用来表示和操作集合的同意架构，包含了实现集合的接口和类。Java中的集合框架结构图如下:<br /><br />        Collection (i)               Map(i)<br />            /     \                              |<br />          /         \                            |<br />       Set(i)   List(i)               SortedMap(i)<br />        /<br />    SortedSet(i)<br />区别:<br />Collection: 集合层次中的根接口。<br />Set: 不能包含重复的element。SortedSet按照升序排列elements的Set。<br />List: 有序(不是排序，而是指elements按照一定的顺序排列)，可以包含重复element，提供了索引访问的方式。<br /><br />△ArrayList<br />1)  ArrayList 我们可以看作是一个可以自动增长的数组，这是和数组的不同之处。<br />2)  利用ArrayList的toArray()方法返回一个对象数组。<br />3)  Arrays的asList()返回一个列表。 注: 返回固定尺寸的列表。asList()返回的列表不支持remove()方法。<br />4)  迭代器(Iterator)提供了一组访问集合的通用方法。 hasNext(),  next(),   remove(),调用remove()方法之前必须至少调用一次next().<br />5)  类Collections与Arrays，前者对列表排序，后者对数组排序。<br /> * 当我们在打印一个集合类的对象的时候，它会调用集合类中的toString()方法，所以我们自定义的类就必须重写toString()方法.<br /> * List<string> stooges = Arrays.asList("Larry", "Moe", "Curly");<br /> * public static void printElements(Collecion c){<br />        Iterator it = c.iterator();<br />         while(it.hasNext()){<br />             System.out.println(it.next());<br />         }<br />    }<br /><br /> <br />   △ Collections<br />   1) 排序Collections.sort()<br />        a. 自然排序(natural ordering);<br />        b. 实现比较器(Comparator)接口.<br />   2)  取最大最element: Collections.max();  Collections.min();<br />   3)  在已经排序的List中搜索指定的element:  Collections.binarySerach()。<br /><br /><br />   △  一般方法实现<br />   import java.util.*;</string></font>
		</p>
		<p>
				<font size="2">class ArrayListTest<br />{<br /> public static void printElements(Collection c){<br />  Iterator it = c.iterator();<br />  while(it.hasNext()){<br />   System.out.println(it.next());<br />  }<br /> }<br /> <br /> public static void main(String[] args){<br />   Student s1 = new Student("antsoul",25);<br />   Student s2 = new Student("feiyang",35);<br />   Student s3 = new Student("gll",24);<br />   Student s4 = new Student("andylau",40);<br />   <br />   ArrayList al = new ArrayList();<br />   al.add(s1);<br />   al.add(s2);<br />   al.add(s3);<br />   al.add(s4);<br />   <br />   Collections.sort(al);<br />   printElements(al);<br /> }<br />}</font>
		</p>
		<p>
				<font size="2">class Point<br />{<br /> int x,y;<br /> public Point(int x,int y){<br />  this.x = x;<br />  this.y = y;<br /> }<br /> <br /> public String toString(){<br />  return ("x="+x+","+"y="+y);<br /> }<br />}</font>
		</p>
		<p>
				<font size="2">class Student implements Comparable<br />{<br /> private String name;<br /> private int num;<br /> <br /> public Student(String name,int num){<br />  this.name = name;<br />  this.num = num;<br /> }<br /> <br /> public int compareTo(Object o){<br />  Student s =(Student)o;<br />  return num &gt; s.num ? 1 : (num == s.num ? 0 : -1);<br /> }<br /> <br /> public String toString(){<br />  return "num:"+num+" "+"name:"+name;<br /> }<br />}    <br /><br />   △ 比较器总是和特定的类相关的，具体到某一个类。比如说对student排序，你要用到学号，所以排序前必须要转换Object为Student,也就是为某一个类指定一个比较器，可以写一个类去实现比较器的接口，但是为了联系紧密，可以在这里用内部类在实现比机器接口。<br />import java.util.*;</font>
		</p>
		<p>
				<font size="2">class ArrayListTest<br />{<br /> public static void printElements(Collection c){<br />  Iterator it = c.iterator();<br />  while(it.hasNext()){<br />   System.out.println(it.next());<br />  }<br /> }<br /> <br /> public static void main(String[] args){<br />   Student s1 = new Student("antsoul",2);<br />   Student s2 = new Student("feiyang",1);<br />   Student s3 = new Student("gll",3);<br />   Student s4 = new Student("andylau",4);<br />   <br />   ArrayList al = new ArrayList();<br />   al.add(s1);<br />   al.add(s2);<br />   al.add(s3);<br />   al.add(s4);<br />   <br />   Collections.sort(al,new Student.StudentComparator()); //student提供自己的比较器<br />   printElements(al);<br /> }<br />}</font>
		</p>
		<p>
				<font size="2">class Point<br />{<br /> int x,y;<br /> public Point(int x,int y){<br />  this.x = x;<br />  this.y = y;<br /> }<br /> <br /> public String toString(){<br />  return ("x="+x+","+"y="+y);<br /> }<br />}</font>
		</p>
		<p>
				<font size="2">class Student implements Comparable<br />{<br /> private String name;<br /> private int num;<br /> <br /> //为了调用方便声明为static<br /> static class StudentComparator implements Comparator<br /> {<br />   public int compare(Object o1,Object o2){<br />    Student s1 =(Student)o1;<br />    Student s2 =(Student)o2;<br />    <br />    return s1.num &gt; s2.num ? 1 :(s1.num==s2.num ? 0 : -1);<br />   } <br /> }<br /> <br /> public Student(String name,int num){<br />  this.name = name;<br />  this.num = num;<br /> }<br /> <br /> public int compareTo(Object o){<br />  Student s =(Student)o;<br />  return num &gt; s.num ? 1 : (num == s.num ? 0 : -1);<br /> }<br /> <br /> public String toString(){<br />  return "num:"+num+" "+"name:"+name;<br /> }<br />}<br /><br />如果student的num相等的情况下，要以name来排序可以这样实现:<br />import java.util.*;</font>
		</p>
		<p>
				<font size="2">class ArrayListTest<br />{<br /> public static void printElements(Collection c){<br />  Iterator it = c.iterator();<br />  while(it.hasNext()){<br />   System.out.println(it.next());<br />  }<br /> }<br /> <br /> public static void main(String[] args){<br />   Student s1 = new Student("antsoul",2);<br />   Student s2 = new Student("feiyang",1);<br />   Student s3 = new Student("dorydoo",3);<br />   Student s4 = new Student("sun",4);<br />   Student s5 = new Student("gll",4);<br />   <br />   ArrayList al = new ArrayList();<br />   al.add(s1);<br />   al.add(s2);<br />   al.add(s3);<br />   al.add(s4);<br />   al.add(s5);<br />   <br />   Collections.sort(al,new Student.StudentComparator()); //student提供自己的比较器<br />   printElements(al);<br /> }<br />}</font>
		</p>
		<p>
				<font size="2">class Point<br />{<br /> int x,y;<br /> public Point(int x,int y){<br />  this.x = x;<br />  this.y = y;<br /> }<br /> <br /> public String toString(){<br />  return ("x="+x+","+"y="+y);<br /> }<br />}</font>
		</p>
		<p>
				<font size="2">class Student implements Comparable<br />{<br /> private String name;<br /> private int num;<br /> <br /> //为了调用方便声明为static<br /> static class StudentComparator implements Comparator<br /> {<br />   public int compare(Object o1,Object o2){<br />    Student s1 =(Student)o1;<br />    Student s2 =(Student)o2;<br />    int result;<br />    <br />    result = s1.num &gt; s2.num ? 1 :(s1.num==s2.num ? 0 : -1);<br />    if(result == 0){ //student的num相同，比较name,因为name为String类型，它实现了Comparable&lt;String&gt; <br />      result = s1.name.compareTo(s2.name);<br />    }<br />    return result;<br />   } <br /> }<br /> <br /> public Student(String name,int num){<br />  this.name = name;<br />  this.num = num;<br /> }<br /> <br /> public int compareTo(Object o){<br />  Student s =(Student)o;<br />  return num &gt; s.num ? 1 : (num == s.num ? 0 : -1);<br /> }<br /> <br /> public String toString(){<br />  return "num="+num+" "+"name="+name;<br /> }<br />}<br /><br /><br /><br /><br /></font>
		</p>
<img src ="http://www.blogjava.net/antsoul/aggbug/102982.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/antsoul/" target="_blank">antsoul</a> 2007-03-10 13:03 <a href="http://www.blogjava.net/antsoul/archive/2007/03/10/102982.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>有意思的题目</title><link>http://www.blogjava.net/antsoul/archive/2007/03/10/102973.html</link><dc:creator>antsoul</dc:creator><author>antsoul</author><pubDate>Sat, 10 Mar 2007 03:46:00 GMT</pubDate><guid>http://www.blogjava.net/antsoul/archive/2007/03/10/102973.html</guid><wfw:comment>http://www.blogjava.net/antsoul/comments/102973.html</wfw:comment><comments>http://www.blogjava.net/antsoul/archive/2007/03/10/102973.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/antsoul/comments/commentRss/102973.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/antsoul/services/trackbacks/102973.html</trackback:ping><description><![CDATA[Q1: 请用JAVA或者C编写一个程序，从N个整数中找出最大的一个。<br />Q2: 请用JAVA或者C编写一个程序，找出2个整数的最大公约数。<br />Q3: 有一个100层高的大厦，你手中有2个相同的玻璃珠子。从这个大厦的某一层扔下去就会碎，用你手中的2颗珠子，找出一个最优的答案，来得知那个临界层面。<img src ="http://www.blogjava.net/antsoul/aggbug/102973.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/antsoul/" target="_blank">antsoul</a> 2007-03-10 11:46 <a href="http://www.blogjava.net/antsoul/archive/2007/03/10/102973.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>不用第三个变量来互换变量值</title><link>http://www.blogjava.net/antsoul/archive/2007/03/07/102438.html</link><dc:creator>antsoul</dc:creator><author>antsoul</author><pubDate>Wed, 07 Mar 2007 09:05:00 GMT</pubDate><guid>http://www.blogjava.net/antsoul/archive/2007/03/07/102438.html</guid><wfw:comment>http://www.blogjava.net/antsoul/comments/102438.html</wfw:comment><comments>http://www.blogjava.net/antsoul/archive/2007/03/07/102438.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/antsoul/comments/commentRss/102438.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/antsoul/services/trackbacks/102438.html</trackback:ping><description><![CDATA[
		<p>  不用第三个变量从而达到交换变量x,y的值，无意在网上看到了这个问题，感觉很有意思，研究了一下，觉得用以下的办法来做最简单！:-)<br /><br />   假如 x = 2, y=3;<br /><br />   x = x + y;<br /><br />   y = x - y;<br /><br />   x = x - y;<br /><br />这样就把x,y的值给换了，呵呵！<br />【code】：<br />class Exchange{<br />  void doExchange(int x,int y){<br />     x = x + y;<br />     y = x - y;<br />     x = x - y;  <br />     System.out.println("x="+x);<br />     System.out.println("y="+y);<br />  }<br />  public static void main(String[] args){<br />    Exchange ex = new Exchange();<br />    ex.doExchange(2,3);<br />  }<br />}<br />Result：<br /><br />D:\jcode&gt;javac Exchange.java</p>
		<p>D:\jcode&gt;java Exchange<br />x=3<br />y=2</p>
<img src ="http://www.blogjava.net/antsoul/aggbug/102438.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/antsoul/" target="_blank">antsoul</a> 2007-03-07 17:05 <a href="http://www.blogjava.net/antsoul/archive/2007/03/07/102438.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>