8

3月

Subversion的安装

[2008-3-8 20:46 | 分类: 软件编程 | by Wudi ]
吃完饭就开始装了,可能原来想的太麻烦,根本不需要用到apache
具体方法如下
,软件下载
下载Subversion服务器程序。
到官方网站的下载二进制安装文件,来到二进制包下载部分,找到 Windows NT, 2000, XP and 2003部分,然后选择" this directory ",这样我们可以看到许多下载的内容,目前可以下载 svn-1.4.0-setup.exe 。

下载Subversion的Windows客户端TortoiseSVN。
TortoiseSVN是扩展Windows Shell的一套工具,可以看作Windows资源管理器的插件,安装之后Windows就可以识别Subversion的工作目录。
官方网站是TortoiseSVN ,下载方式和前面的svn服务器类似,在Download页面的我们可以选择下载的版本,目前的最高稳定版本的安装文件为TortoiseSVN-1.4.0.7501-win32-svn-1.4.0.msi。

2,服务器和客户端安装
服务器安装,直接运行svn-1.4.0-setup.exe ,根据提示安装即可,这样我们就有了一套服务器可以运行的环境。

安装TortoiseSVN,同样直接运行TortoiseSVN-1.4.0.7501-win32-svn-1.4.0.msi按照提示安装即可,不过最后完成后会提示是否重启,其实重启只是使svn工作拷贝在windows中的特殊样式生效,与所有的实际功能无关,这里为了立刻看到好的效果,还是重新启动机器。
  

3,建立版本库(Repository)
运行Subversion服务器需要首先要建立一个版本库(Repository),可以看作服务器上存放数据的数据库,在安装了Subversion服务器之后,可以直接运行,如:

svnadmin create E:\svndemo\repository就会在目录E:\svndemo\repository下创建一个版本库。

我们也可以使用TortoiseSVN图形化的完成这一步:
在目录E:\svndemo\repository下"右键->TortoiseSVN->Create Repository here...“, 然后可以选择版本库模式, 这里使用默认即可, 然后就创建了一系列目录和文件。


4,配置用户和权限
来到E:\svndemo\repository\conf目录,修改svnserve.conf:
# [general]
# password-db = passwd
改为:
[general]
password-db = passwd 然后修改同目录的passwd文件,去掉下面三行的注释:
# [users]
# harry = harryssecret
# sally = sallyssecret
最后变成:
[users]
harry = harryssecret
sally = sallyssecret



5,运行独立服务器
在任意目录下运行:
svnserve -d -r E:\svndemo\repository 我们的服务器程序就已经启动了。注意不要关闭命令行窗口,关闭窗口也会把svnserve停止。


6,初始化导入
来到我们想要导入的项目根目录,在这个例子里是E:\svndemo\initproject,目录下有一个readme.txt文件:


右键->TortoiseSVN->Import...
URL of repository输入“svn://localhost/”
ok
完成之后目录没有任何变化,如果没有报错,数据就已经全部导入到了我们刚才定义的版本库中。

需要注意的是,这一步操作可以完全在另一台安装了TortoiseSVN的主机上进行。例如运行svnserve的主机的IP是133.96.121.22,则URL部分输入的内容就是“svn://133.96.121.22/”。


7,基本客户端操作
取出版本库到一个工作拷贝:
来到任意空目录下,在本例中是E:\svndemo\wc1,运行右键->Checkout,在URL of repository中输入svn://localhost/,这样我们就得到了一份工作拷贝。
在工作拷贝中作出修改并提交:
打开readme.txt,作出修改,然后右键->Commit...,这样我们就把修改提交到了版本库,我们可以运行。

察看所作的修改:
readme.txt上右键->TortoiseSVN->Show Log,这样我们就可以看到我们对这个文件所有的提交。在版本1上右键->Compare with working copy,我们可以比较工作拷贝的文件和版本1的区别。

7

3月

接着上回,我们首先分析的是qq空间的几个常有初始变量的用途。
引用

var g_Src_Domain="u.qzone.qq.com", //设置QQ空间的服务器地址
g_dns_name='',//QQ空间的自定义域名地址
imgcacheDomain='imgcache.qq.com',//QQ空间图片缓存服务器地址
g_iUin=7777777,//QQ号
_s_=new Date(),//获取当前时间
g_JSON=1;//JSON 作为一种更轻、更友好的 Web services客户端的格式(多采用浏览器的形式或访问 REST风格 Web服务的Ajax应用程序的形式)引起了 Web 服务供应商的注意。



接下来就是调用http://u.qzone.qq.com/cgi-bin/entry_js.cgi?uin=7777777,此文件的主要逻辑如下:
1.如果对应的uin也就是QQ号尚未开通QQ空间的话,脚本执行如下代码
引用
top.location.href='http://imgcache.qq.com/qzone/web/load.htm';

意思为跳入只显示“本用户还未激活QQ空间”的页面。

2.如果对应的uin能找到QQ空间,就根据uin读取数据库数据,cgi显示的数据如下,并做分析:

引用

var g_XMLReqFlag= 0x00000000;
var g_iLoginUin = 7190439;//访问人的QQ号
var g_iEntryRight = 0;
var g_iRevertRight = 0;
var g_iActFlag =1;
var g_iUserMark=6;
var g_UserBitmap="0201000104100001";
var g_Main_Domain= "users.qzone.qq.com";//QQ空间用户主服务器地址
var g_My_Main_Domain= "users.qzone.qq.com";//同上
var g_Music_Domain= "qzone-music.qq.com"; //音乐服务器地址
var g_My_Music_Domain= "qzone-music.qq.com"; //同上
var g_Photo_Domain= "photo.qq.com"; //图片服务器
var g_Static_Photo_Domain= "p" + (g_iUin%13+1) + ".photo.qq.com";//这里很搞笑,腾讯的程序员用了个取幕的方法随机了图片服务器,具体方法是将QQ号取除以13的余数再加一。
var g_MsgBoard_Version = 2;
var g_MsgBoard_Domain="m.qzone.qq.com"; //消息服务器
var g_Emotion_Version = 2;
var g_Emotion_Domain = "e.qzone.qq.com"; //表情服务器
var g_Blog_Version = 2007;
var g_My_Blog_Version = 2007;
var g_NewBlog_Domain = "b.qzone.qq.com"; //日志服务器
var g_Statistic_Domain = "g.qzone.qq.com"; //
var g_Property= "GoRE";
var g_TimeStamp=1204772986; //当前时间
var g_nc=1;

g_Configuration是一个大数字,定义空间样式的用途。style的作用应该是设置对应的类型的,我刚刚搜索了下style的枚举值:
  1 : //皮肤     2 : //挂件     3 : //banner     4 : //鼠标方案     5 : //漂浮物     6 : //播放器     7 : //个性花藤     8 : //个性标志(cancel)    9 : //大头贴(小)(cancel)     11 : //大头贴(大)     12 : //公告栏     13 : //自定义导航栏    14 : //欢迎Flash     15 : //礼品盒     16 : //Flash 挂件     49: //QCC皮肤  
其他一下参数的作用:
itemno  皮肤编号:在商城里选择喜欢的皮肤,点鼠标右键看属性即可查到,通常是5位阿拉伯数字
posx  背景水平坐标,只要设置为0即可
posy  景垂直坐标,设置为80
width  背景宽度,只要设置为0即可
height  背景高度,只要设置为0即可
zIndex  背景所在层编号,请设置为90
notPlayFlash  这个参数好象不起作用,设为0或者省略掉也行
g_Configuration={style:1,version:4,fullMode:1,frameStyle:0,simpleMode:0,items:[{type:1,itemno:22895,posx:0,posy:80,width:0,height:0,zindex:94},{type:19,itemno:15330,posx:0,posy:0,width:0,height:0,zindex:10000},{type:5,itemno:66,posx:0,posy:0,width:3,height:0,zindex:0},{type:20,itemno:20630,posx:0,posy:0,width:0,height:0,zindex:0},{type:14,itemno:23521,posx:0,posy:0,width:0,height:0,zindex:0},{type:22,itemno:22469,posx:0,posy:0,width:0,height:0,zindex:0},{type:13,itemno:22647,posx:809,posy:572,width:100,height:500,zindex:0},{type:6,itemno:22222,posx:247,posy:70,width:0,height:0,zindex:100},{type:17,itemno:22145,posx:43,posy:1431,width:0,height:0,zindex:100},{type:16,itemno:23452,posx:-18,posy:983,width:200,height:300,zindex:100} ],windows:[{type:95,itemno:7,posx:310,posy:859,width:355,height:285,zindex:0},{type:99,itemno:5933213,posx:7,posy:395,width:713,height:805,zindex:0},{type:99,itemno:5933217,posx:88,posy:529,width:158,height:50,zindex:0},{type:99,itemno:5933215,posx:88,posy:551,width:158,height:229,zindex:0},{type:99,itemno:5933214,posx:7,posy:1,width:658,height:358,zindex:0},{type:95,itemno:2,posx:285,posy:37,width:355,height:285,zindex:0},{type:94,itemno:1,posx:34,posy:40,width:175,height:285,zindex:0},{type:99,itemno:5933204,posx:296,posy:347,width:152,height:138,zindex:0} ]};


