<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
  <channel>
    <title>笨鸟先飞</title>
    <description></description>
    <link>http://yzc.javaeye.com</link>
    <language>UTF-8</language>
    <copyright>Copyright 2003-2008, JavaEye.com</copyright>
    <docs>http://blogs.law.harvard.edu/tech/rss</docs>
    <generator>JavaEye - 做最棒的软件开发交流社区</generator>
      <item>
        <title>jsp 静态include和动态include</title>
        <author>yangzhichao</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://yzc.javaeye.com">yangzhichao</a>&nbsp;
          链接：<a href="http://yzc.javaeye.com/blog/177566" style="color:red;">http://yzc.javaeye.com/blog/177566</a>&nbsp;
          发表时间: 2008年03月29日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          动态INCLUDE<br />    用jsp:include动作实现 &lt;jsp:include page="included.jsp" flush="true" />它总是会检查所含文件中的变化，适合用于包含动态页面，并且可以带参数。<br /><br />静态INCLUDE<br />   用include伪码实现,不会检查所含文件的变化，适用于包含静态页面&lt;%@ include file="included.htm" %> <br /><br />===================================================================<br /><br />1. 静态include的结果是把其他jsp引入当前jsp,两者合为一体<br />    动态include的结构是两者独立,直到输出时才合并( 看看jsp生成的java文件就可以知道了)<br /><br />2.正是因为这样,动态include的jsp文件独立性很强,是一个单独的jsp文件,需要使用的对象,页面设置,都必须有自己创建,当然,还好它和include它的页面的request范围是一致的.<br /><br />而静态include纯粹是把代码写在外面的一种共享方法,所有的变量都是可以和include它的主文件共享,两者高度紧密结合,不能有变量同名的冲突.而页面设置也可以借用主文件的.
          <br/>
          <span style="color:red;">
            <a href="http://yzc.javaeye.com/blog/177566#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sat, 29 Mar 2008 11:40:34 +0800</pubDate>
        <link>http://yzc.javaeye.com/blog/177566</link>
        <guid>http://yzc.javaeye.com/blog/177566</guid>
      </item>
      <item>
        <title>网页元素跟随BODY上下滚动JS组件</title>
        <author>yangzhichao</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://yzc.javaeye.com">yangzhichao</a>&nbsp;
          链接：<a href="http://yzc.javaeye.com/blog/177365" style="color:red;">http://yzc.javaeye.com/blog/177365</a>&nbsp;
          发表时间: 2008年03月28日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <pre name="code" class="js">
UpDownRoller.prototype.uid=100;
 function UpDownRoller(objID,selfName){
   var obj=document.getElementById(objID);
   obj.style.position="relative";
   obj.style.zIndex=this.uid++;
   this.target=obj;
   this.autoRoll=false;
   this.selfName=selfName;
   this.timerID=null;
 }
 UpDownRoller.prototype.setAutoRoll=function(b){
   if(this.autoRoll==b){
      return null;
   }
   this.autoRoll=b;
   if(b){
     if(this.timerID){
        window.clearInterval(this.timerID);
     }
     this.timerID=window.setInterval(this.selfName+".roll()",10);
   }else{
     this.target.style.pixelTop=0;
   }
 }
 UpDownRoller.prototype.roll=function(){
   if(!this.autoRoll){
       return false;
   }
   var t=this.target;
   t.style.pixelTop=document.body.scrollTop;
 }
 if(document.getElementById("floater")){
   var ft=new UpDownRoller("floater","ft");
   ft.setAutoRoll(true);
 }
</pre>
          <br/>
          <span style="color:red;">
            <a href="http://yzc.javaeye.com/blog/177365#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 28 Mar 2008 17:19:25 +0800</pubDate>
        <link>http://yzc.javaeye.com/blog/177365</link>
        <guid>http://yzc.javaeye.com/blog/177365</guid>
      </item>
      <item>
        <title>基于数据库的无限级树形结构后台（非递归遍历节点，通过增加维护节点PATH字段）</title>
        <author>yangzhichao</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://yzc.javaeye.com">yangzhichao</a>&nbsp;
          链接：<a href="http://yzc.javaeye.com/blog/177355" style="color:red;">http://yzc.javaeye.com/blog/177355</a>&nbsp;
          发表时间: 2008年03月28日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <pre name="code" class="java">
