<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>清新网络世界</title>
	<atom:link href="http://blog.donews.com/QQwinterQQ/feed" rel="self" type="application/rss+xml" />
	<link>http://blog.donews.com/QQwinterQQ</link>
	<description>笑看it</description>
	<lastBuildDate>Tue, 04 Jul 2006 09:33:00 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>常用的JS代码（转载于CSDN)</title>
		<link>http://blog.donews.com/QQwinterQQ/archive/2006/07/04/946065.aspx</link>
		<comments>http://blog.donews.com/QQwinterQQ/archive/2006/07/04/946065.aspx#comments</comments>
		<pubDate>Tue, 04 Jul 2006 09:33:00 +0000</pubDate>
		<dc:creator>winer</dc:creator>
				<category><![CDATA[html]]></category>
		<category><![CDATA[java]]></category>

		<guid isPermaLink="false">http://blog.donews.com/QQwinterQQ/archive/2006/07/04/946065.aspx</guid>
		<description><![CDATA[HTML事件的控件触发 <br /><a target="_blank" href="http://dev.csdn.net/develop/article/20/20566.shtm">http://dev.csdn.net/develop/article/20/20566.shtm</a> <br />JavaScript通用库（二） <br /><a target="_blank" href="http://dev.csdn.net/article/28/28057.shtm">http://dev.csdn.net/article/28/28057.shtm</a> <br />破解网页禁止鼠标右键的技巧 <br /><a target="_blank" href="http://dev.csdn.net/develop/article/19/19419.shtm">http://dev.csdn.net/develop/article/19/19419.shtm</a> <br />如何利用JAVASCRIPT实现浮动广告 <br /><a target="_blank" h]]></description>
			<content:encoded><![CDATA[<p>HTML事件的控件触发 <br /><a target="_blank" href="http://dev.csdn.net/develop/article/20/20566.shtm">http://dev.csdn.net/develop/article/20/20566.shtm</a> <br />JavaScript通用库（二） <br /><a target="_blank" href="http://dev.csdn.net/article/28/28057.shtm">http://dev.csdn.net/article/28/28057.shtm</a> <br />破解网页禁止鼠标右键的技巧 <br /><a target="_blank" href="http://dev.csdn.net/develop/article/19/19419.shtm">http://dev.csdn.net/develop/article/19/19419.shtm</a> <br />如何利用JAVASCRIPT实现浮动广告 <br /><a target="_blank" href="http://community.csdn.net/expert/topic/3226/3226990.xml?temp=.5731165">http://community.csdn.net/expert/topic/3226/3226990.xml?temp=.5731165</a> <br />加入收藏夹大全 <br /><a target="_blank" href="http://www.588188.com/netbook/tech/other/html/other.ohchina.6.htm">http://www.588188.com/netbook/tech/other/html/other.ohchina.6.htm</a> <br />客户端脚本真藏 <br /><a target="_blank" href="http://www.pcdog.com/info/2974.htm">http://www.pcdog.com/info/2974.htm</a> <br />//打开模式对话框 <br />function doSelectUser(txtId) <br />{ </p>
<p>strFeatures=&quot;dialogWidth=500px;dialogHeight=360px;center=yes;middle=yes ;help=no;status=no;scroll=no&quot;; <br />var url,strReturn; </p>
<p>url=&quot;selUser.aspx&quot;; </p>
<p>strReturn=window.showModalDialog(url,&#8221;,strFeatures); </p>
<p>} </p>
<p>//返回模式对话框的值 <br />function okbtn_onclick() <br />{ <br />var commstr=&#8221;; </p>
<p>window.returnValue=commstr; </p>
<p>window.close() ; <br />} <br />全屏幕打开 IE 窗口 <br />var winWidth=screen.availWidth ; <br />var winHeight=screen.availHeight-20; <br />window.open(&quot;main.aspx&quot;,&quot;surveyWindow&quot;,&quot;toolbar=no,width=&quot;+ winWidth +&quot;,height=&quot;+ winHeight +&quot;,top=0,left=0,scrollbars=yes,resizable=yes,center:yes,statusbars=yes&quot;); <br />break <br />//脚本中中使用xml <br />function initialize() { <br />var xmlDoc <br />var xslDoc </p>
<p>xmlDoc = new ActiveXObject(&#8216;Microsoft.XMLDOM&#8217;) <br />xmlDoc.async = false; </p>
<p>xslDoc = new ActiveXObject(&#8216;Microsoft.XMLDOM&#8217;) <br />xslDoc.async = false; </p>
<p>xmlDoc.load(&quot;tree.xml&quot;) <br />xslDoc.load(&quot;tree.xsl&quot;) </p>
<p>folderTree.innerHTML = xmlDoc.documentElement.transformNode(xslDoc) <br />} </p>
<p>Top </p>
<p>回复人：happyjun2000(蓝色游侠∮是非成败转头空，以后不再up了) ( ) 信誉：89 2004-10-27 9:11:08 得分:0 </p>
<p>? <br />一、验证类 <br />1、数字验证内 <br />1.1 整数 <br />1.2 大于0的整数 （用于传来的ID的验证) <br />1.3 负整数的验证 <br />1.4 整数不能大于iMax <br />1.5 整数不能小于iMin <br />2、时间类 <br />2.1 短时间，形如 (13:04:06) <br />2.2 短日期，形如 (2003-12-05) <br />2.3 长时间，形如 (2003-12-05 13:04:06) <br />2.4 只有年和月。形如(2003-05,或者2003-5) <br />2.5 只有小时和分钟,形如(12:03) <br />3、表单类 <br />3.1 所有的表单的值都不能为空 <br />3.2 多行文本框的值不能为空。 <br />3.3 多行文本框的值不能超过sMaxStrleng <br />3.4 多行文本框的值不能少于sMixStrleng <br />3.5 判断单选框是否选择。 <br />3.6 判断复选框是否选择. <br />3.7 复选框的全选，多选，全不选，反选 <br />3.8 文件上传过程中判断文件类型 <br />4、字符类 <br />4.1 判断字符全部由a-Z或者是A-Z的字字母组成 <br />4.2 判断字符由字母和数字组成。 <br />4.3 判断字符由字母和数字，下划线,点号组成.且开头的只能是下划线和字母 <br />4.4 字符串替换函数.Replace(); <br />5、浏览器类 <br />5.1 判断浏览器的类型 <br />5.2 判断ie的版本 <br />5.3 判断客户端的分辨率 </p>
<p>6、结合类 <br />6.1 email的判断。 <br />6.2 手机号码的验证 <br />6.3 身份证的验证 </p>
<p>二、功能类 </p>
<p>1、时间与相关控件类 <br />1.1 日历 <br />1.2 时间控件 <br />1.3 万年历 <br />1.4 显示动态显示时钟效果（文本，如OA中时间） <br />1.5 显示动态显示时钟效果 (图像，像手表) <br />2、表单类 <br />2.1 自动生成表单 <br />2.2 动态添加，修改，删除下拉框中的元素 <br />2.3 可以输入内容的下拉框 <br />2.4 多行文本框中只能输入iMax文字。如果多输入了，自动减少到iMax个文字（多用于短信发送) </p>
<p>3、打印类 <br />3.1 打印控件 <br />4、事件类 <br />4.1 屏蔽右键 <br />4.2 屏蔽所有功能键 <br />4.3 &#8211;&gt; 和&lt;&#8211; F5 F11,F9,F1 <br />4.4 屏蔽组合键ctrl+N <br />5、网页设计类 <br />5.1 连续滚动的文字，图片（注意是连续的，两段文字和图片中没有空白出现） <br />5.2 html编辑控件类 <br />5.3 颜色选取框控件 <br />5.4 下拉菜单 <br />5.5 两层或多层次的下拉菜单 <br />5.6 仿IE菜单的按钮。（效果如rongshuxa.com的导航栏目) <br />5.7 状态栏，title栏的动态效果（例子很多，可以研究一下） <br />5.8 双击后，网页自动滚屏 <br />6、树型结构。 <br />6.1 asp+SQL版 <br />6.2 asp+xml+sql版 <br />6.3 java+sql或者java+sql+xml <br />7、无边框效果的制作 <br />8、连动下拉框技术 <br />9、文本排序 <br />10，画图类，含饼、柱、矢量贝滋曲线 <br />11，操纵客户端注册表类 <br />12，DIV层相关（拖拽、显示、隐藏、移动、增加） <br />13，TABLAE相关(客户端动态增加行列，模拟进度条，滚动列表等) <br />14，各种&lt;object classid=&gt;相关类，如播放器，flash与脚本互动等 <br />16, 刷新/模拟无刷新 异步调用类（XMLHttp或iframe,frame） </p>
<p>一、验证类 <br />1、数字验证内 <br />1.1 整数 <br />/^(-|\+)?\d+$/.test(str) <br />1.2 大于0的整数 （用于传来的ID的验证) <br />/^\d+$/.test(str) <br />1.3 负整数的验证 <br />/^-\d+$/.test(str) <br />2、时间类 <br />2.1 短时间，形如 (13:04:06) <br />function isTime(str) <br />{ <br />var a = str.match(/^(\d{1,2})(:)?(\d{1,2})\2(\d{1,2})$/); <br />if (a == null) {alert(&#8216;输入的参数不是时间格式&#8217;); return false;} <br />if (a[1]&gt;24 || a[3]&gt;60 || a[4]&gt;60) <br />{ <br />alert(&quot;时间格式不对&quot;); <br />return false <br />} <br />return true; <br />} <br />2.2 短日期，形如 (2003-12-05) <br />function strDateTime(str) <br />{ <br />var r = str.match(/^(\d{1,4})(-|\/)(\d{1,2})\2(\d{1,2})$/); <br />if(r==null)return false; <br />var d= new Date(r[1], r[3]-1, r[4]); <br />return (d.getFullYear()==r[1]&amp;&amp;(d.getMonth()+1)==r[3]&amp;&amp;d.getDate()==r[4]); <br />} <br />2.3 长时间，形如 (2003-12-05 13:04:06) <br />function strDateTime(str) <br />{ <br />var reg = /^(\d{1,4})(-|\/)(\d{1,2})\2(\d{1,2}) (\d{1,2}):(\d{1,2}):(\d{1,2})$/; <br />var r = str.match(reg); <br />if(r==null)return false; <br />var d= new Date(r[1], r[3]-1,r[4],r[5],r[6],r[7]); <br />return (d.getFullYear()==r[1]&amp;&amp;(d.getMonth()+1)==r[3]&amp;&amp;d.getDate()==r[4]&amp;&amp;d.getHours()==r[5]&amp;&amp;d.getMinutes()==r[6]&amp;&amp;d.getSeconds()==r[7]); <br />} <br />2.4 只有年和月。形如(2003-05,或者2003-5) <br />2.5 只有小时和分钟,形如(12:03) <br />3、表单类 <br />3.1 所有的表单的值都不能为空 <br />&lt;input onblur=&quot;if(this.value.replace(/^\s+|\s+$/g,&#8221;)==&#8221;)alert(&#8216;不能为空!&#8217;)&quot;&gt; <br />3.2 多行文本框的值不能为空。 <br />3.3 多行文本框的值不能超过sMaxStrleng <br />3.4 多行文本框的值不能少于sMixStrleng <br />3.5 判断单选框是否选择。 <br />3.6 判断复选框是否选择. <br />3.7 复选框的全选，多选，全不选，反选 <br />3.8 文件上传过程中判断文件类型 <br />4、字符类 <br />4.1 判断字符全部由a-Z或者是A-Z的字字母组成 <br />&lt;input onblur=&quot;if(/[^a-zA-Z]/g.test(this.value))alert(&#8216;有错&#8217;)&quot;&gt; <br />4.2 判断字符由字母和数字组成。 <br />&lt;input onblur=&quot;if(/[^0-9a-zA-Z]/g.test(this.value))alert(&#8216;有错&#8217;)&quot;&gt; <br />4.3 判断字符由字母和数字，下划线,点号组成.且开头的只能是下划线和字母 <br />/^([a-zA-z_]{1})([\w]*)$/g.test(str) <br />4.4 字符串替换函数.Replace(); <br />5、浏览器类 <br />5.1 判断浏览器的类型 <br />window.navigator.appName <br />5.2 判断ie的版本 <br />window.navigator.appVersion <br />5.3 判断客户端的分辨率 <br />window.screen.height; window.screen.width; </p>
<p>6、结合类 <br />6.1 email的判断。 <br />function ismail(mail) <br />{ <br />return(new RegExp(/^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/).test(mail)); <br />} <br />6.2 手机号码的验证 <br />6.3 身份证的验证 <br />function isIdCardNo(num) <br />{ <br />if (isNaN(num)) {alert(&quot;输入的不是数字！&quot;); return false;} <br />var len = num.length, re; <br />if (len == 15) <br />re = new RegExp(/^(\d{6})()?(\d{2})(\d{2})(\d{2})(\d{3})$/); <br />else if (len == 18) <br />re = new RegExp(/^(\d{6})()?(\d{4})(\d{2})(\d{2})(\d{3})(\d)$/); <br />else {alert(&quot;输入的数字位数不对！&quot;); return false;} <br />var a = num.match(re); <br />if (a != null) <br />{ <br />if (len==15) <br />{ <br />var D = new Date(&quot;19&quot;+a[3]+&quot;/&quot;+a[4]+&quot;/&quot;+a[5]); <br />var B = D.getYear()==a[3]&amp;&amp;(D.getMonth()+1)==a[4]&amp;&amp;D.getDate()==a[5]; <br />} <br />else <br />{ <br />var D = new Date(a[3]+&quot;/&quot;+a[4]+&quot;/&quot;+a[5]); <br />var B = D.getFullYear()==a[3]&amp;&amp;(D.getMonth()+1)==a[4]&amp;&amp;D.getDate()==a[5]; <br />} <br />if (!B) {alert(&quot;输入的身份证号 &quot;+ a[0] +&quot; 里出生日期不对！&quot;); return false;} <br />} <br />return true; <br />} </p>
<p>画图: <br />&lt;OBJECT <br />id=S <br />style=&quot;LEFT: 0px; WIDTH: 392px; TOP: 0px; HEIGHT: 240px&quot; <br />height=240 <br />width=392 <br />classid=&quot;clsid:369303C2-D7AC-11D0-89D5-00A0C90833E6&quot;&gt; <br />&lt;/OBJECT&gt; <br />&lt;SCRIPT&gt; <br />S.DrawingSurface.ArcDegrees(0,0,0,30,50,60); <br />S.DrawingSurface.ArcRadians(30,0,0,30,50,60); <br />S.DrawingSurface.Line(10,10,100,100); <br />&lt;/SCRIPT&gt; </p>
<p>Top </p>
<p>回复人：happyjun2000(蓝色游侠∮是非成败转头空，以后不再up了) ( ) 信誉：89 2004-10-27 9:11:15 得分:0 </p>
<p>? <br />写注册表： <br />&lt;SCRIPT&gt; <br />var WshShell = WScript.CreateObject(&quot;WScript.Shell&quot;); <br />WshShell.RegWrite (&quot;HKCU\\Software\\ACME\\FortuneTeller\\&quot;, 1, &quot;REG_BINARY&quot;); <br />WshShell.RegWrite (&quot;HKCU\\Software\\ACME\\FortuneTeller\\MindReader&quot;, &quot;Goocher!&quot;, &quot;REG_SZ&quot;); <br />var bKey = WshShell.RegRead (&quot;HKCU\\Software\\ACME\\FortuneTeller\\&quot;); <br />WScript.Echo (WshShell.RegRead (&quot;HKCU\\Software\\ACME\\FortuneTeller\\MindReader&quot;)); <br />WshShell.RegDelete (&quot;HKCU\\Software\\ACME\\FortuneTeller\\MindReader&quot;); <br />WshShell.RegDelete (&quot;HKCU\\Software\\ACME\\FortuneTeller\\&quot;); <br />WshShell.RegDelete (&quot;HKCU\\Software\\ACME\\&quot;); <br />&lt;/SCRIPT&gt; </p>
<p>TABLAE相关(客户端动态增加行列） <br />&lt;HTML&gt; <br />&lt;SCRIPT LANGUAGE=&quot;JScript&quot;&gt; <br />function numberCells() { <br />var count=0; <br />for (i=0; i &lt; document.all.mytable.rows.length; i++) { <br />for (j=0; j &lt; document.all.mytable.rows(i).cells.length; j++) { <br />document.all.mytable.rows(i).cells(j).innerText = count; <br />count++; <br />} <br />} <br />} <br />&lt;/SCRIPT&gt; <br />&lt;BODY onload=&quot;numberCells()&quot;&gt; <br />&lt;TABLE id=mytable border=1&gt; <br />&lt;TR&gt;&lt;TH&gt;&nbsp;&lt;/TH&gt;&lt;TH&gt;&nbsp;&lt;/TH&gt;&lt;TH&gt;&nbsp;&lt;/TH&gt;&lt;TH&gt;&nbsp;&lt;/TH&gt;&lt;/TR&gt; <br />&lt;TR&gt;&lt;TD&gt;&nbsp;&lt;/TD&gt;&lt;TD&gt;&nbsp;&lt;/TD&gt;&lt;TD&gt;&nbsp;&lt;/TD&gt;&lt;TD&gt;&nbsp;&lt;/TD&gt;&lt;/TR&gt; <br />&lt;TR&gt;&lt;TD&gt;&nbsp;&lt;/TD&gt;&lt;TD&gt;&nbsp;&lt;/TD&gt;&lt;TD&gt;&nbsp;&lt;/TD&gt;&lt;TD&gt;&nbsp;&lt;/TD&gt;&lt;/TR&gt; <br />&lt;/TABLE&gt; <br />&lt;/BODY&gt; <br />&lt;/HTML&gt; </p>
<p>１．身份证严格验证： </p>
<p>&lt;script&gt; <br />var aCity={11:&quot;北京&quot;,12:&quot;天津&quot;,13:&quot;河北&quot;,14:&quot;山西&quot;,15:&quot;内蒙古&quot;,21:&quot;辽宁&quot;,22:&quot;吉林&quot;,23:&quot;黑龙江 &quot;,31:&quot;上海&quot;,32:&quot;江苏&quot;,33:&quot;浙江&quot;,34:&quot;安徽&quot;,35:&quot;福建&quot;,36:&quot;江西&quot;,37:&quot;山东&quot;,41:&quot;河南&quot;,42:&quot;湖北 &quot;,43:&quot;湖南&quot;,44:&quot;广东&quot;,45:&quot;广西&quot;,46:&quot;海南&quot;,50:&quot;重庆&quot;,51:&quot;四川&quot;,52:&quot;贵州&quot;,53:&quot;云南&quot;,54:&quot;西藏 &quot;,61:&quot;陕西&quot;,62:&quot;甘肃&quot;,63:&quot;青海&quot;,64:&quot;宁夏&quot;,65:&quot;新疆&quot;,71:&quot;台湾&quot;,81:&quot;香港&quot;,82:&quot;澳门&quot;,91:&quot;国外 &quot;} </p>
<p>function cidInfo(sId){ <br />var iSum=0 <br />var info=&quot;&quot; <br />if(!/^\d{17}(\d|x)$/i.test(sId))return false; <br />sId=sId.replace(/x$/i,&quot;a&quot;); <br />if(aCity[parseInt(sId.substr(0,2))]==null)return &quot;Error:非法地区&quot;; <br />sBirthday=sId.substr(6,4)+&quot;-&quot;+Number(sId.substr(10,2))+&quot;-&quot;+Number(sId.substr(12,2)); <br />var d=new Date(sBirthday.replace(/-/g,&quot;/&quot;)) <br />if(sBirthday!=(d.getFullYear()+&quot;-&quot;+ (d.getMonth()+1) + &quot;-&quot; + d.getDate()))return &quot;Error:非法生日&quot;; <br />for(var i = 17;i&gt;=0;i &#8211;) iSum += (Math.pow(2,i) % 11) * parseInt(sId.charAt(17 &#8211; i),11) <br />if(iSum%11!=1)return &quot;Error:非法证号&quot;; <br />return aCity[parseInt(sId.substr(0,2))]+&quot;,&quot;+sBirthday+&quot;,&quot;+(sId.substr(16,1)%2?&quot;男&quot;:&quot;女&quot;) <br />} </p>
<p>document.write(cidInfo(&quot;380524198002300016&quot;),&quot;&lt;br/&gt;&quot;); <br />document.write(cidInfo(&quot;340524198002300019&quot;),&quot;&lt;br/&gt;&quot;) <br />document.write(cidInfo(&quot;340524197711111111&quot;),&quot;&lt;br/&gt;&quot;) <br />document.write(cidInfo(&quot;34052419800101001x&quot;),&quot;&lt;br/&gt;&quot;); <br />&lt;/script&gt; </p>
<p>２．验证ＩＰ地址 <br />&lt;SCRIPT LANGUAGE=&quot;JavaScript&quot;&gt; <br />function isip(s){ <br />var check=function(v){try{return (v&lt;=255 &amp;&amp; v&gt;=0)}catch(x){return false}}; <br />var re=s.split(&quot;.&quot;) <br />return (re.length==4)?(check(re[0]) &amp;&amp; check(re[1]) &amp;&amp; check(re[2]) &amp;&amp; check(re[3])):false <br />} </p>
<p>var s=&quot;202.197.78.129&quot;; <br />alert(isip(s)) <br />&lt;/SCRIPT&gt; </p>
<p>３．加sp1后还能用的无边框窗口！！ <br />&lt;HTML XMLNS:IE&gt; <br />&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=gb2312&quot;&gt; <br />&lt;IE:Download ID=&quot;include&quot; STYLE=&quot;behavior:url(#default#download)&quot; /&gt; <br />&lt;title&gt;Chromeless Window&lt;/title&gt; </p>
<p>&lt;SCRIPT LANGUAGE=&quot;JScript&quot;&gt; <br />/*&#8212; Special Thanks For andot &#8212;*/ </p>
<p>/* <br />This following code are designed and writen by Windy_sk &lt;seasonx@163.net&gt; <br />You can use it freely, but u must held all the copyright items! <br />*/ </p>
<p>/*&#8212; Thanks For andot Again &#8212;*/ </p>
<p>var CW_width= 400; <br />var CW_height= 300; <br />var CW_top= 100; <br />var CW_left= 100; <br />var CW_url= &quot;/&quot;; <br />var New_CW= window.createPopup(); <br />var CW_Body= New_CW.document.body; <br />var content= &quot;&quot;; <br />var CSStext= &quot;margin:1px;color:black; border:2px outset;border-style:expression(onmouseout=onmouseup=function(){this.style.borderStyle=&#8217;outset&#8217;}, onmousedown=function(){if(event.button!=2)this.style.borderStyle=&#8217;inset&#8217;});background-color:buttonface;width:16px;height:14px;font-size:12px;line-height:11px;cursor:Default;&quot;; </p>
<p>//Build Window <br />include.startDownload(CW_url, function(source){content=source}); </p>
<p>function insert_content(){ <br />var temp = &quot;&quot;; <br />CW_Body.style.overflow= &quot;hidden&quot;; <br />CW_Body.style.backgroundColor= &quot;white&quot;; <br />CW_Body.style.border= &quot;solid black 1px&quot;; <br />content = content.replace(/&lt;a ([^&gt;]*)&gt;/g,&quot;&lt;a onclick=&#8217;parent.open(this.href);return false&#8217; $1&gt;&quot;); <br />temp += &quot;&lt;table width=100% height=100% cellpadding=0 cellspacing=0 border=0&gt;&quot;; <br />temp += &quot;&lt;tr style=&#8217;;font-size:12px;background:#0099CC;height:20;cursor:default&#8217; ondblclick=\&quot;Max.innerText=Max.innerText==&#8217;1&#8242;?&#8217;2&#8242;:&#8217;1&#8242;;parent.if_max=!parent.if_max;parent.show_CW();\&quot; onmouseup=&#8217;parent.drag_up(event)&#8217; onmousemove=&#8217;parent.drag_move(event)&#8217; onmousedown=&#8217;parent.drag_down(event)&#8217; onselectstart=&#8217;return false&#8217; oncontextmenu=&#8217;return false&#8217;&gt;&quot;; <br />temp += &quot;&lt;td style=&#8217;color:#ffffff;padding-left:5px&#8217;&gt;Chromeless Window For IE6 SP1&lt;/td&gt;&quot;; <br />temp += &quot;&lt;td style=&#8217;color:#ffffff;padding-right:5px;&#8217; align=right&gt;&quot;; <br />temp += &quot;&lt;span id=Help onclick=\&quot;alert(&#8216;Chromeless Window For IE6 SP1 &#8211; Ver 1.0\\n\\nCode By Windy_sk\\n\\nSpecial Thanks For andot&#8217;)\&quot; style=\&quot;&quot;+CSStext+&quot;font-family:System;padding-right:2px;\&quot;&gt;?&lt;/span&gt;&quot;; <br />temp += &quot;&lt;span id=Min onclick=&#8217;parent.New_CW.hide();parent.blur()&#8217; style=\&quot;&quot;+CSStext+&quot;font-family:Webdings;\&quot; title=&#8217;Minimum&#8217;&gt;0&lt;/span&gt;&quot;; <br />temp += &quot;&lt;span id=Max onclick=\&quot;this.innerText=this.innerText==&#8217;1&#8242;?&#8217;2&#8242;:&#8217;1&#8242;;parent.if_max=!parent.if_max;parent.show_CW();\&quot; style=\&quot;&quot;+CSStext+&quot;font-family:Webdings;\&quot; title=&#8217;Maximum&#8217;&gt;1&lt;/span&gt;&quot;; <br />temp += &quot;&lt;span id=Close onclick=&#8217;parent.opener=null;parent.close()&#8217; style=\&quot;&quot;+CSStext+&quot;font-family:System;padding-right:2px;\&quot; title=&#8217;Close&#8217;&gt;x&lt;/span&gt;&quot;; <br />temp += &quot;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=2&gt;&quot;; <br />temp += &quot;&lt;div id=include style=&#8217;overflow:scroll;overflow-x:hidden;overflow-y:auto; HEIGHT: 100%; width:&quot;+CW_width+&quot;&#8217;&gt;&quot;; <br />temp += content; <br />temp += &quot;&lt;/div&gt;&quot;; <br />temp += &quot;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&quot;; <br />CW_Body.innerHTML = temp; <br />} </p>
<p>setTimeout(&quot;insert_content()&quot;,1000); </p>
<p>var if_max = true; <br />function show_CW(){ <br />window.moveTo(10000, 10000); <br />if(if_max){ <br />New_CW.show(CW_top, CW_left, CW_width, CW_height); <br />if(typeof(New_CW.document.all.include)!=&quot;undefined&quot;){ <br />New_CW.document.all.include.style.width = CW_width; <br />New_CW.document.all.Max.innerText = &quot;1&quot;; <br />} </p>
<p>}else{ <br />New_CW.show(0, 0, screen.width, screen.height); <br />New_CW.document.all.include.style.width = screen.width; <br />} <br />} </p>
<p>window.onfocus = show_CW; <br />window.onresize = show_CW; </p>
<p>// Move Window <br />var drag_x,drag_y,draging=false </p>
<p>function drag_move(e){ <br />if (draging){ <br />New_CW.show(e.screenX-drag_x, e.screenY-drag_y, CW_width, CW_height); <br />return false; <br />} <br />} </p>
<p>function drag_down(e){ <br />if(e.button==2)return; <br />if(New_CW.document.body.offsetWidth==screen.width &amp;&amp; New_CW.document.body.offsetHeight==screen.height)return; <br />drag_x=e.clientX; <br />drag_y=e.clientY; <br />draging=true; <br />e.srcElement.setCapture(); <br />} </p>
<p>function drag_up(e){ <br />draging=false; <br />e.srcElement.releaseCapture(); <br />if(New_CW.document.body.offsetWidth==screen.width &amp;&amp; New_CW.document.body.offsetHeight==screen.height) return; <br />CW_top = e.screenX-drag_x; <br />CW_left = e.screenY-drag_y; <br />} </p>
<p>&lt;/SCRIPT&gt; <br />&lt;/HTML&gt; </p>
<p>Top </p>
<p>回复人：tingpig(汀) ( ) 信誉：100 2004-10-27 9:32:46 得分:2 </p>
<p>? <br />贴两个关于treeview的 <br />&lt;script language=&quot;javascript&quot;&gt; <br />&lt;!&#8211; <br />//初始化选中节点 <br />function initchecknode() <br />{ <br />var node=TreeView1.getTreeNode(&quot;1&quot;); <br />node.setAttribute(&quot;Checked&quot;,&quot;true&quot;); <br />setcheck(node,&quot;true&quot;); <br />FindCheckedFromNode(TreeView1); <br />} <br />//oncheck事件 <br />function tree_oncheck(tree) <br />{ <br />var node=tree.getTreeNode(tree.clickedNodeIndex); <br />var Pchecked=tree.getTreeNode(tree.clickedNodeIndex).getAttribute(&quot;checked&quot;); <br />setcheck(node,Pchecked); <br />document.all.checked.value=&quot;&quot;; <br />document.all.unchecked.value=&quot;&quot;; <br />FindCheckedFromNode(TreeView1); <br />} <br />//设置子节点选中 <br />function setcheck(node,Pc) <br />{ <br />var i; <br />var ChildNode=new Array(); <br />ChildNode=node.getChildren(); </p>
<p>if(parseInt(ChildNode.length)==0) <br />return; <br />else <br />{ <br />for(i=0;i&lt;ChildNode.length;i++) <br />{ <br />var cNode; <br />cNode=ChildNode[i]; <br />if(parseInt(cNode.getChildren().length)!=0) <br />setcheck(cNode,Pc); <br />cNode.setAttribute(&quot;Checked&quot;,Pc); <br />} <br />} <br />} <br />//获取所有节点状态 <br />function FindCheckedFromNode(node) { <br />var i = 0; <br />var nodes = new Array(); <br />nodes = node.getChildren(); </p>
<p>for (i = 0; i &lt; nodes.length; i++) { <br />var cNode; <br />cNode=nodes[i]; <br />if (cNode.getAttribute(&quot;Checked&quot;)) <br />AddChecked(cNode); <br />else <br />AddUnChecked(cNode); </p>
<p>if (parseInt(cNode.getChildren().length) != 0 ) { <br />FindCheckedFromNode(cNode); <br />} <br />} <br />} <br />//添加选中节点 <br />function AddChecked(node) { <br />document.all.checked.value += node.getAttribute(&quot;NodeData&quot;); <br />document.all.checked.value += &#8216;,&#8217;; <br />} <br />//添加未选中节点 <br />function AddUnChecked(node) { <br />document.all.unchecked.value += node.getAttribute(&quot;NodeData&quot;); <br />document.all.unchecked.value += &#8216;,&#8217;; <br />} <br />//&#8211;&gt; <br />&lt;/script&gt; </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.donews.com/QQwinterQQ/archive/2006/07/04/946065.aspx/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>linux下使用“虚拟光驱”</title>
		<link>http://blog.donews.com/QQwinterQQ/archive/2006/07/04/946052.aspx</link>
		<comments>http://blog.donews.com/QQwinterQQ/archive/2006/07/04/946052.aspx#comments</comments>
		<pubDate>Tue, 04 Jul 2006 09:29:00 +0000</pubDate>
		<dc:creator>winer</dc:creator>
		
		<guid isPermaLink="false">http://blog.donews.com/QQwinterQQ/archive/2006/07/04/946052.aspx</guid>
		<description><![CDATA[<span class="tpc_content">  在＃提示符下执行命令<br />cp /dev/cdrom XXXXX.iso<br />XXXXX.iso即为需要命名的ISO文件名<br />执行之后，光盘上所有文件就被映射成XXXXX.iso<br /><br />至于如何加载嘛<br />请看下面<br />还是在＃提示符下执行命令<br />rm -rf /dev/cdrom<br />ln -s /dev/loop7 /dev/cdrom<br />losetup /dev/loop7 /PATH（iso文件路径）<br />mount /mnt/cdrom<br /><br />如果需要换盘<br />losetup -d /dev/loop7<br />再重复<br />losetup /dev/loop7 /PATH（iso文件路径）<br />mount /mnt/cdrom<br /><br />如果是普通含有iso的光盘<br />可以直接使用命令<br />mount -t iso9660 -o loop /../*.iso /path<br />/..]]></description>
			<content:encoded><![CDATA[<p><span class="tpc_content">  在＃提示符下执行命令<br />cp /dev/cdrom XXXXX.iso<br />XXXXX.iso即为需要命名的ISO文件名<br />执行之后，光盘上所有文件就被映射成XXXXX.iso</p>
<p>至于如何加载嘛<br />请看下面<br />还是在＃提示符下执行命令<br />rm -rf /dev/cdrom<br />ln -s /dev/loop7 /dev/cdrom<br />losetup /dev/loop7 /PATH（iso文件路径）<br />mount /mnt/cdrom</p>
<p>如果需要换盘<br />losetup -d /dev/loop7<br />再重复<br />losetup /dev/loop7 /PATH（iso文件路径）<br />mount /mnt/cdrom</p>
<p>如果是普通含有iso的光盘<br />可以直接使用命令<br />mount -t iso9660 -o loop /../*.iso /path<br />/&#8230;/*.iso 是iso文件路径<br />/path 是挂载点</span></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.donews.com/QQwinterQQ/archive/2006/07/04/946052.aspx/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>java设计模式之行为模式[Memento(备忘机制)]</title>
		<link>http://blog.donews.com/QQwinterQQ/archive/2006/06/06/905448.aspx</link>
		<comments>http://blog.donews.com/QQwinterQQ/archive/2006/06/06/905448.aspx#comments</comments>
		<pubDate>Tue, 06 Jun 2006 15:42:00 +0000</pubDate>
		<dc:creator>winer</dc:creator>
				<category><![CDATA[java]]></category>

		<guid isPermaLink="false">http://blog.donews.com/QQwinterQQ/archive/2006/06/06/905448.aspx</guid>
		<description><![CDATA[Memento定义:<br/>memento是一个保存另外一个对象内部状态拷贝的对象.这样以后就可以将该对象恢复到原先保存的状态.<br/><br/>Memento模式相对也比较好理解,我们看下列代码:<br/><br/>public 
class Originator { <br/><br/>　　 private int number; <br/><br/>　　private File file = 
null;<br/><br/>　　public Originator(){}<br/><br/>　　// 创建一个Memento<br/>　　public Memento 
getMemento(){<br/>　　　　return new Memento(this);<br/>　　}<br/><br/>　　// 
恢复到原始值<br/>　　public void setMemento(Memento m){<br/>　　　　 number = 
m.number;<br/>　　　　 file = 
m.file;<br/>　　}<br/><br/>}<br/><br/>&#038;n]]></description>
			<content:encoded><![CDATA[<p>Memento定义:<br/>memento是一个保存另外一个对象内部状态拷贝的对象.这样以后就可以将该对象恢复到原先保存的状态.<br/><br/>Memento模式相对也比较好理解,我们看下列代码:<br/><br/>public<br />
class Originator { <br/><br/>　　 private int number; <br/><br/>　　private File file =<br />
null;<br/><br/>　　public Originator(){}<br/><br/>　　// 创建一个Memento<br/>　　public Memento<br />
getMemento(){<br/>　　　　return new Memento(this);<br/>　　}<br/><br/>　　//<br />
恢复到原始值<br/>　　public void setMemento(Memento m){<br/>　　　　 number =<br />
m.number;<br/>　　　　 file =<br />
m.file;<br/>　　}<br/><br/>}<br/><br/>&nbsp;<br/>&nbsp;<br/><br/>我们再看看Memento类:<br/><br/>private class<br />
Memento implements java.io.Serializable{<br/><br/>　　private int<br />
number;<br/><br/>　　private File file = null;<br/><br/>　　public Memento( Originator<br />
o){<br/><br/>　　　　number = o.number;<br/>　　　　file =<br />
o.file;<br/><br/>　　}<br/><br/>}<br/><br/>&nbsp;<br/>&nbsp;<br/><br/>可见<br />
Memento中保存了Originator中的number和file的值.<br />
通过调用Originator中number和file值改变的话,通过调用setMemento()方法可以恢复.<br/><br/>Memento模式的缺点是耗费大,如果内部状态很多,再保存一份,无意要浪费大量内存.<br/><br/>Memento模式在Jsp+Javabean中的应用<br/>在Jsp应用中,我们通常有很多表单要求用户输入,比如用户注册,需要输入姓名和Email等,<br />
如果一些表项用户没有填写或者填写错误,我们希望在用户按&quot;提交Submit&quot;后,通过Jsp程序检查,发现确实有未填写项目,则在该项目下红字显示警告或错误,同时,还要显示用户刚才已经输入的表项.<br/><br/>如下图中<br />
First Name是用户已经输入,Last<br />
Name没有输入,我们则提示红字警告.:<br/><br/>[缺图]<br/><br/>这种技术的实现,就是利用了Javabean的scope=&quot;request&quot;或scope=&quot;session&quot;特性,也就是Memento模式.<br/><br/>具体示例和代码见<br />
JavaWorld的英文原文 , Javabean表单输入特性参见我的另外一篇文章.<br/><br/></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.donews.com/QQwinterQQ/archive/2006/06/06/905448.aspx/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>java设计模式之行为模式[Template]</title>
		<link>http://blog.donews.com/QQwinterQQ/archive/2006/06/06/905446.aspx</link>
		<comments>http://blog.donews.com/QQwinterQQ/archive/2006/06/06/905446.aspx#comments</comments>
		<pubDate>Tue, 06 Jun 2006 15:41:00 +0000</pubDate>
		<dc:creator>winer</dc:creator>
				<category><![CDATA[java]]></category>

		<guid isPermaLink="false">http://blog.donews.com/QQwinterQQ/archive/2006/06/06/905446.aspx</guid>
		<description><![CDATA[Template定义:<br/>定义一个操作中算法的骨架,将一些步骤的执行延迟到其子类中.<br/><br/>其实Java的抽象类本来就是Template模式,因此使用很普遍.而且很容易理解和使用,我们直接以示例开始:<br/><br/>public 
abstract class Benchmark<br/>{<br/>　　/**<br/>　　* 
下面操作是我们希望在子类中完成<br/>　　*/<br/>　　public abstract void benchmark(); 
<br/><br/>　　/**<br/>　　* 重复执行benchmark次数<br/>　　*/<br/>　　public final long repeat (int 
count) {<br/>　　　　if (count &#60;= 0)<br/>　　　　　　return 0;<br/>　　　　else 
{<br/>　　　　　　long startTime = System.currentTimeMillis();<br/><br/>　　　　for (int i = 
0; i &#60; c]]></description>
			<content:encoded><![CDATA[<p>Template定义:<br/>定义一个操作中算法的骨架,将一些步骤的执行延迟到其子类中.<br/><br/>其实Java的抽象类本来就是Template模式,因此使用很普遍.而且很容易理解和使用,我们直接以示例开始:<br/><br/>public<br />
abstract class Benchmark<br/>{<br/>　　/**<br/>　　*<br />
下面操作是我们希望在子类中完成<br/>　　*/<br/>　　public abstract void benchmark();<br />
<br/><br/>　　/**<br/>　　* 重复执行benchmark次数<br/>　　*/<br/>　　public final long repeat (int<br />
count) {<br/>　　　　if (count &lt;= 0)<br/>　　　　　　return 0;<br/>　　　　else<br />
{<br/>　　　　　　long startTime = System.currentTimeMillis();<br/><br/>　　　　for (int i =<br />
0; i &lt; count; i++) <br/>　　　　　　benchmark();<br/><br/>　　　　long stopTime =<br />
System.currentTimeMillis();<br/>　　　　return stopTime &#8211;<br />
startTime;<br/>　　}<br/>}<br/>}<br/>&nbsp;<br/><br/>在上例中,我们希望重复执行benchmark()操作,但是对benchmark()的具体内容没有说明,而是延迟到其子类中描述:<br/><br/>public<br />
class MethodBenchmark extends Benchmark<br/>{<br/>　　/**<br/>　　*<br />
真正定义benchmark内容<br/>　　*/<br/>　　public void benchmark() {<br/><br/>　　　　for (int i =<br />
0; i &lt; Integer.MAX_VALUE; i++){<br/>　　　 　　System.out.printtln(&quot;i=&quot;+i);　<br />
　　<br/>　　　<br />
}<br/>　　}<br/>}<br/>&nbsp;<br/><br/>至此,Template模式已经完成,是不是很简单?看看如何使用:<br/><br/>Benchmark<br />
operation = new MethodBenchmark();<br/>long duration =<br />
operation.repeat(Integer.parseInt(args[0].trim()));<br/>System.out.println(&quot;The<br />
operation took &quot; + duration + &quot;<br />
milliseconds&quot;);<br/><br/>&nbsp;<br/><br/>也许你以前还疑惑抽象类有什么用,现在你应该彻底明白了吧?<br />
至于这样做的好处,很显然啊,扩展性强,以后Benchmark内容变化,我只要再做一个继承子类就可以,不必修改其他应用代码.<br/><br/></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.donews.com/QQwinterQQ/archive/2006/06/06/905446.aspx/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>java设计模式之结构模式[Flyweight(享元)]</title>
		<link>http://blog.donews.com/QQwinterQQ/archive/2006/06/06/905443.aspx</link>
		<comments>http://blog.donews.com/QQwinterQQ/archive/2006/06/06/905443.aspx#comments</comments>
		<pubDate>Tue, 06 Jun 2006 15:41:00 +0000</pubDate>
		<dc:creator>winer</dc:creator>
				<category><![CDATA[java]]></category>

		<guid isPermaLink="false">http://blog.donews.com/QQwinterQQ/archive/2006/06/06/905443.aspx</guid>
		<description><![CDATA[Flyweight定义:避免大量拥有相同内容的小类的开销(如耗费内存),使大家共享一个类(元类).为什么使用?面向对象语言的原则就是一切都是对象,但是如果真正使用起来,有时对象数可能显得很庞大,比如,字处理软件,如果以每个文字都作为一个对象,几千个字,对象数就是几千,无疑耗费内存,那么我们还是要&#34;求同存异&#34;,找出这些对象群的共同点,设计一个元类,封装可以被共享的类,另外,还有一些特性是取决于应用(context),是不可共享的,这也Flyweight中两个重要概念内部状态intrinsic和外部状态extrinsic之分.说白点,就是先捏一个的原始模型,然后随着不同场合和环境,再产生各具特征的具体模型,很显然,在这里需要产生不同的新对象,所以Flyweight模式中常出现Factory模式.Flyweight的内部状态是用来共享的,Flyweight 
factory负责维护一个Flyweight 
pool(模式池)来存放内部状态的对象.Flyweight模式是一个提高程序效率和性]]></description>
			<content:encoded><![CDATA[<p>Flyweight定义:<br/>避免大量拥有相同内容的小类的开销(如耗费内存),使大家共享一个类(元类).<br/><br/>为什么使用?<br/>面向对象语言的原则就是一切都是对象,但是如果真正使用起来,有时对象数可能显得很庞大,比如,字处理软件,如果以每个文字都作为一个对象,几千个字,对象数就是几千,无疑耗费内存,那么我们还是要&quot;求同存异&quot;,找出这些对象群的共同点,设计一个元类,封装可以被共享的类,另外,还有一些特性是取决于应用(context),是不可共享的,这也Flyweight中两个重要概念内部状态intrinsic和外部状态extrinsic之分.<br/><br/>说白点,就是先捏一个的原始模型,然后随着不同场合和环境,再产生各具特征的具体模型,很显然,在这里需要产生不同的新对象,所以Flyweight模式中常出现Factory模式.Flyweight的内部状态是用来共享的,Flyweight<br />
factory负责维护一个Flyweight<br />
pool(模式池)来存放内部状态的对象.<br/><br/>Flyweight模式是一个提高程序效率和性能的模式,会大大加快程序的运行速度.应用场合很多:比如你要从一个数据库中读取一系列字符串,这些字符串中有许多是重复的,那么我们可以将这些字符串储存在Flyweight池(pool)中.<br/><br/>如何使用?<br/><br/>我们先从Flyweight抽象接口开始:<br/><br/>public<br />
inte***ce Flyweight <br/>{<br/>　　public void operation( ExtrinsicState state<br />
);<br/>}<br/><br/>//用于本模式的抽象数据类型(自行设计)<br/>public inte***ce ExtrinsicState {<br />
}<br/>&nbsp;<br/><br/>下面是接口的具体实现(ConcreteFlyweight) ,并为内部状态增加内存空间,<br />
ConcreteFlyweight必须是可共享的,它保存的任何状态都必须是内部(intrinsic),也就是说,ConcreteFlyweight必须和它的应用环境场合无关.<br/><br/>public<br />
class ConcreteFlyweight implements Flyweight {<br/>　　private IntrinsicState<br />
state; <br/>　　<br/>　　public void operation( ExtrinsicState state ) <br/>　　{<br />
<br/>　　　　　　//具体操作<br/>　　} <br/><br/>}<br />
<br/>&nbsp;<br/><br/>当然,并不是所有的Flyweight具体实现子类都需要被共享的,所以还有另外一种不共享的ConcreteFlyweight:<br/><br/>public<br />
class UnsharedConcreteFlyweight implements Flyweight {<br/><br/>　　public void<br />
operation( ExtrinsicState state ) { }<br/><br/>}<br/>&nbsp;<br/><br/>Flyweight<br />
factory负责维护一个Flyweight池(存放内部状态),当客户端请求一个共享Flyweight时,这个factory首先搜索池中是否已经有可适用的,如果有,factory只是简单返回送出这个对象,否则,创建一个新的对象,加入到池中,再返回送出这个对象.池<br/><br/>public<br />
class FlyweightFactory { <br/>　　//Flyweight pool<br/>　　private Hashtable<br />
flyweights = new Hashtable(); <br/><br/>　　public Flyweight getFlyweight( Object<br />
key ) { <br/><br/>　　　　Flyweight flyweight = (Flyweight) flyweights.get(key);<br />
<br/><br/>　　　　if( flyweight == null )<br />
{<br/>　　　　　　//产生新的ConcreteFlyweight<br/>　　　　　　flyweight = new ConcreteFlyweight();<br />
<br/>　　　　　　flyweights.put( key, flyweight ); <br/>　　　　} <br/><br/>　　　　return<br />
flyweight; <br/>　　} <br/>}<br />
<br/>&nbsp;<br/><br/>至此,Flyweight模式的基本框架已经就绪,我们看看如何调用:<br/><br/>FlyweightFactory factory =<br />
new FlyweightFactory(); <br/>Flyweight fly1 = factory.getFlyweight( &quot;Fred&quot; );<br />
<br/>Flyweight fly2 = factory.getFlyweight( &quot;Wilma&quot;<br />
);<br/>&#8230;&#8230;<br/><br/>从调用上看,好象是个纯粹的Factory使用,但奥妙就在于Factory的内部设计上.<br/><br/>Flyweight模式在XML等数据源中应用<br/>我们上面已经提到,当大量从数据源中读取字符串,其中肯定有重复的,那么我们使用Flyweight模式可以提高效率,以唱片CD为例,在一个XML文件中,存放了多个CD的资料.<br/><br/>每个CD有三个字段:<br/>1.出片日期(year)<br/>2.歌唱者姓名等信息(artist)<br/>3.唱片曲目<br />
(title)<br/><br/>其中,歌唱者姓名有可能重复,也就是说,可能有同一个演唱者的多个不同时期<br />
不同曲目的CD.我们将&quot;歌唱者姓名&quot;作为可共享的ConcreteFlyweight.其他两个字段作为UnsharedConcreteFlyweight.<br/><br/>首先看看数据源XML文件的内容:<br/><br/><br/>&lt;?xml<br />
version=&quot;1.0&quot;?&gt;<br/>&lt;collection&gt;<br/><br/>&lt;cd&gt;<br/>&lt;title&gt;Another<br />
Green World&lt;/title&gt;<br/>&lt;year&gt;1978&lt;/year&gt;<br/>&lt;artist&gt;Eno,<br />
Brian&lt;/artist&gt;<br/>&lt;/cd&gt;<br/><br/>&lt;cd&gt;<br/>&lt;title&gt;Greatest<br />
Hits&lt;/title&gt;<br/>&lt;year&gt;1950&lt;/year&gt;<br/>&lt;artist&gt;Holiday,<br />
Billie&lt;/artist&gt;<br/>&lt;/cd&gt;<br/><br/>&lt;cd&gt;<br/>&lt;title&gt;Taking<br />
Tiger Mountain (by<br />
strategy)&lt;/title&gt;<br/>&lt;year&gt;1977&lt;/year&gt;<br/>&lt;artist&gt;Eno,<br />
Brian&lt;/artist&gt;<br/>&lt;/cd&gt;<br/><br/>&#8230;&#8230;.<br />
<br/><br/>&lt;/collection&gt;<br/>&nbsp;<br/><br/><br/>虽然上面举例CD只有3张,CD可看成是大量重复的小类,因为其中成分只有三个字段,而且有重复的(歌唱者姓名).<br/><br/>CD就是类似上面接口<br />
Flyweight:<br/><br/><br/>public class CD {<br/><br/>　　private String<br />
title;<br/>　　private int year;<br/>　　private Artist artist;<br/><br/>　　public String<br />
getTitle() {　　return title;　}<br/>　　public int getYear() {　　　　return<br />
year;　　}<br/>　　public Artist getArtist() {　　　　return artist;　　}<br/><br/>　　public<br />
void setTitle(String t){　　　　title = t;}<br/>　　public void setYear(int y){year =<br />
y;}<br/>　　public void setArtist(Artist a){artist =<br />
a;}<br/><br/>}<br/>&nbsp;<br/><br/>将&quot;歌唱者姓名&quot;作为可共享的ConcreteFlyweight:<br/><br/>public class<br />
Artist {<br/><br/>　　//内部状态<br/>　　private String name; <br/><br/>　　// note that Artist<br />
is immutable.<br/>　　String getName(){return name;}<br/><br/>　　Artist(String<br />
n){<br/>　　　　name = n;<br/>　　} <br/><br/>}<br/>&nbsp;<br/><br/>再看看Flyweight<br />
factory,专门用来制造上面的可共享的ConcreteFlyweight:Artist<br/><br/>public class ArtistFactory<br />
{<br/><br/>　　Hashtable pool = new Hashtable();<br/><br/>　　Artist getArtist(String<br />
key){<br/><br/>　　　　Artist result;<br/>　　　　result =<br />
(Artist)pool.get(key);<br/>　　　　////产生新的Artist<br/>　　　　if(result == null)<br />
{<br/>　　　　　　result = new<br />
Artist(key);<br/>　　　　　　pool.put(key,result);<br/>　　　　　　<br/>　　　　}<br/>　　　 return<br />
result;<br/>　<br />
}<br/><br/>}<br/>&nbsp;<br/><br/>当你有几千张甚至更多CD时,Flyweight模式将节省更多空间,共享的flyweight越多,空间节省也就越大.<br/><br/></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.donews.com/QQwinterQQ/archive/2006/06/06/905443.aspx/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>java设计模式之结构模式[Bridge]</title>
		<link>http://blog.donews.com/QQwinterQQ/archive/2006/06/06/905440.aspx</link>
		<comments>http://blog.donews.com/QQwinterQQ/archive/2006/06/06/905440.aspx#comments</comments>
		<pubDate>Tue, 06 Jun 2006 15:40:00 +0000</pubDate>
		<dc:creator>winer</dc:creator>
				<category><![CDATA[java]]></category>

		<guid isPermaLink="false">http://blog.donews.com/QQwinterQQ/archive/2006/06/06/905440.aspx</guid>
		<description><![CDATA[Bridge定义 
:将抽象和行为划分开来,各自独立,但能动态的结合.为什么使用?通常,当一个抽象类或接口有多个具体实现(concrete 
subclass),这些concrete之间关系可能有以下两种:1. 这多个具体实现之间恰好是并列的,如前面举例,打桩,有两个concrete 
class:方形桩和圆形桩;这两个形状上的桩是并列的,没有概念上的重复,那么我们只要使用继承就可以了.2.实际应用上,常常有可能在这多个concrete 
class之间有概念上重叠.那么需要我们把抽象共同部分和行为共同部分各自独立开来,原来是准备放在一个接口里,现在需要设计两个接口,分别放置抽象和行为.例如,一杯咖啡为例,有中杯和大杯之分,同时还有加奶 
不加奶之分. 如果用单纯的继承,这四个具体实现(中杯 大杯 加奶 不加奶)之间有概念重叠,因为有中杯加奶,也有中杯不加奶, 
如果再在中杯这一层再实现两个继承,很显然混乱,扩展性极差.那我们使用Bridge模式来实现它.如何实现?]]></description>
			<content:encoded><![CDATA[<p>Bridge定义<br />
:<br/>将抽象和行为划分开来,各自独立,但能动态的结合.<br/><br/>为什么使用?<br/>通常,当一个抽象类或接口有多个具体实现(concrete<br />
subclass),这些concrete之间关系可能有以下两种:<br/>1. 这多个具体实现之间恰好是并列的,如前面举例,打桩,有两个concrete<br />
class:方形桩和圆形桩;这两个形状上的桩是并列的,没有概念上的重复,那么我们只要使用继承就可以了.<br/><br/>2.实际应用上,常常有可能在这多个concrete<br />
class之间有概念上重叠.那么需要我们把抽象共同部分和行为共同部分各自独立开来,原来是准备放在一个接口里,现在需要设计两个接口,分别放置抽象和行为.<br/><br/>例如,一杯咖啡为例,有中杯和大杯之分,同时还有加奶<br />
不加奶之分. 如果用单纯的继承,这四个具体实现(中杯 大杯 加奶 不加奶)之间有概念重叠,因为有中杯加奶,也有中杯不加奶,<br />
如果再在中杯这一层再实现两个继承,很显然混乱,扩展性极差.那我们使用Bridge模式来实现它.<br/><br/>如何实现?<br/>以上面提到的咖啡 为例.<br />
我们原来打算只设计一个接口(抽象类),使用Bridge模式后,我们需要将抽象和行为分开,加奶和不加奶属于行为,我们将它们抽象成一个专门的行为接口.<br/><br/>先看看抽象部分的接口代码:<br/><br/>public<br />
abstract class Coffee<br/>{<br/>　　CoffeeImp coffeeImp;<br/><br/>　　public void<br />
setCoffeeImp() {<br/>　　　　this.CoffeeImp =<br />
CoffeeImpSingleton.getTheCoffeImp();<br/>　　}<br/><br/>　　public CoffeeImp<br />
getCoffeeImp() {return this.CoffeeImp;}<br/><br/>　　public abstract void<br />
pourCoffee();<br/>}<br/>&nbsp;<br/><br/>其中CoffeeImp 是加不加奶的行为接口,看其代码如下:<br/><br/>public<br />
abstract class CoffeeImp<br/>{<br/>　　public abstract void<br />
pourCoffeeImp();<br/>}<br/>&nbsp;<br/><br/>现在我们有了两个抽象类,下面我们分别对其进行继承,实现concrete<br />
class:<br/><br/>//中杯<br/>public class MediumCoffee extends Coffee<br/>{<br/>　　public<br />
MediumCoffee() {setCoffeeImp();}<br/><br/>　　public void<br />
pourCoffee()<br/>　　{<br/>　　　　CoffeeImp coffeeImp =<br />
this.getCoffeeImp();<br/>　　　　//我们以重复次数来说明是冲中杯还是大杯 ,重复2次是中杯<br/>　　　　for (int i = 0;<br />
i &lt; 2;<br />
i++)<br/>　　　　{<br/><br/>　　　　　　coffeeImp.pourCoffeeImp();<br/>　　　　}<br/>　　<br/>　　}<br/>}<br/><br/>//大杯<br/>public<br />
class SuperSizeCoffee extends Coffee<br/>{<br/>　　public SuperSizeCoffee()<br />
{setCoffeeImp();}<br/><br/>　　public void pourCoffee()<br/>　　{<br/>　　　　CoffeeImp<br />
coffeeImp = this.getCoffeeImp();<br/>　　　　//我们以重复次数来说明是冲中杯还是大杯 ,重复5次是大杯<br/>　　　　for<br />
(int i = 0; i &lt; 5;<br />
i++)<br/>　　　　{<br/><br/>　　　　　　coffeeImp.pourCoffeeImp();<br/>　　　　}<br/>　　<br/>　　}<br/>}<br/>&nbsp;<br/><br/>上面分别是中杯和大杯的具体实现.下面再对行为CoffeeImp进行继承:<br/><br/>//加奶<br/>public<br />
class MilkCoffeeImp extends CoffeeImp<br/>{<br/>　　MilkCoffeeImp()<br />
{}<br/><br/>　　public void<br />
pourCoffeeImp()<br/>　　{<br/>　　　　System.out.println(&quot;加了美味的牛奶&quot;);<br/>　　}<br/>}<br/><br/>//不加奶<br/>public<br />
class FragrantCoffeeImp extends CoffeeImp<br/>{<br/>　　FragrantCoffeeImp()<br />
{}<br/><br/>　　public void<br />
pourCoffeeImp()<br/>　　{<br/>　　　　System.out.println(&quot;什么也没加,清香&quot;);<br/>　　}<br/>}<br/>&nbsp;<br/><br/>Bridge模式的基本框架我们已经搭好了,别忘记定义中还有一句:动态结合,我们现在可以喝到至少四种咖啡:<br/>1.中杯加奶<br/>2.中杯不加奶<br/>3.大杯加奶<br/>4.大杯不加奶<br/><br/>看看是如何动态结合的,在使用之前,我们做个准备工作,设计一个单态类(Singleton)用来hold当前的CoffeeImp:<br/><br/>public<br />
class CoffeeImpSingleton<br/>{<br/>　　private static CoffeeImp<br />
coffeeImp;<br/><br/>　　public CoffeeImpSingleton(CoffeeImp coffeeImpIn)<br/>　　<br />
{this.coffeeImp = coffeeImpIn;}<br/><br/>　　public static CoffeeImp<br />
getTheCoffeeImp()<br/>　　{<br/>　　　　return coffeeImp;<br/>　　}<br/>}<br/>&nbsp;<br/><br/>看看中杯加奶<br />
和大杯加奶 是怎么出来的:<br/><br/>//拿出牛奶<br/>CoffeeImpSingleton coffeeImpSingleton = new<br />
CoffeeImpSingleton(new MilkCoffeeImp());<br/><br/>//中杯加奶<br/>MediumCoffee<br />
mediumCoffee = new<br />
MediumCoffee();<br/>mediumCoffee.pourCoffee();<br/><br/>//大杯加奶<br/>SuperSizeCoffee<br />
superSizeCoffee = new<br />
SuperSizeCoffee();<br/>superSizeCoffee.pourCoffee();<br/><br/>注意:<br />
Bridge模式的执行类如CoffeeImp和Coffee是一对一的关系,<br />
正确创建CoffeeImp是该模式的关键,<br/><br/>Bridge模式在EJB中的应用<br/>EJB中有一个Data Access Object<br />
(DAO)模式,这是将商业逻辑和具体数据资源分开的,因为不同的数据库有不同的数据库操作.将操作不同数据库的行为独立抽象成一个行为接口DAO.如下:<br/><br/>1.Business<br />
Object<br />
(类似Coffee)<br/><br/>实现一些抽象的商业操作:如寻找一个用户下所有的订单<br/><br/>涉及数据库操作都使用DAOImplementor.<br/><br/>2.Data<br />
Access Object (类似CoffeeImp)<br/><br/>一些抽象的对数据库资源操作<br/><br/>3.DAOImplementor<br />
如OrderDAOCS, OrderDAOOracle, OrderDAOSybase(类似MilkCoffeeImp<br />
FragrantCoffeeImp)<br/><br/>具体的数据库操作,如&quot;INSERT INTO &quot;等语句,OrderDAOOracle是Oracle<br />
OrderDAOSybase是Sybase数据库.<br/><br/>4.数据库 (Cloudscape, Oracle, or Sybase database<br />
via JDBC API)<br/><br/><br/></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.donews.com/QQwinterQQ/archive/2006/06/06/905440.aspx/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>java设计模式之结构模式[Decorator(油漆工)]</title>
		<link>http://blog.donews.com/QQwinterQQ/archive/2006/06/06/905435.aspx</link>
		<comments>http://blog.donews.com/QQwinterQQ/archive/2006/06/06/905435.aspx#comments</comments>
		<pubDate>Tue, 06 Jun 2006 15:39:00 +0000</pubDate>
		<dc:creator>winer</dc:creator>
				<category><![CDATA[java]]></category>

		<guid isPermaLink="false">http://blog.donews.com/QQwinterQQ/archive/2006/06/06/905435.aspx</guid>
		<description><![CDATA[Decorator常被翻译成&#34;装饰&#34;,我觉得翻译成&#34;油漆工&#34;更形象点,油漆工(decorator)是用来刷油漆的,那么被刷油漆的对象我们称decoratee.这两种实体在Decorator模式中是必须的.Decorator定义:动态给一个对象添加一些额外的职责,就象在墙上刷油漆.使用Decorator模式相比用生成子类方式达到功能的扩充显得更为灵活.为什么使用Decorator?我们通常可以使用继承来实现功能的拓展,如果这些需要拓展的功能的种类很繁多,那么势必生成很多子类,增加系统的复杂性,同时,使用继承实现功能拓展,我们必须可预见这些拓展功能,这些功能是编译时就确定了,是静态的.使用Decorator的理由是:这些功能需要由用户动态决定加入的方式和时机.Decorator提供了&#34;即插即用&#34;的方法,在运行期间决定何时增加何种功能.如何使用?举Adapter中的打桩示例,在Adapter中有两种类:方形桩 
圆形桩,A]]></description>
			<content:encoded><![CDATA[<p>Decorator常被翻译成&quot;装饰&quot;,我觉得翻译成&quot;油漆工&quot;更形象点,油漆工(decorator)是用来刷油漆的,那么被刷油漆的对象我们称decoratee.这两种实体在Decorator模式中是必须的.<br/><br/>Decorator定义:<br/>动态给一个对象添加一些额外的职责,就象在墙上刷油漆.使用Decorator模式相比用生成子类方式达到功能的扩充显得更为灵活.<br/><br/>为什么使用Decorator?<br/>我们通常可以使用继承来实现功能的拓展,如果这些需要拓展的功能的种类很繁多,那么势必生成很多子类,增加系统的复杂性,同时,使用继承实现功能拓展,我们必须可预见这些拓展功能,这些功能是编译时就确定了,是静态的.<br/><br/>使用Decorator的理由是:这些功能需要由用户动态决定加入的方式和时机.Decorator提供了&quot;即插即用&quot;的方法,在运行期间决定何时增加何种功能.<br/><br/>如何使用?<br/>举Adapter中的打桩示例,在Adapter中有两种类:方形桩<br />
圆形桩,Adapter模式展示如何综合使用这两个类,在Decorator模式中,我们是要在打桩时增加一些额外功能,比如,挖坑<br />
在桩上钉木板等,不关心如何使用两个不相关的类.<br/><br/>我们先建立一个接口:<br/><br/>public inte***ce Work<br/>{<br />
<br/>　　public void<br />
insert();<br/><br/>}<br/>&nbsp;<br/><br/>接口Work有一个具体实现:插入方形桩或圆形桩,这两个区别对Decorator是无所谓.我们以插入方形桩为例:<br/><br/>public<br />
class SquarePeg implements Work{<br/>　　public void<br />
insert(){<br/>　　　　System.out.println(&quot;方形桩插入&quot;);<br/>　　}<br />
<br/><br/>}<br/>&nbsp;<br/><br/>现在有一个应用:需要在桩打入前,挖坑,在打入后,在桩上钉木板,这些额外的功能是动态,可能随意增加调整修改,比如,可能又需要在打桩之后钉架子(只是比喻).<br/><br/>那么我们使用Decorator模式,这里方形桩SquarePeg是decoratee(被刷油漆者),我们需要在decoratee上刷些&quot;油漆&quot;,这些油漆就是那些额外的功能.<br/><br/>public<br />
class Decorator implements Work{<br/><br/>　　private Work<br />
work;<br/>　　//额外增加的功能被打包在这个List中<br/>　　private ArrayList others = new ArrayList();<br />
<br/><br/>　　//在构造器中使用组合new方式,引入Work对象;<br/>　　public Decorator(Work<br />
work)<br/>　　{<br/>　　　　this.work=work;<br/>　　<br />
<br/>　　　　others.add(&quot;挖坑&quot;);<br/><br/>　　　　others.add(&quot;钉木板&quot;);<br/>　　}<br/><br/>　　public<br />
void insert(){<br/><br/>　　　　newMethod();<br/>　　}<br />
<br/><br/><br/>　　<br/>　　//在新方法中,我们在insert之前增加其他方法,这里次序先后是用户灵活指定的 　　 <br/>　　public<br />
void<br />
newMethod()<br/>　　{<br/>　　　　otherMethod();<br/>　　　　work.insert();<br/><br/><br/>　　}<br />
<br/><br/>　　public void otherMethod()<br/>　　{<br/>　　　　ListIterator listIterator =<br />
others.listIterator();<br/>　　　　while<br />
(listIterator.hasNext())<br/>　　　　{<br/>　　　　　　System.out.println(((String)(listIterator.next()))<br />
+ &quot; 正在进行&quot;);<br/>　　　　}<br/><br/>　　}<br />
<br/><br/>}<br/>&nbsp;<br/><br/>在上例中,我们把挖坑和钉木板都排在了打桩insert前面,这里只是举例说明额外功能次序可以任意安排.<br/><br/>好了,Decorator模式出来了,我们看如何调用:<br/><br/>Work<br />
squarePeg = new SquarePeg(); <br/>Work decorator = new<br />
Decorator(squarePeg);<br/>decorator.insert();<br />
<br/><br/>Decorator模式至此完成.<br/><br/>如果你细心,会发现,上面调用类似我们读取文件时的调用:<br/><br/>FileReader fr<br />
= new FileReader(filename);<br/>BufferedReader br = new<br />
BufferedReader(fr);<br/><br/>实际上Java 的I/O<br />
API就是使用Decorator实现的,I/O变种很多,如果都采取继承方法,将会产生很多子类,显然相当繁琐.<br/><br/>Jive中的Decorator实现<br/>在论坛系统中,有些特别的字是不能出现在论坛中如&quot;打倒XXX&quot;,我们需要过滤这些&quot;反动&quot;的字体.不让他们出现或者高亮度显示.<br/><br/>在IBM<br />
Java专栏中专门谈Jive的文章中,有谈及Jive中ForumMessageFilter.java使用了Decorator模式,其实,该程序并没有真正使用Decorator,而是提示说:针对特别论坛可以设计额外增加的过滤功能,那么就可以重组ForumMessageFilter作为Decorator模式了.<br/><br/>所以,我们在分辨是否真正是Decorator模式,以及会真正使用Decorator模式,一定要把握好Decorator模式的定义,以及其中参与的角色(Decoratee<br />
和Decorator).<br/><br/></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.donews.com/QQwinterQQ/archive/2006/06/06/905435.aspx/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>java设计模式之结构模式[Composite(组合)]</title>
		<link>http://blog.donews.com/QQwinterQQ/archive/2006/06/06/905427.aspx</link>
		<comments>http://blog.donews.com/QQwinterQQ/archive/2006/06/06/905427.aspx#comments</comments>
		<pubDate>Tue, 06 Jun 2006 15:36:00 +0000</pubDate>
		<dc:creator>winer</dc:creator>
				<category><![CDATA[java]]></category>

		<guid isPermaLink="false">http://blog.donews.com/QQwinterQQ/archive/2006/06/06/905427.aspx</guid>
		<description><![CDATA[Composite定义:<br/>将对象以树形结构组织起来,以达成&#8220;部分－整体&#8221; 
的层次结构，使得客户端对单个对象和组合对象的使用具有一致性.<br/><br/>Composite比较容易理解，想到Composite就应该想到树形结构图。组合体内这些对象都有共同接口,当组合体一个对象的方法被调用执行时，Composite将遍历(Iterator)整个树形结构,寻找同样包含这个方法的对象并实现调用执行。可以用牵一动百来形容。<br/><br/>所以Composite模式使用到Iterator模式，和Chain 
of 
Responsibility模式类似。<br/><br/>Composite好处:<br/>1.使客户端调用简单，客户端可以一致的使用组合结构或其中单个对象，用户就不必关系自己处理的是单个对象还是整个组合结构，这就简化了客户端代码。<br/>2.更容易在组合体内加入对象部件. 
客户端不必因为加入了新的对象部件而更改代码。<br/><br/>如何使用Composite?<br/>首先定义一个接口或抽象类，这是设计模式通用方式了，其他设计模]]></description>
			<content:encoded><![CDATA[<p>Composite定义:<br/>将对象以树形结构组织起来,以达成&ldquo;部分－整体&rdquo;<br />
的层次结构，使得客户端对单个对象和组合对象的使用具有一致性.<br/><br/>Composite比较容易理解，想到Composite就应该想到树形结构图。组合体内这些对象都有共同接口,当组合体一个对象的方法被调用执行时，Composite将遍历(Iterator)整个树形结构,寻找同样包含这个方法的对象并实现调用执行。可以用牵一动百来形容。<br/><br/>所以Composite模式使用到Iterator模式，和Chain<br />
of<br />
Responsibility模式类似。<br/><br/>Composite好处:<br/>1.使客户端调用简单，客户端可以一致的使用组合结构或其中单个对象，用户就不必关系自己处理的是单个对象还是整个组合结构，这就简化了客户端代码。<br/>2.更容易在组合体内加入对象部件.<br />
客户端不必因为加入了新的对象部件而更改代码。<br/><br/>如何使用Composite?<br/>首先定义一个接口或抽象类，这是设计模式通用方式了，其他设计模式对接口内部定义限制不多，Composite却有个规定，那就是要在接口内部定义一个用于访问和管理Composite组合体的对象们（或称部件Component）.<br/><br/>下面的代码是以抽象类定义，一般尽量用接口inte***ce,<br/><br/>public<br />
abstract class Equipment<br/>{<br/>　　private String name; <br/>　　//网络价格<br/>　　public<br />
abstract double netPrice();<br/>　　//折扣价格<br/>　　public abstract double<br />
discountPrice();<br/>　　//增加部件方法　　<br/>　　public boolean add(Equipment equipment) {<br />
return false; }<br/>　　//删除部件方法<br/>　　public boolean remove(Equipment equipment) {<br />
return false; }<br/>　　//注意这里，这里就提供一种用于访问组合体类的部件方法。<br/>　　public Iterator iter() {<br />
return null; }<br/>　　<br/>　　public Equipment(final String name) { this.name=name;<br />
}<br/>}<br />
<br/>&nbsp;<br/><br/>抽象类Equipment就是Component定义，代表着组合体类的对象们,Equipment中定义几个共同的方法。<br/><br/>public<br />
class Disk extends Equipment<br/>{<br/>　　public Disk(String name) { super(name);<br />
}<br/>　　//定义Disk网络价格为1<br/>　　public double netPrice() { return 1.;<br />
}<br/>　　//定义了disk折扣价格是0.5 对折。<br/>　　public double discountPrice() { return .5;<br />
}<br/>}<br/>&nbsp;<br/><br/>Disk是组合体内的一个对象，或称一个部件，这个部件是个单独元素(<br />
Primitive)。<br/>还有一种可能是，一个部件也是一个组合体，就是说这个部件下面还有&#8217;儿子&#8217;，这是树形结构中通常的情况，应该比较容易理解。现在我们先要定义这个组合体：<br/><br/>abstract<br />
class CompositeEquipment extends Equipment<br/>{<br/>　　private int i=0;<br />
<br/>　　//定义一个Vector 用来存放&#8217;儿子&#8217;<br/>　　private Lsit equipment=new<br />
ArrayList();<br/><br/>　　public CompositeEquipment(String name) { super(name);<br />
}<br/><br/>　　public boolean add(Equipment equipment) { <br/>　　　　<br />
this.equipment.add(equipment); <br/>　　　　 return true; <br/>　　 }<br/><br/>　　public<br />
double netPrice() <br/>　　{<br/>　　　　double netPrice=0.;<br/>　　　　Iterator<br />
iter=equipment.iterator();<br/>　　　　for(iter.hasNext())<br/>　　　　　　netPrice+=((Equipment)iter.next()).netPrice();<br/>　　　　return<br />
netPrice;<br/>　　}<br/><br/>　　public double discountPrice() <br/>　　{<br/>　　　　double<br />
discountPrice=0.;<br/>　　　　Iterator<br />
iter=equipment.iterator();<br/>　　　　for(iter.hasNext())<br/>　　　　　　discountPrice+=((Equipment)iter.next()).discountPrice();<br/>　　　　return<br />
discountPrice;<br/>　　}<br/>　　<br/><br/>　　//注意这里，这里就提供用于访问自己组合体内的部件方法。<br/>　　//上面dIsk<br />
之所以没有，是因为Disk是个单独(Primitive)的元素.<br/>　　public Iterator<br />
iter()<br/>　　{<br/>　　　　return equipment.iterator()<br />
;<br/>　　{<br/>　　//重载Iterator方法<br/>　　 public boolean hasNext() { return<br />
i&lt;equipment.size(); }<br/>　　//重载Iterator方法<br/>　　 public Object next()<br/>　　<br />
{<br/>　　　　if(hasNext())<br/>　　　　　　 return equipment.elementAt(i++);<br/>　　　　else<br />
<br/>　　 　　 　 throw new NoSuchElementException();<br/>　　<br />
}<br/>　　<br/><br/>}<br/>&nbsp;<br/><br/>上面CompositeEquipment继承了Equipment,同时为自己里面的对象们提供了外部访问的方法,重载了Iterator,Iterator是Java的Collection的一个接口，是Iterator模式的实现.<br/><br/>我们再看看CompositeEquipment的两个具体类:盘盒Chassis和箱子Cabinet，箱子里面可以放很多东西，如底板，电源盒，硬盘盒等；盘盒里面可以放一些小设备，如硬盘<br />
软驱等。无疑这两个都是属于组合体性质的。<br/><br/>public class Chassi* **tends<br />
CompositeEquipment<br/>{<br/>　　 public Chassis(String name) { super(name); }<br/>　　<br />
public double netPrice() { return 1.+super.netPrice(); }<br/>　　 public double<br />
discountPrice() { return .5+super.discountPrice(); }<br/>} <br/><br/>public class<br />
Cabinet extends CompositeEquipment<br/>{<br/>　　 public Cabinet(String name) {<br />
super(name); }<br/>　　 public double netPrice() { return 1.+super.netPrice();<br />
}<br/>　　 public double discountPrice() { return .5+super.discountPrice();<br />
}<br/>}<br/>&nbsp;<br/><br/>至此我们完成了整个Composite模式的架构。<br/><br/>我们可以看看客户端调用Composote代码:<br/><br/>Cabinet<br />
cabinet=new Cabinet(&quot;Tower&quot;);<br/><br/>Chassis chassis=new Chassis(&quot;PC<br />
Chassis&quot;);<br/>//将PC Chassis装到Tower中<br />
(将盘盒装到箱子里)<br/>cabinet.add(chassis);<br/>//将一个10GB的硬盘装到 PC Chassis<br />
(将硬盘装到盘盒里)<br/>chassis.add(new Disk(&quot;10 GB&quot;));<br/><br/>//调用<br />
netPrice()方法;<br/>System.out.println(&quot;netPrice=&quot;+cabinet.netPrice());<br/>System.out.println(&quot;discountPrice=&quot;+cabinet.discountPrice());<br/><br/>上面调用的方法netPrice()或discountPrice()，实际上Composite使用Iterator遍历了整个树形结构,寻找同样包含这个方法的对象并实现调用执行.<br/><br/>Composite是个很巧妙体现智慧的模式，在实际应用中，如果碰到树形结构，我们就可以尝试是否可以使用这个模式。<br/><br/>以论坛为例，一个版(forum)中有很多帖子(message),这些帖子有原始贴，有对原始贴的回应贴，是个典型的树形结构，那么当然可以使用Composite模式，那么我们进入Jive中看看，是如何实现的.<br/><br/>Jive解剖<br/>在Jive中<br />
ForumThread是ForumMessages的容器container(组合体).也就是说，ForumThread类似我们上例中的<br />
CompositeEquipment.它和messages的关系如图：<br/>[thread]<br/>　　 |- [message]<br/>　　 |-<br />
[message]<br/>　　 　　 |- [message]<br/>　　 　　 |- [message]<br/>　　 　　 　　 |- [message]<br />
<br/><br/>我们在ForumThread看到如下代码：<br/><br/>public inte***ce ForumThread {<br/>　　 &#8230;.<br />
<br/>　　 public void addMessage(ForumMessage parentMessage, ForumMessage<br />
newMessage)<br/>　　 　　 　　 throws UnauthorizedException; <br/><br/>　　 public void<br />
deleteMessage(ForumMessage message)<br/>　　 　　 　　 throws<br />
UnauthorizedException;<br/><br/>　　<br/>　　 public Iterator messages();<br/>　　 　　 &#8230;.<br />
<br/><br/>}<br/>&nbsp;<br/><br/>类似CompositeEquipment, 提供用于访问自己组合体内的部件方法: 增加 删除<br />
遍历.<br/><br/>结合我的其他模式中对Jive的分析，我们已经基本大体理解了Jive论坛体系的框架，如果你之前不理解设计模式，而直接去看Jive源代码，你肯定无法看懂。<br/><br/> <img src='http://blog.donews.com/QQwinterQQ/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> <br/><br/></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.donews.com/QQwinterQQ/archive/2006/06/06/905427.aspx/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>java设计模式之结构模式[Adapter(适配器)]</title>
		<link>http://blog.donews.com/QQwinterQQ/archive/2006/06/06/905425.aspx</link>
		<comments>http://blog.donews.com/QQwinterQQ/archive/2006/06/06/905425.aspx#comments</comments>
		<pubDate>Tue, 06 Jun 2006 15:36:00 +0000</pubDate>
		<dc:creator>winer</dc:creator>
				<category><![CDATA[java]]></category>

		<guid isPermaLink="false">http://blog.donews.com/QQwinterQQ/archive/2006/06/06/905425.aspx</guid>
		<description><![CDATA[定义:将两个不兼容的类纠合在一起使用，属于结构型模式,需要有Adaptee(被适配者)和Adaptor(适配器)两个身份.为何使用?我们经常碰到要将两个没有关系的类组合在一起使用,第一解决方案是：修改各自类的接口，但是如果我们没有源代码，或者，我们不愿意为了一个应用而修改各自的接口。 
怎么办? 
使用Adapter，在这两种接口之间创建一个混合接口(混血儿).如何使用?实现Adapter方式,其实&#34;think in 
Java&#34;的&#34;类再生&#34;一节中已经提到,有两种方式：组合(composition)和继承(inheritance).假设我们要打桩，有两种类：方形桩 
圆形桩.public class SquarePeg{　　public void insert(String 
str){　　　　System.out.println(&#34;SquarePeg 
insert():&#038;q]]></description>
			<content:encoded><![CDATA[<p>定义:<br/>将两个不兼容的类纠合在一起使用，属于结构型模式,需要有Adaptee(被适配者)和Adaptor(适配器)两个身份.<br/><br/>为何使用?<br/>我们经常碰到要将两个没有关系的类组合在一起使用,第一解决方案是：修改各自类的接口，但是如果我们没有源代码，或者，我们不愿意为了一个应用而修改各自的接口。<br />
怎么办?<br />
<br/><br/>使用Adapter，在这两种接口之间创建一个混合接口(混血儿).<br/><br/>如何使用?<br/>实现Adapter方式,其实&quot;think in<br />
Java&quot;的&quot;类再生&quot;一节中已经提到,有两种方式：组合(composition)和继承(inheritance).<br/><br/><br/>假设我们要打桩，有两种类：方形桩<br />
圆形桩.<br/>public class SquarePeg{<br/>　　public void insert(String<br />
str){<br/>　　　　System.out.println(&quot;SquarePeg<br />
insert():&quot;+str);<br/>　　}<br/><br/>}<br/><br/>public class RoundPeg{<br/>　　public void<br />
insertIntohole(String msg){<br/>　　　　System.out.println(&quot;RoundPeg<br />
insertIntoHole():&quot;+msg);<br/>}<br/>}<br/><br/>现在有一个应用,需要既打方形桩,又打圆形桩.那么我们需要将这两个没有关系的类综合应用.假设RoundPeg我们没有源代码,或源代码我们不想修改,那么我们使用Adapter来实现这个应用:<br/><br/>public<br />
class PegAdapter extends SquarePeg{<br/><br/>　　private RoundPeg<br />
roundPeg;<br/><br/>　　public PegAdapter(RoundPeg<br />
peg)(this.roundPeg=peg;)<br/><br/>　　public void insert(String str){<br />
roundPeg.insertIntoHole(str);}<br/><br/>}<br/><br/>在上面代码中,RoundPeg属于Adaptee,是被适配者.PegAdapter是Adapter,将Adaptee(被适配者RoundPeg)和Target(目标SquarePeg)进行适配.实际上这是将组合方法(composition)和继承(inheritance)方法综合运用.<br/><br/>PegAdapter首先继承SquarePeg，然后使用new的组合生成对象方式，生成RoundPeg的对象roundPeg，再重载父类insert()方法。从这里,你也了解使用new生成对象和使用extends继承生成对象的不同,前者无需对原来的类修改,甚至无需要知道其内部结构和源代码.<br/><br/>如果你有些Java使用的经验，已经发现，这种模式经常使用。<br/><br/>进一步使用<br/>上面的PegAdapter是继承了SquarePeg,如果我们需要两边继承，即继承SquarePeg<br />
又继承RoundPeg,因为Java中不允许多继承，但是我们可以实现(implements)两个接口(inte***ce)<br/><br/>public<br />
inte***ce IRoundPeg{<br/>　　public void insertIntoHole(String<br />
msg);<br/><br/>}<br/><br/>public inte***ce ISquarePeg{<br/>　　public void<br />
insert(String str);<br/><br/>}<br/><br/>下面是新的RoundPeg 和SquarePeg,<br />
除了实现接口这一区别，和上面的没什么区别。<br/>public class SquarePeg implements<br />
ISquarePeg{<br/>　　public void insert(String<br />
str){<br/>　　　　System.out.println(&quot;SquarePeg<br />
insert():&quot;+str);<br/>　　}<br/><br/>}<br/><br/>public class RoundPeg implements<br />
IRoundPeg{<br/>　　public void insertIntohole(String<br />
msg){<br/>　　　　System.out.println(&quot;RoundPeg<br />
insertIntoHole():&quot;+msg);<br/>　　}<br/>}<br/><br/>下面是新的PegAdapter,叫做two-way<br />
adapter:<br/><br/>public class PegAdapter implements<br />
IRoundPeg,ISquarePeg{<br/><br/>　　private RoundPeg roundPeg;<br/>　　private SquarePeg<br />
squarePeg;<br/><br/>　　// 构造方法<br/>　　public PegAdapter(RoundPeg<br />
peg){this.roundPeg=peg;}<br/>　　// 构造方法<br/>　　public PegAdapter(SquarePeg<br />
peg)(this.squarePeg=peg;)<br/><br/>　　public void insert(String str){<br />
roundPeg.insertIntoHole(str);}<br/><br/>}<br/><br/>还有一种叫Pluggable<br />
Adapters,可以动态的获取几个adapters中一个。使用Reflection技术，可以动态的发现类中的Public方法。<br/><br/></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.donews.com/QQwinterQQ/archive/2006/06/06/905425.aspx/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>java设计模式之结构模式[Proxy(代理)]&#8211;B</title>
		<link>http://blog.donews.com/QQwinterQQ/archive/2006/06/06/905421.aspx</link>
		<comments>http://blog.donews.com/QQwinterQQ/archive/2006/06/06/905421.aspx#comments</comments>
		<pubDate>Tue, 06 Jun 2006 15:35:00 +0000</pubDate>
		<dc:creator>winer</dc:creator>
				<category><![CDATA[java]]></category>

		<guid isPermaLink="false">http://blog.donews.com/QQwinterQQ/archive/2006/06/06/905421.aspx</guid>
		<description><![CDATA[因此,Forum中各种操作权限是和ForumPermissions定义的用户级别有关系的,作为接口Forum的实现:ForumProxy正是将这种对应关系联系起来.比如,修改Forum的名称,只有论坛管理者或系统管理者可以修改,代码如下:<br/><br/>public 
class ForumProxy implements Forum {<br/><br/>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 = 
permis]]></description>
			<content:encoded><![CDATA[<p>因此,Forum中各种操作权限是和ForumPermissions定义的用户级别有关系的,作为接口Forum的实现:ForumProxy正是将这种对应关系联系起来.比如,修改Forum的名称,只有论坛管理者或系统管理者可以修改,代码如下:<br/><br/>public<br />
class ForumProxy implements Forum {<br/><br/>private ForumPermissions<br />
permissions;<br/>private Forum forum; <br/>this.authorization = authorization;<br />
<br/><br/>public ForumProxy(Forum forum, Authorization<br />
authorization,<br/>ForumPermissions permissions)<br/>{<br/>this.forum =<br />
forum;<br/>this.authorization = authorization;<br/>this.permissions =<br />
permissions;<br/>}<br/><br/>&#8230;..<br/><br/>public void setName(String name) throws<br />
UnauthorizedException,<br/>ForumAlreadyExist***ception<br/>{<br/>　　//只有是系统或论坛管理者才可以修改名称<br/>　　if<br />
(permissions.isSystemOrForumAdmin())<br />
{<br/>　　　　forum.setName(name);<br/>　　}<br/>　　else {<br/>　　　　throw new<br />
UnauthorizedException();<br/>　　}<br/>}<br/><br/>&#8230;<br/><br/>}<br/>&nbsp;<br/><br/>而DbForum才是接口Forum的真正实现,以修改论坛名称为例:<br/><br/>public<br />
class DbForum implements Forum, Cacheable {<br/>&#8230;<br/><br/>public void<br />
setName(String name) throws ForumAlreadyExist***ception<br />
{<br/><br/>　　&#8230;.<br/><br/>　　this.name = name;<br/>　　//这里真正将新名称保存到数据库中<br />
<br/>　　saveToDb();<br/><br/>　　&#8230;.<br/>}<br/><br/><br/>&#8230;<br />
<br/><br/>}<br/>&nbsp;<br/><br/>凡是涉及到对论坛名称修改这一事件,其他程序都首先得和ForumProxy打交道,由ForumProxy决定是否有权限做某一样事情,ForumProxy是个名副其实的&quot;网关&quot;,&quot;安全代理系统&quot;.<br/><br/>在平时应用中,无可避免总要涉及到系统的授权或安全体系,不管你有无意识的使用Proxy,实际你已经在使用Proxy了.<br/><br/>我们继续结合Jive谈入深一点,下面要涉及到工厂模式了,如果你不了解工厂模式,请看我的另外一篇文章:设计模式之Factory<br/><br/>我们已经知道,使用Forum需要通过ForumProxy,Jive中创建一个Forum是使用Factory模式,有一个总的抽象类ForumFactory,在这个抽象类中,调用ForumFactory是通过getInstance()方法实现,这里使用了Singleton(也是设计模式之一,由于介绍文章很多,我就不写了,看这里),getInstance()返回的是ForumFactoryProxy.<br/><br/>为什么不返回ForumFactory,而返回ForumFactory的实现ForumFactoryProxy?<br/>原因是明显的,需要通过代理确定是否有权限创建forum.<br/><br/>在ForumFactoryProxy中我们看到代码如下:<br/><br/>public<br />
class ForumFactoryProxy extends ForumFactory { <br/><br/>　　protected ForumFactory<br />
factory;<br/>　　protected Authorization authorization;<br/>　　protected<br />
ForumPermissions permissions;<br/><br/>　　public ForumFactoryProxy(Authorization<br />
authorization, ForumFactory factory,<br/>　　ForumPermissions<br />
permissions)<br/>　　{<br/>　　　　this.factory = factory;<br/>　　　　this.authorization =<br />
authorization;<br/>　　　　this.permissions = permissions;<br/>　　}<br/><br/>　　public<br />
Forum createForum(String name, String description)<br/>　　　　　　throws<br />
UnauthorizedException,<br />
ForumAlreadyExist***ception<br/>　　{<br/>　　　　//只有系统管理者才可以创建forum <br/>　　　　if<br />
(permissions.get(ForumPermissions.SYSTEM_ADMIN)) {<br/>　　　　　　Forum newForum =<br />
factory.createForum(name, description);<br/>　　　　　　return new ForumProxy(newForum,<br />
authorization, permissions);<br/>　　　　}<br/>　　　　else {<br/>　　　　　　throw new<br />
UnauthorizedException();<br/>　　}<br/>}<br/>&nbsp;<br/><br/>方法createForum返回的也是ForumProxy,<br />
Proxy就象一道墙,其他程序只能和Proxy交互操作.<br/><br/>注意到这里有两个Proxy:ForumProxy和ForumFactoryProxy.<br />
代表两个不同的职责:使用Forum和创建Forum;<br/>至于为什么将使用对象和创建对象分开,这也是为什么使用Factory模式的原因所在:是为了&quot;封装&quot;<br />
&quot;分派&quot;;换句话说,尽可能功能单一化,方便维护修改.<br/><br/>Jive论坛系统中其他如帖子的创建和使用,都是按照Forum这个思路而来的.<br/><br/>以上我们讨论了如何使用Proxy进行授权机制的访问,Proxy还可以对用户隐藏另外一种称为copy-on-write的优化方式.拷贝一个庞大而复杂的对象是一个开销很大的操作,如果拷贝过程中,没有对原来的对象有所修改,那么这样的拷贝开销就没有必要.用代理延迟这一拷贝过程.<br/><br/>比如:我们有一个很大的Collection,具体如hashtable,有很多客户端会并发同时访问它.其中一个特别的客户端要进行连续的数据获取,此时要求其他客户端不能再向hashtable中增加或删除<br />
东东.<br/><br/>最直接的解决方案是:使用collection的lock,让这特别的客户端获得这个lock,进行连续的数据获取,然后再释放lock.<br/>public<br />
void foFetches(Hashtable ht){<br/>　　synchronized(ht){<br/>　　　　//具体的连续数据获取动作..<br />
<br/>　　}<br />
<br/><br/>}<br/><br/>但是这一办法可能锁住Collection会很长时间,这段时间,其他客户端就不能访问该Collection了.<br/><br/>第二个解决方案是clone这个Collection,然后让连续的数据获取针对clone出来的那个Collection操作.这个方案前提是,这个Collection是可clone的,而且必须有提供深度clone的方法.Hashtable就提供了对自己的clone方法,但不是Key和value对象的clone,关于Clone含义可以参考专门文章.<br/>public<br />
void foFetches(Hashtable ht){<br/><br/>　　Hashttable<br />
newht=(Hashtable)ht.clone();<br/><br/>}<br/><br/>问题又来了,由于是针对clone出来的对象操作,如果原来的母体被其他客户端操作修改了,<br />
那么对clone出来的对象操作就没有意义了.<br/><br/>最后解决方案:我们可以等其他客户端修改完成后再进行clone,也就是说,这个特别的客户端先通过调用一个叫clone的方法来进行一系列数据获取操作.但实际上没有真正的进行对象拷贝,直至有其他客户端修改了这个对象Collection.<br/><br/>使用Proxy实现这个方案.这就是copy-on-write操作.<br/><br/>Proxy应用范围很广,现在流行的分布计算方式RMI和Corba等都是Proxy模式的应用.<br/><br/><br/></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.donews.com/QQwinterQQ/archive/2006/06/06/905421.aspx/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