下回分析G4.1.js核心文件。

6

3月

QQ空间架构简析

[2008-3-6 22:00 | 分类: 软件编程 | by Wudi ]
晚上进你空间,无意想到研究一下qq空间的核心架构,就打算在写一篇分析一下。
引用

< html  >< meta >< meta http-equiv="Content-Type" content="text/html;charset=gb2312" />< script>var g_Src_Domain="u.qzone.qq.com",g_dns_name='xxxxx',imgcacheDomain='imgcache.qq.com',g_iUin=7777777,_s_=new Date(),g_JSON=1;< script src="http://u.qzone.qq.com/cgi-bin/entry_js.cgi?uin=7777777">< script src="http://imgcache.qq.com/ac/qzone/G4.1.js">< script >if (typeof G41Loaded=="undefined") location="http://qzone.qq.com/new_help/error.htm"< /script>< noscript >< img src="http://imgcache.qq.com/qzone/noscript.gif" >< /noscript >< /html  >


主要通过javascript,第一步预先得到空间的最基本信息,第二部调用http://u.qzone.qq.com/cgi-bin/entry_js.cgi,从数据库得到空间样式,第三部初始化G4.1(我觉得4.1应该是空间核心代码的版本号),js里的代码全是空间的脚本,以及HTML代码。最后是判断是否支持空间脚本。今天先简单的说这些,下回详解。

6

3月

社区的产品和运营(转)

[2008-3-6 19:44 | 分类: IT世界 | by Wudi ]
全文转自http://blog.edooon.com/
 前两周应摇篮网CEO高翔和胖葫芦创始人只说的邀请,分别和他们的团队交流了一下社区的产品和运营经验。在这里把讲的内容整理出来,不是很系统,也不是很全面,主要是我自己在运营社区网站时的一些经验心得,和大家分享交流一下。

  一个网站基本上由技术、产品和运营这三大块组成,每块可能有更细致的划分,但基本上离不开这个大的框架。很多人讨论过,对于一个网站,是技术重要?是产品重要?还是运营重要?各执一词,没有答案。我的理解大概是下面几方面:

  技术是骨架,产品是血液,运营是肌肉。如果把网站比喻成人体的话,我会这样来类比各部分的机能:技术好比是人体的骨架,决定了网站能做到什么样的高度。这个骨架一定要高大,而且骨质要硬,不能缺“钙”。产品是人体的血液,表面上看不太出来,但它决定了网站内在的潜力。这个网站“造血”的能力是否强大,直接影响到它是否能有更高的投入产出比。这是一个网站的动力之源。运营是人体的肌肉,看网站是否足够强壮,就看它的运营能力。有很多矮个子也可以锻炼得非常强壮,而有的高个子却非常瘦弱,这是运营能力的区别。但也有一种情况是假象,那就是“肥胖”,看上去块头很大,实际上很不健康。

  三者需要很好的平衡。当然,每个网站都会希望自己技术、产品和运营都异常强大,这只是美好的愿望。实际情况是,每个网站都会有自己的长处和短项。但这就好比是一张凳子的三条腿,只有尽量去平衡,才能坐得稳。在三者本身不平衡的情况下,就需要很好地区分事情的优先级,调配资源,人为地来达到一个平衡的目的,这样网站才能获得比较良性而且快速的增长。

  短期看的是长处,长期看的是短处。这句话的原始出处是李玉琢的《我与商业领袖的合作与冲突》一书,“短期看,企业家比的是长处;长期看,企业家比的是短处。”我觉得很有道理,就借用到这里。当网站规模还比较小的时候,拥有一个优势就足以让你脱颖而出。比如BuyRen(现在的易购)早期基本没有技术和产品可言,完全靠的是运营,也获得了一定层面上的成功。但这种成功是有瓶颈的,需要有新的优势来弥补不足。当网站发展到一定的规模,任何一个细节的不足,都可能导致和对手竞争的失败。所以任何时候都需要认清自己的优势和劣势,不能因为短期的成功而忽略了长期的发展,需要未雨绸缪,提前在短板上下功夫,做准备。

  所有的目的:满足用户需求。无论是技术,还是产品和运营,所有要实现的目的无非就是一个,满足用户的需求。只有满足了用户的需求,网站本身才有价值,技术、产品和运营才有存在的必要。所以技术追求的不是新、产品追求的不是酷、运营追求的不是快,而是能在多大程度上满足用户的需求,花最小的代价满足用户的需求。同时,也只有当技术、产品和运营都非常了解用户的需求,这个网站获得成功的几率才会大。我看到现在的普遍情况是:运营非常了解用户的需求,产品比较了解用户的需求,技术几乎不或很少了解用户的需求,这是需要提高的地方。

  实用&平衡&服务。怎么满足用户的需求?侧重点是不同的。我认为技术的重点是实用,没有什么比一看就知道用,而且流程清晰,基本不会出错的网站更好的了。现在对新技术的盲目使用已经到了令人吃惊的地步,很多用户对突然浮出来的窗口茫然失措,他哪里会知道这是最流行的AJAX,他只会怀疑是不是中病毒了。好的功能和技术不能用在错误的地方。产品的首要任务是平衡。任何人任何网站都不会拥有足够的资源,那么就需要产品去平衡这永远匮乏的资源,并将之梳理清晰,排列优先级,根据功能的价值、开发的时间、人员安排等等因素来综合考虑并实施。运营需要突出的是服务。在新用户需要帮助的时候马上提示他,在用户提出疑问的时候尽快回复他,不给用户带来任何会让他产生挫折感的操作,调动整个社区用户互帮互助的积极性,形成良好的社区文化,这都是良好服务质量的表现。这点上,创业团队永远比公司运作得要强很多,实质上还是一个人员积极性和投入程度的问题。

 说起豆瓣,校内这些国内非常优秀的社区网站,大家谈得最多的还是他们的产品。因为涉及到用户之间的互动沟通,涉及到内容的呈现方式,涉及到操作的各种流程,社区网站的产品重要性会远大于一般的网站,而且往往会是成败的关键。

  我认为社区网站最重要的是需要有一个自生长机制,圈网的CEO曹剑把它称之为内驱力,含义大概是相同的。国内刚开始讨论WEB2.0的时候人有人举了一个非常生动的例子来解释WEB1.0和WEB2.0的区别。他说,一个WEB1.0的网站,只要一天没有人上班,这个网站基本就很难保持它的竞争力;而一个WEB2.0网站,即使一周没人上班,也能运转得很好。这里WEB1.0和WEB2.0的区别,是内容的产生、呈现和管理方式。我所理解的WEB2.0,可能需要在这个基础上再加一条:有一种规则象一只无形的手,来推动用户更积极地产生、呈现和管理内容,同时形成更复杂的社会关系。这也就是我为什么把产品比作“血液”的原因。这种内在的,源源不断的潜力,可以转化为网站飞速发展的动力。

  可能这么说还过于生涩,举个例子加以说明,是我曾经跟蓝色提起过的蓝色理想的发展模式。技术类的社区站点有个特色,不断地有新人加入,有高手离开。就好像一所学校,大家在这里学到想学的东西,然后离开。任何一个技术社区,高手的数量有限,曲高必然和寡,他们已经很难得到自己想要的东西,也没有过多的时间来帮助其他人,即使帮助了,也很难获得什么回报(很现实的想法,但事实如此)。蓝色理想在这块做得还算非常优秀,通过社区文化的建立笼络住一批高手,虽然他们没有离开,但是活跃性还是有限。那么这时候就需要有一个机制(或者说规则)来满足不同层次用户的需求,来激励他们,往你想让他们去的方向引导。

  整个规则的核心是:记录你在网站上的一切活动,并用科学的测评方法来反映你的价值。这个核心可以套用到其他所有的社区网站。具体是通过注册用户在网站上贡献的内容(比如在蓝色理想上有作品库、论坛、BLOG等栏目),来获得其他用户的评分,按照各项技能指标的得分来反映用户素质水平(比如按编程、WEB标准、PS、Flash等技能来区分)。整合个人信息和测评之后和人才系统结合起来,企业可以很轻松地了解到一个用户的技能水平大概是什么程度,同时还可以看到他以往的作品和在社区里发表的内容,立体地展示了他的综合素质。这样不但能在社区内获得更高的荣誉体现自身价值,也能获得更多企业的关注从而得到更好的职业发展,无疑会更好地调动用户的积极性来推动社区的发展。在用户层面来说,会吸引更多用户、贡献更多内容、获得间接评价、体现自身价值;在网站层面来说,会增加网站内容、提高网站访问量、扩大行业影响力和增进网站的商业价值。

  如何去建立这个规则,并让这个规则产生直接而且有效的结果,我的思路是这样的。首先要发现用户的需求。蓝色理想的用户有展示作品的需求,有希望获得企业亲睐的需求;饭统网的用户有发掘特色餐馆,有获得更高折扣的需求;易购网的用户有在网上找到喜欢的商品,有以最低价格购买的需求;各个网站用户的需求会有所差异。而我们需要通过调查,沟通和观察等形式去发掘这些需求,并将之分类整理,结合网站自身业务发展和客户的需求排列优先级。其次需要去尝试这些需求,前面的可能更多的还只是一种推论,未经证实会被大部分的用户所采纳。比如今天饭统网的臧总说他们利用积分换餐券的活动就非常冷清,其实也很好理解,现在大部分的餐馆都会在消费后免费赠送餐券,那又何必再花积分来换呢?这种需求可能在尝试后发现并不可行。一定要经过尝试,经过数据的统计和分析,才能把需求整合到规则中去。然后需要整合客户的资源来满足用户的需求。大部分的社区网站还是一个平台,可以通过一些活动把用户和客户整合到一起,就好比搭一座桥把两个岛屿联系在一起。易购网的两周年庆典活动是一个典型的例子。最后就是要客观地反映用户的价值。哪些用户对于网站来说是价值更大的,需要有一个东西来量化,我们称之为积分制度。通过积分制度来衡量用户的价值,整合客户资源来正确地满足用户的需求。这就是规则的核心。