/**
 * 
 * @author yangzhichao
 *
 * @param &lt;PK>
 * @param &lt;T>
 */
public interface TreeNode&lt;PK extends Number, T extends TreeNode&lt;PK, T>> extends
		Serializable {
	public static final String DEFAULT_PATH_SEPARATOR = "-";

	/**
	 * 节点标识
	 * 
	 * @return
	 */
	PK getId();

	/**
	 * 节点名字
	 * 
	 * @return
	 */
	String getName();

	/**
	 * 获取直接父节点对象
	 * 
	 * @return 直接上级对象
	 */
	T getParent();

	/**
	 * 设置父节点
	 * 
	 * @param t
	 */
	void setParent(T t);

	/**
	 * 获取路径
	 * 
	 * @return
	 */
	String getPath();

	/**
	 * 
	 * @param path
	 * @return
	 */
	void setPath(String path);

	/**
	 * 是否为叶节点
	 * 
	 * @return 返回所有叶节点
	 */
	boolean isLeaf();

	/**
	 * 判断是否为指定节点的父节点
	 * 
	 * @param child
	 *            被判断的节点
	 * @return
	 */
	boolean isParentOf(T child);

	/**
	 * 判断是否为指定节点的子节点
	 * 
	 * @param parent
	 *            被判断的节点对象
	 * @return
	 */
	boolean isChildOf(T parent);

	/**
	 * 节点是否有效
	 * 
	 * @return
	 */
	boolean isValid();

	/**
	 * 获取子节点
	 * 
	 * @return
	 */
	Collection&lt;T> getChildren();

	/**
	 * 节点类别
	 * 
	 * @return
	 */
	@SuppressWarnings("unchecked")
	Class getClazz();

	/**
	 * 状态
	 * 
	 * @return
	 */
	int getStatus();
}
</pre><br /><br /><pre name="code" class="java">
/**
 * 树型抽象实现
 * 
 * @author yangzhichao
 * 
 */