足球站长群里讨论的时候别人推荐看的一篇文章,写的很好,也很对,感触很深。
最近一直在考虑社区的核心在哪,也许这篇给了我更多的想法。

3

3月

常用正则表达式

[2008-3-3 22:32 | 分类: 软件编程 | by Wudi ]

^\d+$   //非负整数(正整数 + 0)

^[0-9]*[1-9][0-9]*$   //正整数

^((-\d+)|(0+))$   //非正整数(负整数 + 0)

^-[0-9]*[1-9][0-9]*$   //负整数

^-?\d+$     //整数

^\d+(\.\d+)?$   //非负浮点数(正浮点数 + 0)

^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$   //正浮点数

^((-\d+(\.\d+)?)|(0+(\.0+)?))$   //非正浮点数(负浮点数 + 0)

^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$   //负浮点数

^(-?\d+)(\.\d+)?$   //浮点数

^[A-Za-z]+$   //由26个英文字母组成的字符串

^[A-Z]+$   //由26个英文字母的大写组成的字符串

^[a-z]+$   //由26个英文字母的小写组成的字符串

^[A-Za-z0-9]+$   //由数字和26个英文字母组成的字符串

^\w+$   //由数字、26个英文字母或者下划线组成的字符串

^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$     //email地址

^[a-zA-z]+://(\w+(-\w+)*)(\.(\w+(-\w+)*))*(\?\S*)?$   //url


//这里是判断YYYY-MM-DD这种格式的,基本上把闰年和2月等的情况都考虑进去了
^((((1[6-9]|[2-9]\d)\d{2})-(0?[13578]|1[02])-(0?[1-9]|[12]\d|3[01]))|(((1[6-9]|[2-9]\d)\d{2})-(0?[13456789]|1[012])-(0?[1-9]|[12]\d|30))|(((1[6-9]|[2-9]\d)\d{2})-0?2-(0?[1-9]|1\d|2[0-8]))|(((1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))-0?2-29-))$



//下面的是加了时间验证的

^((((1[6-9]|[2-9]\d)\d{2})-(0?[13578]|1[02])-(0?[1-9]|[12]\d|3[01]))|(((1[6-9]|[2-9]\d)\d{2})-(0?[13456789]|1[012])-(0?[1-9]|[12]\d|30))|(((1[6-9]|[2-9]\d)\d{2})-0?2-(0?[1-9]|1\d|2[0-8]))|(((1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))-0?2-29-)) (20|21|22|23|[0-1]?\d):[0-5]?\d:[0-5]?\d$


很久前自己半写办整理的,以后慢慢扩充,但觉得对大家是有帮助得。

1

3月

关于SEO

[2008-3-1 20:20 | 分类: 软件编程 | by Wudi ]
1.什么是SEO?Search Engine Optimization,搜索引擎优化,简单的说,SEO是一种让网站从百度GOOGLE等搜索引擎获得更多潜在客户的网络营销方式。SEO的主要工作是通过了解各类搜索引擎如何抓取互联网页面、如何进行索引以及如何确定其对某一特定关键词的搜索结果排名等技术,来对网页进行相关的优化,使其提高搜索引擎排名,从而提高网站访问量,最终提升网站的销售能力或宣传能力的技术。
2.最早接触SEO是在做一些无趣的垃圾站(意为没实质内容纯粹是为了赚钱的网站,站长们都这么称呼)的时候用到,因为数据是采集的,整个网站就是一个N叉树,只等着给搜索引擎搜索到,然后通过SEO将个别关键字做上去,这样流量就来了广告收入也来了,起初的SEO很简单,关键字累积,Title,description,keywords等等,但往往效果不是很好,只能通过多撒网的办法来弥补,IP也只有上千,而且很容易给搜索引擎K(K:Kill的意思)。
3.真正做专业类型的网站加上适当的SEO反而会起到意想不到的效果,在做论坛的后,我无意的去提交了dmoz(Open Directory,开放式目录,各大搜索引擎都会去收录,被收录的网站在搜索引擎的权重较高,但也望望比较难收录,里面的编辑都是义务得),在不到1个月就给收录,给收录后不久pr值(pagerank:google对网站页面的评分)就变成了4(目前变成了3,也许是算法变了,也许是网站质量下降了,具体为什么不得而知)。加上域名的优化,因为域名包含关键字本事就是一个优化,加上内容的优化,顺理成章的在关键的时候排到了该关键字的第一页(现在是第二页,下面细说),也为此带来了不少的IP。
4.刚刚说道现在是第二页,我就不能不说一下现在搜索引擎的自我优化,自我优化在我的意思里是指搜索引擎对本事的优化,利用本事的资源将关键字做给自己或者自己的合作伙伴,这两种都是一个目的--获取利用,前者是用来推广自己的网站,例如百度的百科,百度的视频(百度我说你坏话你别K我哦 - -!)这方面我觉得google做的比较好,百度结果页第一页前两名竟然都是搜索引擎本事的,相当的霸道;而后者为给合作伙伴的,合作伙伴又分为两种网站间的合作,比如什么热门关键字都会有sina 163一腿这样的道理,另外一直是搜索引擎本事提供的推广,用来推广自己的关键字,越热门的越值钱或越值钱的关键字越值钱。
5.搜索引擎的人为因素,有些网站被K,不可能是算法或服务器自动K的,而大部分是人为因素,比如:反动的,反ZF的或影响不好的,都或和谐掉。再者就是垃圾站,我上面说的,内容是雷同的、没实质内容的。
6.SEO其实不难,但也可以认为很难,在这样页面优化,搜索优化等等都是次要的,最关键的还是把内容做上去,一个好的网站是不需要SEO的,而是需要CEO的。

29

2月

设计模式

[2008-2-29 21:32 | 分类: 软件编程 | by Wudi ]
     设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。

      毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样。

      GoF的“设计模式”是第一次将设计模式提升到理论高度,并将之规范化,本书提出了23种基本设计模式,自此,在可复用面向对象软件的发展过程中,新的大量的设计模式不断出现。

一、设计模式和框架

      现在,可复用面向对象软件系统现在一般划分为三大类:应用程序工具箱和框架(Framework),我们平时开发的具体软件都是应用程序;Java的API属于工具箱;而框架是构成一类特定软件可复用设计的一组相互协作的类。EJB(EnterpriseJavaBeans)是Java应用于企业计算的框架.

      框架通常定义了应用体系的整体结构类和对象的关系等等设计参数,以便于具体应用实现者能集中精力于应用本身的特定细节。框架主要记录软件应用中共同的设计决策,框架强调设计复用,因此框架设计中必然要使用设计模式.

      另外,设计模式有助于对框架结构的理解,成熟的框架通常使用了多种设计模式,如果你熟悉这些设计模式,毫无疑问,你将迅速掌握框架的结构,我们一般开发者如果突然接触EJBJ2EE等框架,会觉得特别难学,难掌握,那么转而先掌握设计模式,无疑是给了你剖析EJB或J2EE系统的一把利器。

二、设计模式的原则

   近年来,大家都开始注意设计模式。那么,到底我们为什么要用设计模式呢?这么多设计模式为什么要这么设计呢?说实话,以前我还真没搞清楚。就是看大家一口一个"Design pattern",心就有点发虚。于是就买了本"四人帮"的设计模式,结果看得似懂非懂:看得时候好像是懂了,过一会就忘了。可能是本人比较"愚钝"吧:))最近,有了点感悟。"独乐不如众乐",与大家分享一下,还望指教!
    为什么要提倡"Design Pattern"呢?根本原因是为了代码复用,增加可维护性。那么怎么才能实现代码复用呢?OO界有前辈的几个原则:"开-闭"原则(Open Closed Principal)、里氏代换原则、合成复用原则。设计模式就是实现了这些原则,从而达到了代码复用、增加可维护性的目的。

    1、"开-闭"原则

    此原则是由"Bertrand Meyer"提出的。原文是:"Software entities should be open for extension,but closed for modification"。就是说模块应对扩展开放,而对修改关闭。模块应尽量在不修改原(是"原",指原来的代码)代码的情况下进行扩展。那么怎么扩展呢?我们看工厂模式"factory pattern":假设中关村有一个卖盗版盘和正版片的小子,我们给他设计一"光盘销售管理软件"。我们应该先设计一"光盘"接口。
而盗版盘和正版片是其子类。小子通过"DiscFactory"来管理这些光盘。代码为:

public class DiscFactory{
    public static 光盘 getDisc(String name){
       return (光盘)Class.forName(name).getInstance();
    }
}
有人要买盗版盘,怎么实现呢?

public class 小子{
    public static void main([] args){
        光盘 d=DiscFactory.getDisc("盗版盘");
        光盘.卖();
    }
}

    如果有一天,这小子良心发现了,开始卖正版软件。没关系,我们只要再创建一个"光盘"的子类"正版软件"就可以了。不需要修改原结构和代码。怎么样?对扩展开发,对修改关闭。"开-闭原则"
    工厂模式是对具体产品进行扩展,有的项目可能需要更多的扩展性,要对这个"工厂"也进行扩展,那就成了"抽象工厂模式"。

    2、里氏代换原则

里氏代换原则是由"Barbara Liskov"提出的。如果调用的是父类的话,那么换成子类也完全可以运行。比如:
       光盘 d=new 盗版盘();
       d.卖();
    现在要将"盗版盘"类改为"正版片"类,没问题,完全可以运行。Java编译程序会检查程序是否符合里氏代换原则。还记得java继承的一个原则吗?子类overload方法的访问权限不能小于父类对应方法的访问权限。比如"光盘"中的方法"卖"访问权限是"public",那么"盗版盘"和"正版片"中的"卖"方法就不能是package或private,编译不能通过。为什么要这样呢?你想啊:如果"盗版盘"的"卖"方法是private。那么下面这段代码就不能执行了:
            光盘 d=new 盗版盘();
            d.卖();
可以说:里氏代换原则是继承复用的一个基础。

    3、合成复用原则

    就是说要少用继承,多用合成关系来实现。我曾经这样写过程序:有几个类要与数据库打交道,就写了一个数据库操作的类,然后别的跟数据库打交道的类都继承这个。结果后来,我修改了数据库操作类的一个方法,各个类都需要改动。"牵一发而动全身"!面向对象是要把波动限制在尽量小的范围。


    在Java中,应尽量针对Interface编程,而非实现类。这样,更换子类不会影响调用它方法的代码。要让各个类尽可能少的跟别人联系,"不要与陌生人说话"。这样,城门失火,才不至于殃及池鱼。扩展性和维护性才能提高

    理解了这些原则,再看设计模式,只是在具体问题上怎么实现这些原则而已。张无忌学太极拳,忘记了所有招式,打倒了"玄幂二老",所谓"心中无招"。设计模式可谓招数,如果先学通了各种模式,又忘掉了所有模式而随心所欲,可谓OO之最高境界。呵呵,搞笑,搞笑!(JR)

      4 依赖倒转原则

抽象不应该依赖与细节,细节应当依赖与抽象。

要针对接口编程,而不是针对实现编程。

传递参数,或者在组合聚合关系中,尽量引用层次高的类。

主要是在构造对象时可以动态的创建各种具体对象,当然如果一些具体类比较稳定,就不必在弄一个抽象类做它的父类,这样有画舌添足的感觉

      5 接口隔离原则

定制服务的例子,每一个接口应该是一种角色,不多不少,不干不该干的事,该干的事都要干

      6 抽象类

抽象类不会有实例,一般作为父类为子类继承,一般包含这个系的共同属性和方法。

注意:好的继承关系中,只有叶节点是具体类,其他节点应该都是抽象类,也就是说具体类

是不被继承的。将尽可能多的共同代码放到抽象类中。

      7 迪米特法则

最少知识原则。不要和陌生人说话。

三、一个模式的四个基本要素

      设计模式使人们可以更加简单方便地复用成功的设计和体系结构。将已证实的技术表述成设计模式也会使新系统开发者更加容易理解其设计思路。


1. 模式名称(pattern name)

      一个助记名,它用一两个词来描述模式的问题、解决方案和效果。命名一个新的模式增加了我们的设计词汇。设计模式允许我们在较高的抽象层次上进行设计。基于一个模式词汇表,我们自己以及同事之间就可以讨论模式并在编写文档时使用它们。模式名可以帮助我们思考,便于我们与其他人交流设计思想及设计结果。找到恰当的模式名也是我们设计模式编目工作的难点之一。

2. 问题(problem)

      描述了应该在何时使用模式。它解释了设计问题和问题存在的前因后果,它可能描述了特定的设计问题,如怎样用对象表示算法等。也可能描述了导致不灵活设计的类或对象结构。有时候,问题部分会包括使用模式必须满足的一系列先决条件。

3. 解决方案(solution)

      描述了设计的组成成分,它们之间的相互关系及各自的职责和协作方式。因为模式就像一个模板,可应用于多种不同场合,所以解决方案并不描述一个特定而具体的设计或实现,而是提供设计问题的抽象描述和怎样用一个具有一般意义的元素组合(类或对象组合)来解决这个问题。