public abstract class AbstractTreeNode&lt;PK extends Number, T extends AbstractTreeNode&lt;PK, T>>
		implements TreeNode&lt;PK, T> {
	/**
	 * 标识
	 */
	private PK id;
	/**
	 * 名字
	 */
	private String name;
	/**
	 * 上级节点
	 */
	private T parent;
	/**
	 * 路径
	 */
	private String path;
	/**
	 * 直接子节点集合
	 */
	private Collection&lt;T> children;
	/**
	 * 序号
	 */
	private int order;

	public boolean isChildOf(T parent) {
		return parent == null || this.getParent() == null ? false : this
				.getParent().equals(parent);
	}

	public boolean isParentOf(T child) {
		return child == null || child.getParent() == null ? false : this
				.equals(child.getParent());
	}

	/**
	 * 默认根据是否有子节点判断
	 */
	public boolean isLeaf() {
		return !(this.getChildren() != null && this.getChildren().size() > 0);
	}

	@SuppressWarnings("unchecked")
	public boolean equals(Object object) {
		if (!(object instanceof AbstractTreeNode)) {
			return false;
		}
		AbstractTreeNode o = (AbstractTreeNode) object;
		// 类型和ID要一致
		return new EqualsBuilder().append(this.getClazz().getName(),
				o.getClazz().getName()).append(this.getId(), o.getId())
				.isEquals();
	}

	public PK getId() {
		return id;
	}

	public void setId(PK id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getPath() {
		return path;
	}

	public void setPath(String path) {
		this.path = path;
	}

	public T getParent() {
		return parent;
	}

	public void setParent(T parent) {
		this.parent = parent;
	}

	public Collection&lt;T> getChildren() {
		return children;
	}

	public void setChildren(Collection&lt;T> children) {
		this.children = children;
	}

	public int getOrder() {
		return order;
	}

	public void setOrder(int order) {
		this.order = order;
	}
}
</pre><br /><br /><pre name="code" class="java">
/**
 * 树型DAO接口
 * 
 * @author yangzhichao
 * 
 * @param &lt;PK>
 * @param &lt;T>
 */
public interface TreeNodeDao&lt;PK extends Number, T extends TreeNode&lt;PK, T>>
		extends BaseDao&lt;PK, T> {
	/**
	 * 获取父亲节点
	 * 
	 * @param t
	 * @return
	 */
	T getParent(T t) throws DataAccessException;

	/**
	 * 获取直接子节点
	 * 
	 * @param t
	 * @return
	 * @throws DataAccessException
	 */
	Collection&lt;T> getDirectChildren(T t) throws DataAccessException;

	/**
	 * 获取直接子枝干
	 * 
	 * @param t
	 * @return
	 */
	Collection&lt;T> getDirectBranches(T t) throws DataAccessException;

	/**
	 * 获取直接叶子节点
	 * 
	 * @param t
	 * @return
	 */
	Collection&lt;T> getDirectLeaves(T t) throws DataAccessException;

	/**
	 * 获取所有孩子
	 * 
	 * @param t
	 * @return
	 * @throws DataAccessException
	 */
	Collection&lt;T> getAllChildren(T t) throws DataAccessException;

	/**
	 * 通过PATH获取所有子节点
	 * 
	 * @param t
	 * @return
	 * @throws DataAccessException
	 */
	Collection&lt;T> getAllChildrenByPath(T t) throws DataAccessException;

	/**
	 * 通过PATH获取所有子枝干
	 * 
	 * @param t
	 * @return
	 * @throws DataAccessException
	 */
	Collection&lt;T> getAllBranchesByPath(T t) throws DataAccessException;

	/**
	 * 通过PATH获取所有子叶子
	 * 
	 * @param t
	 * @return
	 * @throws DataAccessException
	 */
	Collection&lt;T> getAllLeavesByPath(T t) throws DataAccessException;

	/**
	 * 通过PATH获取所有父节点
	 * 
	 * @param t
	 * @return
	 */
	Collection&lt;T> getAllParentByPath(T t) throws DataAccessException;

	/**
	 * 通过PATH获取到ROOT节点为止(包含ROOT)的所有父亲节点
	 * 
	 * @param t
	 * @param root
	 * @return
	 */
	Collection&lt;T> getAllParentByPath(T t, T root) throws DataAccessException;

	/**
	 * 更新所有path属性包含oldPath子串的节点的path属性的oldPath子串为newPath
	 * 
	 * @param oldPath
	 * @param newPath
	 * @throws DataAccessException
	 */
	void updatePath(Class&lt;T> clazz, String oldPath, String newPath)
			throws DataAccessException;
}
</pre><br /><br /><pre name="code" class="java">
/**
 * 
 * @author yangzhichao
 * 
 * @param &lt;PK>
 * @param &lt;T>
 */
public abstract class HibernateTreeNodeDao&lt;PK extends Number, T extends TreeNode&lt;PK, T>>
		extends SpringHibernateDao&lt;PK, T> implements TreeNodeDao&lt;PK, T> {

	/**
	 * 根据ID字符串和类别获取对象
	 * 
	 * @param id
	 * @param c
	 * @return
	 */
	protected abstract T get(String id, Class&lt;T> c);

	@SuppressWarnings("unchecked")
	public Collection&lt;T> getAllParentByPath(T t) {
		ArrayList&lt;T> parents = new ArrayList&lt;T>();
		for (String parentID : t.getPath().trim().split("-")) {
			if (parentID != null && !parentID.trim().equals("")
					&& !parentID.trim().equals("-")) {
				parents.add(this.get(parentID, (Class&lt;T>) t.getClazz()));
			}
		}
		return parents;
	}

	@SuppressWarnings("unchecked")
	public Collection&lt;T> getAllParentByPath(T t, T root) {
		ArrayList&lt;T> parents = new ArrayList&lt;T>();
		for (String parentID : t.getPath().trim().split("-")) {
			if (parentID != null && !parentID.trim().equals("")
					&& !parentID.trim().equals("-")) {
				parents.add(this.get(parentID, (Class&lt;T>) t.getClazz()));
				if (root.getId().toString().equals(parentID.trim())) {
					break;
				}
			}
		}
		return parents;
	}

	public T getParent(T t) {
		return t.getParent();
	}

	/**
	 * 路径分隔符
	 */
	public String getPathSeparator() {
		return TreeNode.DEFAULT_PATH_SEPARATOR;
	}

	/**
	 * 设置节点t的路径
	 * 
	 * @param t
	 */
	private void setPath(T t) {
		// 设置路径
		if (t.getParent() == null) {
			t.setPath("-");
		} else {
			t.setPath(t.getParent().getPath() + t.getParent().getId()
					+ this.getPathSeparator());
		}
	}

	/**
	 * 插入
	 * 
	 * @throws
	 */
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED, rollbackFor = DataAccessException.class)
	public void insert(T t) throws DataAccessException {
		this.setPath(t);
		super.insert(t);
	}

	/**
	 * 更新
	 * 
	 * @throws
	 */
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED, rollbackFor = DataAccessException.class)
	public void update(T t) throws DataAccessException {
		boolean parentChanged = false;
		T old = this.get(t.getId(), t.getClazz());
		T oldParent = this.getParent(old);
		if (oldParent != null && !oldParent.equals(t.getParent())
				|| (oldParent == null && t.getParent() != null)) {
			// 上级节点改变
			parentChanged = true;
		}
		// 清除旧副本，不然保存时候会找到两个同一ID的对象会报错
		this.getHibernateTemplate().evict(old);
		if (parentChanged) {
			if (t.getParent() != null
					&& t.getParent().getPath() != null
					&& t.getParent().getPath().indexOf("-"+t.getId().toString()+"-") != -1) {
				throw new DataAccessException(this.getClass(),
						"不能选择子节点作为当前节点的父节点");
			}
			if (t.getParent() != null && t.getParent().equals(t)) {
				throw new DataAccessException(this.getClass(),
						"不能选择本身作为当前节点的父节点");
			}
			// 设置路径
			this.setPath(t);
			// 重新设置所有子节点路径
			this.updatePath(t.getClazz(), old.getPath(), t.getPath());
		}
		super.update(t);
	}

	/**
	 * 更新路径，当某节点上级节点改变时候调用
	 * 
	 * @throws DataAccessException
	 */
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED,rollbackFor = DataAccessException.class)
	public void updatePath(final Class&lt;T> clazz, String oldPath, String newPath)
			throws DataAccessException {
		if (oldPath == null || oldPath.trim().length() &lt; 1
				|| oldPath.trim().equals("-")) {
			return;
		}
		if (newPath == null || newPath.trim().length() &lt; 1) {
			newPath = "-";
		}
		if (oldPath.charAt(0) != '-') {
			oldPath = "-" + oldPath;
		}
		if (oldPath.charAt(oldPath.length() - 1) != '-') {
			oldPath = oldPath + "-";
		}
		if (newPath.charAt(0) != '-') {
			newPath = "-" + newPath;
		}
		if (newPath.charAt(newPath.length() - 1) != '-') {
			newPath = newPath + "-";
		}
		final String newPathTemp = newPath;
		final String oldPathTemp = oldPath;
		try {
			this.getHibernateTemplate().execute(new HibernateCallback() {
				public Object doInHibernate(Session session)
						throws HibernateException, SQLException {
					StringBuilder hql = new StringBuilder();
					hql.append(" update ");
					hql.append(clazz.getName());
					hql.append(" o ");
					hql.append(" set o.path=replace(o.path,:oldPath");
					hql.append(",:newPath");
					hql.append(")");
					hql.append(" where o.path like :oldPathLike ");
					Query query = session.createQuery(hql.toString());
					query.setString("oldPath", oldPathTemp.trim()).setString(
							"newPath", newPathTemp.trim()).setString(
							"oldPathLike", "%" + oldPathTemp.trim() + "%")
							.executeUpdate();
					return null;
				}
			});
		} catch (Exception e1) {
			throw new DataAccessException(this.getClass(), "更新路径失败", e1);
		}
	}

	public Collection&lt;T> getAllChildren(T t) throws DataAccessException {
		return this.getAllChildrenByPath(t);
	}

	public Collection&lt;T> getAllChildrenByPath(T t) throws DataAccessException {
		HibernateCriteriaQuery query = new HibernateCriteriaQuery();
		DetachedCriteria dc = DetachedCriteria.forClass(t.getClazz());
		dc.add(Restrictions.like("path", "%-" + t.getId().toString() + "-%"));
		query.setQuery(dc);
		return this.find(query);
	}

	public Collection&lt;T> getDirectChildren(T t) throws DataAccessException {
		HibernateCriteriaQuery query = new HibernateCriteriaQuery();
		DetachedCriteria dc = DetachedCriteria.forClass(t.getClazz());
		dc.add(Restrictions.eq("parent", t));
		query.setQuery(dc);
		return this.find(query);
	}
}
</pre>
          <br/>
          <span style="color:red;">
            <a href="http://yzc.javaeye.com/blog/177355#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 28 Mar 2008 17:00:00 +0800</pubDate>
        <link>http://yzc.javaeye.com/blog/177355</link>
        <guid>http://yzc.javaeye.com/blog/177355</guid>
      </item>
      <item>
        <title>获取网页元素的绝对位置</title>
        <author>yangzhichao</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://yzc.javaeye.com">yangzhichao</a>&nbsp;
          链接：<a href="http://yzc.javaeye.com/blog/177105" style="color:red;">http://yzc.javaeye.com/blog/177105</a>&nbsp;
          发表时间: 2008年03月28日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          function fGetXY(obj){<br />           var oTmp = obj;	  	  <br />           if(!oTmp||(typeOf(oTmp.offsetLeft) == "undefined")<br />               ||(typeOf(oTmp.offsetTop) == "undefined")<br />               ||!oTmp.tagName){<br />                return null;<br />           }<br />           var pt = new Point(0,0);   <br />           do{<br />	      pt.x += oTmp.offsetLeft;<br />	      pt.y += oTmp.offsetTop;<br />	      oTmp = oTmp.offsetParent;<br />	  } while(oTmp.tagName!="BODY");<br />	  return pt;<br />       }<br />       <br />       function Point(iX, iY){<br />          this.x = iX;<br />          this.y = iY;<br />       }
          <br/>
          <span style="color:red;">
            <a href="http://yzc.javaeye.com/blog/177105#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 28 Mar 2008 08:54:06 +0800</pubDate>
        <link>http://yzc.javaeye.com/blog/177105</link>
        <guid>http://yzc.javaeye.com/blog/177105</guid>
      </item>
      <item>
        <title>面向对象设计准则</title>
        <author>yangzhichao</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://yzc.javaeye.com">yangzhichao</a>&nbsp;
          链接：<a href="http://yzc.javaeye.com/blog/177100" style="color:red;">http://yzc.javaeye.com/blog/177100</a>&nbsp;
          发表时间: 2008年03月28日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          摘抄自《敏捷软件开发-原则、方法与实践》-Robert C. Martin <br /><br /><br />(1)SRP 单一职责原则 <br />就一个类而言，应该仅有一个引起它变化的原因。 <br />职责即为"变化的原因". <br />  <br />(2)OCP 开放封闭原则 <br />软件实体（类、模块、函数等）应该是可以扩展的，但是不可修改。 <br />对于扩展是开放的,对于更改是封闭的. <br />关键是抽象.将一个功能的通用部分和实现细节部分清晰的分离开来. <br />开发人员应该仅仅对程序中呈现出频繁变化的那些部分作出抽象.拒绝不成熟的抽象和抽象本身一样重要. <br />  <br />(3)LSP Liskov替换原则 <br />子类型必须能替换掉他们的基本类型 <br />  <br />(4)DIP 依赖倒置原则 <br />抽象不应该依赖于细节。细节应该依赖于抽象。 <br />Hollywood原则: "Don't call us, we'll call you".程序中所有的依赖关系都应该终止于抽象类和接口。针对接口而非实现编程。 <br />任何变量都不应该持有一个指向具体类的指针或引用。 <br />任何类都不应该从具体类派生。 <br />任何方法都不应该覆写他的任何基类中的已经实现了的方法。 <br />  <br />(5)ISP 接口隔离原则 <br />不应该强迫客户依赖于他们不用的方法。接口属于客户，不属于他所在的类层次结构。 <br />多个面向特定用户的接口胜于一个通用接口。 <br />  <br />(6)REP 重用发布等价原则 <br />重用的粒度就是发布的粒度. <br />  <br />(7)CCP 共同重用原则 <br />一个包中的所有类应该是共同重用的。如果重用了包中的一个类，那么就要重用包中的所有类。 <br />相互之间没有紧密联系的类不应该在同一个包中。 <br />  <br />(8)CRP 共同封闭原则 <br />包中的所有类对于同一类性质的变化应该是共同封闭的。一个变化若对一个包影响，则将对包中的所有类产生影响，而对其他的包不造成任何影响. <br />  <br />(9)ADP 无依赖原则 <br />在包的依赖关系中不允许存在环. <br />细节不应该被依赖. <br />  <br />(10)SDP 稳定依赖原则 <br />朝着稳定的方向进行依赖. <br />应该把封装系统高层设计的软件（比如抽象类）放进稳定的包中，不稳定的包中应该只包含那些很可能会改变的软件（比如具体类）。 <br />  <br />(11)SAP 稳定抽象原则 <br />包的抽象程度应该和其他稳定程度一致. <br />一个稳定的包应该也是抽象的，一个不稳定的包应该是抽象的. <br />  <br />(12)DAP(Default Abstraction Principle)缺省抽象原则 <br />在接口和实现接口的类之间引入一个抽象类,这个类实现了接口的大部分操作. <br />  <br />(13)IDP(Interface Design Principle)接口设计原则 <br />规划一个接口而不是实现一个接口。 <br />  <br />(14)BBP(Black Box Principle)黑盒原则 <br />多用类的聚合，少用类的继承。 <br />  <br />(15)DCSP(Don't Concrete Supperclass Principle)不要构造具体的超类原则 <br />避免维护具体的超类。
          <br/>
          <span style="color:red;">
            <a href="http://yzc.javaeye.com/blog/177100#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 28 Mar 2008 08:37:01 +0800</pubDate>
        <link>http://yzc.javaeye.com/blog/177100</link>
        <guid>http://yzc.javaeye.com/blog/177100</guid>
      </item>
      <item>
        <title>纯CSS的TIP实现</title>
        <author>yangzhichao</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://yzc.javaeye.com">yangzhichao</a>&nbsp;
          链接：<a href="http://yzc.javaeye.com/blog/176938" style="color:red;">http://yzc.javaeye.com/blog/176938</a>&nbsp;
          发表时间: 2008年03月27日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          &lt;html><br />&lt;head><br />&lt;style><br />.tipable {	<br />  position:absolute;<br />	color: #0000cc;<br />	text-decoration: none!important;<br />	font-size: 12px;<br />}<br />.tipable:hover {<br />	background: none;<br />}<br /><br />.tipable span {<br />	display: none;<br />}<br /><br />.tipable:hover span {<br />  display: block;<br />  position:absolute;<br />  border:1px solid #640000;<br />  background: #FFFFCC;	<br />  color:#000;<br />  padding:5px;<br />  left:20px;<br />  top:20px;<br />  white-space:nowrap;<br />}<br />&lt;/style><br />&lt;/head><br />&lt;body> <br />&lt;a href="javascript:void(null)" class="tipable">查看提示 <br />&lt;span>这是提示!&lt;/span> <br />&lt;/a> <br />&lt;/body><br />&lt;/html>
          <br/>
          <span style="color:red;">
            <a href="http://yzc.javaeye.com/blog/176938#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 27 Mar 2008 16:56:32 +0800</pubDate>
        <link>http://yzc.javaeye.com/blog/176938</link>
        <guid>http://yzc.javaeye.com/blog/176938</guid>
      </item>
  </channel>
</rss>