4. 效果(consequences)

      描述了模式应用的效果及使用模式应权衡的问题。尽管我们描述设计决策时,并不总提到模式效果,但它们对于评价设计选择和理解使用模式的代价及好处具有重要意义。软件效果大多关注对时间和空间的衡量,它们也表述了语言和实现问题。因为复用是面向对象设计的要素之一,所以模式效果包括它对系统的灵活性、扩充性或可移植性的影响,显式地列出这些效果对理解和评价这些模式很有帮助。

四、一些基本的设计模式

Abstract Factory:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

Adapter:将一个类的接口转换成客户希望的另外一个接口。A d a p t e r模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

Bridge:将抽象部分与它的实现部分分离,使它们都可以独立地变化。

Builder:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

Chain of Responsibility:为解除请求的发送者和接收者之间耦合,而使多个对象都有机会处理这个请求。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它。

Command:将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可取消的操作。

Composite:将对象组合成树形结构以表示“部分-整体”的层次结构。它使得客户对单个对象和复合对象的使用具有一致性。

Decorator:动态地给一个对象添加一些额外的职责。就扩展功能而言, 它比生成子类方式更为灵活。

Facade:为子系统中的一组接口提供一个一致的界面, F a c a d e模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。

Factory Method:定义一个用于创建对象的接口,让子类决定将哪一个类实例化。Factory Method使一个类的实例化延迟到其子类。

Flyweight:运用共享技术有效地支持大量细粒度的对象。

Interpreter:给定一个语言, 定义它的文法的一种表示,并定义一个解释器, 该解释器使用该表示来解释语言中的句子。

Iterator:提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示。

Mediator:用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。

Memento:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到保存的状态。

Observer:定义对象间的一种一对多的依赖关系,以便当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动刷新。

Prototype:用原型实例指定创建对象的种类,并且通过拷贝这个原型来创建新的对象。

Proxy:为其他对象提供一个代理以控制对这个对象的访问。

Singleton:保证一个类仅有一个实例,并提供一个访问它的全局访问点。

State:允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它所属的类。

Strategy:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。本模式使得算法的变化可独立于使用它的客户。

Template Method:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。Template Method使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

Visitor:表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。


    创建型 结构型 行为型
类 Factory Method  Adapter_Class  Interpreter
Template Method  
对象 Abstract Factory
Builder
Prototype
Singleton  Adapter_Object
Bridge
Composite
Decorator
Facade
Flyweight
Proxy  Chain of Responsibility
Command
Iterator
Mediator
Memento
Observer
State
Strategy
Visitor  
概览  


名称 Factory Method
结构  
意图 定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method 使一个类的实例化延迟到其子类。
适用性 当一个类不知道它所必须创建的对象的类的时候。
当一个类希望由它的子类来指定它所创建的对象的时候。
当类将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将哪一个帮助子类是代理者这一信息局部化的时候。

名称 Abstract Factory
结构  
意图 提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
适用性 一个系统要独立于它的产品的创建、组合和表示时。
一个系统要由多个产品系列中的一个来配置时。
当你要强调一系列相关的产品对象的设计以便进行联合使用时。
当你提供一个产品类库,而只想显示它们的接口而不是实现时。

名称 Builder
结构  
意图 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
适用性 当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时。
当构造过程必须允许被构造的对象有不同的表示时。

名称 Prototype
结构  
意图 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
适用性 当要实例化的类是在运行时刻指定时,例如,通过动态装载;或者
为了避免创建一个与产品类层次平行的工厂类层次时;或者
当一个类的实例只能有几个不同状态组合中的一种时。建立相应数目的原型并克隆它们可能比每次用合适的状态手工实例化该类更方便一些。

名称 Singleton
结构  
意图 保证一个类仅有一个实例,并提供一个访问它的全局访问点。
适用性 当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时。
当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需更改代码就能使用一个扩展的实例时。

名称 Adapter
结构
  
意图 将一个类的接口转换成客户希望的另外一个接口。A d a p t e r 模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
适用性 你想使用一个已经存在的类,而它的接口不符合你的需求。
你想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类(即那些接口可能不一定兼容的类)协同工作。
(仅适用于对象A d a p t e r )你想使用一些已经存在的子类,但是不可能对每一个都进行子类化以匹配它们的接口。对象适配器可以适配它的父类接口。

名称 Bridge
结构  
意图 将抽象部分与它的实现部分分离,使它们都可以独立地变化。
适用性 你不希望在抽象和它的实现部分之间有一个固定的绑定关系。例如这种情况可能是因为,在程序运行时刻实现部分应可以被选择或者切换。
类的抽象以及它的实现都应该可以通过生成子类的方法加以扩充。这时B r i d g e 模式使你可以对不同的抽象接口和实现部分进行组合,并分别对它们进行扩充。
对一个抽象的实现部分的修改应对客户不产生影响,即客户的代码不必重新编译。
(C + +)你想对客户完全隐藏抽象的实现部分。在C + +中,类的表示在类接口中是可见的。
有许多类要生成。这样一种类层次结构说明你必须将一个对象分解成两个部分。R u m b a u g h 称这种类层次结构为“嵌套的普化”(nested generalizations )。
你想在多个对象间共享实现(可能使用引用计数),但同时要求客户并不知道这一点。一个简单的例子便是C o p l i e n 的S t r i n g 类[ C o p 9 2 ],在这个类中多个对象可以共享同一个字符串表示(S t r i n g R e p )。

名称 Composite
结构  
意图 将对象组合成树形结构以表示“部分-整体”的层次结构。C o m p o s i t e 使得用户对单个对象和组合对象的使用具有一致性。
适用性 你想表示对象的部分-整体层次结构。
你希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。

名称 Decorator
结构  
意图 动态地给一个对象添加一些额外的职责。就增加功能来说,D e c o r a t o r 模式相比生成子类更为灵活。
适用性 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
处理那些可以撤消的职责。
当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。

名称 Facade
结构  
意图 为子系统中的一组接口提供一个一致的界面,F a c a d e 模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
适用性 当你要为一个复杂子系统提供一个简单接口时。子系统往往因为不断演化而变得越来越复杂。大多数模式使用时都会产生更多更小的类。这使得子系统更具可重用性,也更容易对子系统进行定制,但这也给那些不需要定制子系统的用户带来一些使用上的困难。F a c a d e 可以提供一个简单的缺省视图,这一视图对大多数用户来说已经足够,而那些需要更多的可定制性的用户可以越过f a c a d e 层。
客户程序与抽象类的实现部分之间存在着很大的依赖性。引入f a c a d e 将这个子系统与客户以及其他的子系统分离,可以提高子系统的独立性和可移植性。
当你需要构建一个层次结构的子系统时,使用f a c a d e 模式定义子系统中每层的入口点。如果子系统之间是相互依赖的,你可以让它们仅通过f a c a d e 进行通讯,从而简化了它们之间的依赖关系。

名称 Flyweight
结构  
意图 运用共享技术有效地支持大量细粒度的对象。
适用性 一个应用程序使用了大量的对象。
完全由于使用大量的对象,造成很大的存储开销。
对象的大多数状态都可变为外部状态。
如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象。
应用程序不依赖于对象标识。由于F l y w e i g h t 对象可以被共享,对于概念上明显有别的对象,标识测试将返回真值。

名称 Proxy
结构  
意图 为其他对象提供一种代理以控制对这个对象的访问。
适用性 在需要用比较通用和复杂的对象指针代替简单的指针的时候,使用P r o x y 模式。下面是一 些可以使用P r o x y 模式常见情况:
1) 远程代理(Remote Proxy )为一个对象在不同的地址空间提供局部代表。 NEXTSTEP[Add94] 使用N X P r o x y 类实现了这一目的。Coplien[Cop92] 称这种代理为“大使” (A m b a s s a d o r )。
2 )虚代理(Virtual Proxy )根据需要创建开销很大的对象。在动机一节描述的I m a g e P r o x y 就是这样一种代理的例子。
3) 保护代理(Protection Proxy )控制对原始对象的访问。保护代理用于对象应该有不同 的访问权限的时候。例如,在C h o i c e s 操作系统[ C I R M 9 3 ]中K e m e l P r o x i e s 为操作系统对象提供 了访问保护。
4 )智能指引(Smart Reference )取代了简单的指针,它在访问对象时执行一些附加操作。 它的典型用途包括:

对指向实际对象的引用计数,这样当该对象没有引用时,可以自动释放它(也称为S m a r tP o i n t e r s[ E d e 9 2 ] )。
当第一次引用一个持久对象时,将它装入内存。
在访问一个实际对象前,检查是否已经锁定了它,以确保其他对象不能改变它。

名称 Chain of Responsibility
结构  
意图 使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
适用性 有多个的对象可以处理一个请求,哪个对象处理该请求运行时刻自动确定。
你想在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。
可处理一个请求的对象集合应被动态指定。

名称 Command
结构  
意图 将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤消的操作。
适用性 像上面讨论的M e n u I t e m 对象那样,抽象出待执行的动作以参数化某对象。你可用过程语言中的回调(c a l l b a c k )函数表达这种参数化机制。所谓回调函数是指函数先在某处注册,而它将在稍后某个需要的时候被调用。C o m m a n d 模式是回调机制的一个面向对象的替代品。
在不同的时刻指定、排列和执行请求。一个C o m m a n d 对象可以有一个与初始请求无关的生存期。如果一个请求的接收者可用一种与地址空间无关的方式表达,那么就可将负责该请求的命令对象传送给另一个不同的进程并在那儿实现该请求。
支持取消操作。C o m m a n d 的E x c u t e 操作可在实施操作前将状态存储起来,在取消操作时这个状态用来消除该操作的影响。C o m m a n d 接口必须添加一个U n e x e c u t e 操作,该操作取消上一次E x e c u t e 调用的效果。执行的命令被存储在一个历史列表中。可通过向后和向前遍历这一列表并分别调用U n e x e c u t e 和E x e c u t e 来实现重数不限的“取消”和“重做”。
支持修改日志,这样当系统崩溃时,这些修改可以被重做一遍。在C o m m a n d 接口中添加装载操作和存储操作,可以用来保持变动的一个一致的修改日志。从崩溃中恢复的过程包括从磁盘中重新读入记录下来的命令并用E x e c u t e 操作重新执行它们。
用构建在原语操作上的高层操作构造一个系统。这样一种结构在支持事务( t r a n s a c t i o n )的信息系统中很常见。一个事务封装了对数据的一组变动。C o m m a n d 模式提供了对事务进行建模的方法。C o m m a n d 有一个公共的接口,使得你可以用同一种方式调用所有的事务。同时使用该模式也易于添加新事务以扩展系统。

名称 Interpreter
结构  
意图 给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
适用性 当有一个语言需要解释执行, 并且你可将该语言中的句子表示为一个抽象语法树时,可使用解释器模式。而当存在以下情况时该模式效果最好:
该文法简单对于复杂的文法, 文法的类层次变得庞大而无法管理。此时语法分析程序生成器这样的工具是更好的选择。它们无需构建抽象语法树即可解释表达式, 这样可以节省空间而且还可能节省时间。
效率不是一个关键问题最高效的解释器通常不是通过直接解释语法分析树实现的, 而是首先将它们转换成另一种形式。例如,正则表达式通常被转换成状态机。但即使在这种情况下, 转换器仍可用解释器模式实现, 该模式仍是有用的。

名称 Iterator
结构  
意图 提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示。
适用性 访问一个聚合对象的内容而无需暴露它的内部表示。
支持对聚合对象的多种遍历。
为遍历不同的聚合结构提供一个统一的接口(即, 支持多态迭代)。

名称 Mediator
结构  
意图 用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
适用性 一组对象以定义良好但是复杂的方式进行通信。产生的相互依赖关系结构混乱且难以理解。
一个对象引用其他很多对象并且直接与这些对象通信,导致难以复用该对象。
想定制一个分布在多个类中的行为,而又不想生成太多的子类。

名称 Memento
结构  
意图 在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。
适用性 必须保存一个对象在某一个时刻的(部分)状态, 这样以后需要时它才能恢复到先前的状态。
如果一个用接口来让其它对象直接得到这些状态,将会暴露对象的实现细节并破坏对象的封装性。

名称 Observer
结构  
意图 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新。
适用性 当一个抽象模型有两个方面, 其中一个方面依赖于另一方面。将这二者封装在独立的对象中以使它们可以各自独立地改变和复用。
当对一个对象的改变需要同时改变其它对象, 而不知道具体有多少对象有待改变。
当一个对象必须通知其它对象,而它又不能假定其它对象是谁。换言之, 你不希望这些对象是紧密耦合的。

名称 State
结构  
意图 允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。
适用性 一个对象的行为取决于它的状态, 并且它必须在运行时刻根据状态改变它的行为。
一个操作中含有庞大的多分支的条件语句,且这些分支依赖于该对象的状态。这个状态通常用一个或多个枚举常量表示。通常, 有多个操作包含这一相同的条件结构。S t a t e模式将每一个条件分支放入一个独立的类中。这使得你可以根据对象自身的情况将对象的状态作为一个对象,这一对象可以不依赖于其他对象而独立变化。

名称 Strategy
结构  
意图 定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。
适用性 许多相关的类仅仅是行为有异。“策略”提供了一种用多个行为中的一个行为来配置一个类的方法。
需要使用一个算法的不同变体。例如,你可能会定义一些反映不同的空间/时间权衡的算法。当这些变体实现为一个算法的类层次时[ H O 8 7 ] ,可以使用策略模式。
算法使用客户不应该知道的数据。可使用策略模式以避免暴露复杂的、与算法相关的数据结构。
一个类定义了多种行为, 并且这些行为在这个类的操作中以多个条件语句的形式出现。将相关的条件分支移入它们各自的S t r a t e g y 类中以代替这些条件语句。

名称 Template Method
结构  
意图 定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。Te m p l a t e M e t h o d 使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
适用性 一次性实现一个算法的不变的部分,并将可变的行为留给子类来实现。
各子类中公共的行为应被提取出来并集中到一个公共父类中以避免代码重复。这是O p d y k e 和J o h n s o n 所描述过的“重分解以一般化”的一个很好的例子[ O J 9 3 ]。首先识别现有代码中的不同之处,并且将不同之处分离为新的操作。最后,用一个调用这些新的操作的模板方法来替换这些不同的代码。
控制子类扩展。模板方法只在特定点调用“h o o k ”操作(参见效果一节),这样就只允许在这些点进行扩展。

名称 Visitor
结构  
意图 表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
适用性 一个对象结构包含很多类对象,它们有不同的接口,而你想对这些对象实施一些依赖于其具体类的操作。
需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而你想避免让这些操作“污染”这些对象的类。Vi s i t o r 使得你可以将相关的操作集中起来定义在一个类中。当该对象结构被很多应用共享时,用Vi s i t o r 模式让每个应用仅包含需要用到的操作。
定义对象结构的类很少改变,但经常需要在此结构上定义新的操作。改变对象结构类需要重定义对所有访问者的接口,这可能需要很大的代价。如果对象结构类经常改变,那么可能还是在这些类中定义这些操作较好。


五、成功采用设计模式的三个步骤

  如何把设计模式的采用和日益临近的最后期限、紧缩的预算和很多公司现有的有限团队资源相结合?以下是成功制订设计模式的三个步骤。

强大的通信和培训
  许多机构拥有领先技术,可能正式通过了设计师论坛的论证或者非正式的公认专家。这些领先厂商将推广设计模式采用中的开放通信,并将培训开发具体设计模式的团队。通信应当跨开发团队和项目以便预先防止采用竖井和多种惟一的实现(谨记每个Developer/Project AntiPattern的实现)。培训可以采用正式的internal lunch-and-learns、正式的internal class或者派一些员工参加外部培训。这些培训方式将促进正确的设计模式应用程序。如果仅有极少的观众能够参加培训,最佳的候选人是那些感觉适合在回来后能够培训其同事的人。

设计模式采用指导
  设计模式可用于使项目受益,但是他们也可能因为误用而对应用程序造成损害。应当鼓励采用他们,但是对其的采用应当受到审阅和验证。设计模式可以包含在设计和开发过程中。在任何一种情况中,设计模式的使用应当由审阅者确认和验证。在审阅过程中还可能会遇到这样的情况,额外的设计模式不适用于最初包括的地方。即使环境中没有进行正式的审阅,这一步骤也可以通过同事审阅或者团队讨论来完成。这一步骤中的审阅者要么是主要团队的成员,要么与他们建立开放通信。
  指导采用对于broad exposure类别的设计模式非常关键。这些设计模式具有很多相关的风险,因为他们将创建依赖性。这些依赖性可能在一些对象类中,例如,只工作在更加广泛的DAO设计模式实现范围中的数据访问对象(DAO)、或者跨应用程序边界(如使用Value Object设计模式在应用程序和应用程序层之间传输数据)。这些设计模式也可以由项目中的其他人或者不同项目的人实现,而且实现应当重新使用,不同于创建另一种独特的实现。

重用实现,不只是设计模式
  只要在创建自己的设计模式实现中有一定的满足,团队和公司就可以在重用发生在代码层时,而不是设计创意层时获得更多益处。使企业获益的最初设计模式是改进的实现。但是,真正的目标是重用实现。重用实现将导致:a)其他可重用的类(取决于公共实现);b)缩短开发时间和降低成本;c)缩短维护时间和降低成本;d)在应用程序之间和内部轻松集成。
  这种重用对broad exposure设计模式非常重要(有时是基本的)。这些设计模式创建了外部依赖性(集成将从公共实现中受益)或者产生全部的自定义类库(如果有公共基础将可重用)。isolated use设计模式也可以从重用中获益,但是如果他们是根据具体情况定制的,他们就非常难以重用。
  有时您可能会问自己:“如果重用比较好,为什么设计模式和可以重用的实现不可以一同应用呢?”在我们讨论设计模式如何使更多读者获益的时候才会讨论这个问题。如果可能,如果已经预定义了实现,那么达到广泛适用性这个目标就会非常困难。然而,一旦设计模式被应用到特殊的问题域或者技术基础设施中,那么就可以重用在该环境中产生的实现。

架构中的设计模式
  这看起来像是一件可怕的任务,需要掌握设计模式如何应用在实际情况中,如何构建优质的实现,以及如何促进重用实现。完成该任务的方法之一就是在环境中引入应用程序架构。应用程序架构提供了应用程序需要的结构,从而使开发团队可以关注应用程序的域逻辑。这包含了已实现的设计模式。除了重用设计模式概念或者单个实现之外,可以在多个项目和应用程序之间重用架构。这种共享的公共实现确保了兼容性,并为开发和维护多种不同的实现提供了一种低成本替代方案。兼容性提供了重新使用需要的技术基础。没有足够的篇幅在这里深入讨论架构的其他重要品质,如运行时监测和管理、可配置应用程序逻辑和适应性行为等。

26

2月

关于用mencoder将各种格式转换为flv格式,网络上应该也有一些文章,我把最近学习的心得和大家分享一下.
如果您正准备开始使用mencoder,似乎也可以当作教程来看,如果您有更好的方法或技术,请不吝赐教!
mencoder,可以从其官方网站上获得:
http://www.mplayerhq.hu
下载完之后,修改一下环境变量,将mencoder.exe及mplayer.exe文件所在的目录添加到path变量里。
mencoder是在命令行中执行的(官网上的文档里的实例似乎都是linux下的)
我是计算机小白,当然只会使用windows……
开始菜单 -> 运行 -> cmd -> 回车,就打开了命令行窗口
这时,我们可以拿一个视频来试试看,我用的是一个mtv,wmv格式的,文件名:APerfectMatch.wmv。
在命令行中输入:(注意,不要从网页上直接copy这段命令到cmd,windows的命令行似乎是不支持换行的......)
mencoder "D:\music\sk8ter_boi_300.wmv" -o "D:\output.flv" -of lavf -oac mp3lame -lameopts abr:br=56 -ovc lavc -lavcopts vcodec=flv:vbitrate=150:mbd=2:mv0:trell:v4mv:cbp:last_pred=3 -srate 22050
按下回车后,如果你看到显示:“mencoder 不是内部或外部命令,也不是可运行的程序,或批处理文件”,那么说明环境变量没有设置好
如果正常,会看到开始转视频,会看到一排一排的字往上翻,内容大概是这样:
Pos: 226.8s 297f (100%) 48fps Trem: 0min 5mb a-v:-0.009 [142:56]
这里边的内容,我最关注的是2个括号里面的,小括号里应该是转换的进度,中括号里的内容很重要,142表示视频比特率,56表示音频比特率(比特率这个词不知道用的对不对......)
转换结束,会显示2行文字:
Video stream: 142.564 kbit/s (17820 B/s) size: 4046677 bytes 227.080 secs 2700 frames
Audio stream: 56.938 kbit/s (7117 B/s) size: 1616197 bytes 227.082 secs
这2行信息我想大家都能明白,其中我一直关注的是那个142.564kbit/s,用过flash8自带转换工具的应该知道高级设置里有个选项是最大数据速率,当选中中等画质的时候,是400kb/s,而低品质也是150kb/s,也就是说,用那句命令转换的视频,其画质都不如品质的,那么,品质怎么样呢?看一下,怎么看flv文件?别忘了我们有万能播放器mplayer,哈哈,直接在命令行里输入:
mplayer "d:\output.flv",看到咱们刚刚转好的视频,我当时一看,画面上马赛克倒是没有,全是瓷砖,我晕倒...
进入正题了,怎么来提高画面品质?(晕倒,原来前面都不是正题...=_=o)
回头看一下我们的命令行:
mencoder "D:\music\sk8ter_boi_300.wmv" -o "D:\output.flv" -of lavf -oac mp3lame -lameopts abr:br=56 -ovc lavc -lavcopts vcodec=flv:vbitrate=150:mbd=2:mv0:trell:v4mv:cbp:last_pred=3 -srate 22050。
下面一个一个分析:
mencoder 说明你用的是mencoder;
"d:\.....wmv" -> 是指你的输入视频;
-o -> 后面指定输出路径;(前面有“-”的都是option(选项的意思))
-of -> 大概是output format的缩写,输出文件格式,咦!为什么不是flv,而是lavf?lavf表示你使用了libavcodec里的格式,flv正好是libavcodec里的,呵呵;
-oac -> 大概是output audio codec的缩写,指定输出音频编码,这儿选用的是mp3lame;
-lameopts -> 指定lame的options,就是设置音频输出的一些参数啦,我只关心视频,跳过
-ovc -> 大概是output video codec的缩写,制定输出视频编码(我最关心的好像要上场了),选用的lavc,什么意思?说是用了libavcodec的编码器;
-lavcopts -> 是lavc的options,要设置视频编码的参数了!(心跳加速,血压升高,口中开始大量分泌唾液),看看它后面都有什么:
codec=flv 说的是用的flv编码器,这个咱不理;
vbitrate=150 video bit rate!视频数据速率!就是它了!原来我设的是150啊!
找到了,下面不看了!改成vbitrate=1000,再试试看!
结果,和前一次一模一样......(我还改成10000的,真的,还是一样,我当时以为它的单位是b/s而不是kb/s)
冷静下来,去往上看了一下官方文档,这个参数是最大数据速率,最大嘛,你设多大都一样啊,看来不是靠它来控制品质。
不卖关子了,直接给出我的结论吧,设置品质有2种途径:
1、设置-lavcopts,看这样一句命令:
mencoder "D:\music\APerfectMatch.wmv" -o "D:\output.flv" -of lavf -oac mp3lame -lameopts abr:br=56 -ovc lavc -lavcopts vcodec=flv:vbitrate=500:mbd=2:mv0:trell:v4mv:cbp:last_pred=3:dia=4:cmp=6:vb_strategy=1 -vf scale=320:240,expand=320:240:::1,crop=320:240:0:0 -ofps 30 -srate 22050
看看多了什么?
在-lavcopts里多了dia=4:cmp=6:vb_strategy=1这3条
他们的含义我只是大概了解一点点,毕竟不是专业搞视频编码的
dia越大品质越高,如果需要快速编码,设置为-1,设为4时已经很有利于品质了;
cmp越大品质越高,默认值0,是最快速的,一般设到3,设为6已经只会细微提高品质了,但速度会慢
vb_strategy,大概是1或者0,默认值可能为0,我这里设为1,会对编码有帮助,这个参数我自己没有过多推敲,可能并不影响品质......
2、加-sws选项,看下面的命令:
mencoder "D:\music\APerfectMatch.wmv" -o "D:\output.flv" -of lavf -oac mp3lame -lameopts abr:br=56 -ovc lavc -lavcopts vcodec=flv:vbitrate=500:mbd=2:mv0:trell:v4mv:cbp:last_pred=3 -sws 3 -vf scale=320:240,expand=320:240:::1,crop=320:240:0:0 -ofps 30 -srate 22050
只是加一个 -sws 3进去,转换后的效果和前面一种方法大致相同,视频数据速率都是422.5kb/s左右,解释一下
-sws就是用来设置品质的,默认值为2,那么,为什么不用这种简单的方式呢?我个人认为,用前面一种方法有利于找到一个速度和品质的平衡点,毕竟变化的范围比较大。
其他一些选项,我也没有深入研究。

26

2月

Silverlight是什么?

[2008-2-26 15:34 | 分类: 软件编程 | by Wudi ]
Silverlight是什么?如果你从Google上搜一下,一定能找到很多的介绍。但如果你是一位开发人员,你或许应该从下面的角度了解什么是Silverlight。

Silverlight集合了多种技术到一个开发平台上,这样你可以在开发中选择你自己需要的工具和技术。下面将分别介绍Silverlight为我们带来了什么。

WPF和XAML.。大家知道Silverlight的原名叫WPF/E,它是WPF的一个子集。所以Silverlight包含了WPF技术,它可以大大的扩展浏览器中的页面元素。有了它我们可以创建图像、动画,媒体和其他胖客户端特性。超越了网页界面只能使用HTML的局限。XAML让我们可以方便的创建WPF元素。
JavaScript扩展。Silverlight对JavaScript进行了扩展,提供对WebUI更加强大的控制能力和与WPF元素协同工作的能力。
跨浏览器、跨平台支持。一个Silverlight程序可以在大多数的浏览器上运行,这样我们开发Silverlight应用的时候就不用考虑他将运行在什么平台上。
可与现有应用程序集成。Silverlight可以无缝的与现有的JavaScript和Asp.Net Ajax 代码集成,并作为已创建功能的一个重要的补充。
采用.NET编程模型和相关的开发工具。我们可以采用托管的JScript和IronPython来编写Silverlight应用程序,也可以使用C#和Visual Basic来完成。你还可以使用Visual Studio 这样的工具来创建Silverlight应用程序。
LINQ。Silverlight包含LINQ,它可以让你在.NET中通过更加直观的和强类型的对象来访问数据。
如果你已经在使用ASP.NET,你可以将Silverlight集成到你所熟悉的ASP.NET的服务器端应用和客户端应用中。你可以创建ASP.NET的服务端资源,并通过Ajax在客户端无刷新的访问服务器端资源。

下图描述了Silverlight包含的内容



点击在新窗口中浏览此图片

21

2月

对中国电信业重组的想法若干

[2008-2-21 20:35 | 分类: 杂事 | by Wudi ]
点击在新窗口中浏览此图片

1.由于工作关系与中移动有业务接触,所以对电信业的重组也较为关注。流传的重组方案为:中国联通的CDMA网与GSM网分离,前者被中国电信收购,后者与中国网通合并,组成新联通,中国铁通并入中国移动。

2.中国电信方面:在原有固网用户的基础上,收购了联通的C网便拿到了CDMA业务也成为电信业户新的增长点,也兼并了联通C的基础资源从而增加本事基础资源的厚度,也许小灵通会退出短暂的历史舞台。

3.中国联通方面:在卖掉C网后再加上网通的固网与固话业户后,是乎变成了一个“大综合”。但由于吃掉的网通是北京奥运会的网络通讯赞助商也许会给网通带来一定的经济收入。但由于历史遗留的南电北通问题,会给联通与网通的融合带来不小的问题。但真正收益的还是中国网通,而中联通将C网几百亿卖掉后全部放入G网的发展,必将与中移动在移动业务上有一争,但是乎还是不可动摇移动的大佬地位。

4.中国移动方面:借助兼并铁通后也许可以顺利的拿到期望已久的3G牌照,也不枉费这2年在3G上的投入。兼并铁通是乎对移动本事没有多少主导型的影响,间接的可能会增加固网固话的业务而不是移动原来那个名义上的集团用户。

5.资本方面:由于5大运营商的合并为3大家,所以中移动中电信肯定会回归A股市场。而对3家的价值方面更好带来突飞猛进的提升。

6.消费者方面:鉴于联通在GMS网络可能会有强大的发展,移动必将与联通展开话费大战,收益的比较是我们广大的消费人民。

7.编者按:也应该变化一下我天天流水的风格了,只是说了一下我对通讯业务方面的大概想法,最后继续祝愿你的身体快快康复。么么

10

1月

如何卸载ORACLE

[2008-1-10 10:37 | 分类: 软件编程 | by Wudi ]
软件环境:
1、Windows 2000+ORACLE 8.1.7
2、ORACLE安装路径为:C:\ORACLE
实现方法:
1、开始->设置->控制面板->管理工具->服务 停止所有Oracle服务。
2、开始->程序->Oracle - OraHome81->Oracle Installation Products-> Universal Installer 卸装所有Oracle产品,但Universal Installer本身不能被删除
5、运行regedit,选择HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE,按del键删除这个入口。
6、运行regedit,选择HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services,滚动 这个列表,删除所有Oracle入口。
7、运行refedit,选择HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Eventlog\Application, 删除所有Oracle入口。
8、开始->设置->控制面板->系统->高级->环境变量 删除环境变量CLASSPATH和PATH中有关Oracle的设定
9、从桌面上、STARTUP(启动)组、程序菜单中,删除所有有关Oracle的组和图标
10、删除\Program Files\Oracle目录
11、重新启动计算机,重起后才能完全删除Oracle所在目录
12、删除与Oracle有关的文件,选择Oracle所在的缺省目录C:\Oracle,删除这个入口目录及所有子目录,并从Windows 2000目录(一般为C:\WINNT)下删除以下文件ORACLE.INI、oradim73.INI、oradim80.INI、oraodbc.ini等等。
13、WIN.INI文件中若有[ORACLE]的标记段,删除该段
14、如有必要,删除所有Oracle相关的ODBC的DSN
15、到事件查看器中,删除Oracle相关的日志 说明:如果有个别DLL文件无法删除的情况,则不用理会,重新启动,开始新的安装,安装时,选择一个新的目录,则,安装完毕并重新启动后,老的目录及文件就可以删除掉了。

5

1月

关于CMMI的几点感悟

[2008-1-5 23:16 | 分类: 工作 | by Wudi ]
最近往复旅行工作都是为了CMMI,到底什么是CMMI?有什么用?我写一些我自己的理解。

CMMI,Capability Maturity Model Integration的缩写,译为软件能力成熟度模型集成模型。

用通俗点的意思来理解就是做软件项目要走流程,按规矩办事,现在的软件项目开发大部分都不会这么规范的进行,

可能处于成本的考虑,可能处于项目进度的考虑。CMMI需要从项目的立项、需求、计划、设计、编码、测试直至实施验收。

一步步下来,其实看起来跟现在有些规模的企业的流程差不多,但他更注重与质量与度量,需要的是数据,比如需求的变更次数,

设计的修改次数,为什么要修改需求的;比如测试用例有多少,代码有多少,等等。这说明CMMI对整个流程的细节都需要很好的把

握,但这里会产生一个问题,真正的软件开发中质量与度量也敢当什么职务呢?不参与开发肯定不符合现在中小企业的用人需求,明

显的人员富余,再者软件开发中肯定会注重过程而往往会忽略掉对度的把握,也就是对度量的把握。所以我觉得cmmi有理,但真正

只能取其精华而不能照搬。也许这样真正的会做到所说的成熟度从而提高整个项目的进度。杂论一通完毕。
分页: 4/5 第一页 上页 1 2 3 4 5 下页 最后页 [ 显示模式: 摘要 | 列表 ]