百万级访问网站前期的技术准备

Posted on

百万级访问网站前期的技术准备 **

博客分类:

开了自己域名的博客,第一篇就得来个重磅一点的才对得起这4美金的域名。作为一个技术从业者十年,逛了十年发现有些知识东一榔头西一棒槌的得满世界 看个遍才整理出个头绪,那咱就系统点的从头一步一步的说,一个从日几千访问的小小网站,到日访问一两百万的小网站,怎么才能让它平滑的度过这个阶段,别在 技术上出现先天不足,写给一些技术人员,也写给不懂技术的创业者。 对互联网有了解的人都有自己的想法,有人就把想法付诸实现,做个网站然后开始运营。其实从纯网站技术上来说,因为开源模式的发展,现在建一个小网站 已经很简单也很便宜。当访问量到达一定数量级的时候成本就开始飙升了,问题也开始显现了。因为带宽的增加、硬件的扩展、人员的扩张所带来的成本提高是显而 易见的,而还有相当大的一部分成本是因为代码重构、架构重构,甚至底层开发语言更换引起的,最惨的就是数据丢失,辛辛苦苦好几年,一夜回到创业前。 减少成本就是增加利润。很多事情,我们在一开始就可以避免,先打好基础,往后可以省很多精力,少操很多心。 假设你是一个参与创业的技术人员,当前一穷二白,什么都要自己做,自己出钱,初期几十万的资金,做一个应用不是特别复杂的网站,那么就要注意以下几点: 一、开发语言 一般来说,技术人员(程序员)创业都是根据自己技术背景选择自己最熟悉的语言,不过考虑到不可能永远是您一个人写程序,这点还得仔细想想。无论用什么语言,最终代码质量是看管理,所以我们还是从纯语言层面来说实际一点。现在流行的java、php、.net、python、ruby都 有自己的优劣,python和ruby,现在人员还是相对难招一些,性能优化也会费些力气,.net平台买不起windows server。java、php用的还是最多。对于初期,应用几乎都是靠前端支撑的网站来说,php的优势稍大一些,入门简单、设计模式简单、写起来快、 性能足够等,不过不注重设计模式也是它的劣势,容易变得松散,隐藏bug稍多、难以维护。java的优势在于整套管理流程已经有很多成熟工具来辅助,强类 型也能避免一些弱智BUG,大多数JAVA程序员比较注重设计模式,别管实不实际,代码格式看起来还是不错的。这也是个劣势,初学者可能太注重模式而很难 解决实际需求。 前端不只是html、css这类。整个负责跟用户交互的部分都是前端,包括处理程序。这类程序还是建议用php,主要原因就是开发迅速、从业人员广泛。至于后端例如行为分析、银行接口、异步消息处理等,随便用什么程序,那个只能是根据不同业务需求来选择不同语言了。 二、代码版本管理 如果开发人员之间的网络速度差不多,就SVN;比较分散例如跨国,就hg。大多数人还是svn的. 假设选了svn,那么有几点考虑。一是采用什么树结构。初期可能只有一条主干,往后就需要建立分支,例如一条开发分支,一条上线分支,再往后,可能 要每个小组一个分支。建议一开始人少时选择两条分支,开发和线上,每个功能本地测试无误后提交到开发分支,最后统一测试,可以上线时合并到上线分支。如果 喜欢把svn当做移动硬盘用,写一点就commit一次也无所谓,就是合并的时候头大一些,这些人可以自己建个分支甚至建立个本地代码仓库,随便往自己的 分支提交,测试完毕后再提交到开发分支上。 部署,可以手工部署也可以自动部署。手工部署相对简单,一般是直接在服务器上svn update,或者找个新目录svn checkout,再把web root给ln -s过去。应用越复杂,部署越复杂,没有什么统一标准,只要别再用ftp上传那种形式就好,一是上传时文件引用不一致错误率增加,二是很容易出现开发人员 的版本跟线上版本不一致,导致本来想改个错字结果变成回滚的杯具。如果有多台服务器还是建议自动部署,更换代码的机器从当前服务池中临时撤出,更新完毕后 再重新加入。 不管项目多小,养成使用版本管理的好习惯,最起码还可以当做你的备份,我的 http://zhiyi.us 虽然就是一个wordpress,可还是svn了,只改动一两句css那也是劳动成果。 三、服务器硬件 别羡慕大客户和有钱人,看看机房散户区,一台服务器孤独的支撑的网站数不清。如果资金稍微充足,建议至少三台的标准配置,分别用作web处理、数据 库、备份。web服务器至少要8G内存,双sata raid1,如果经济稍微宽松,或静态文件或图片多,则15k sas raid1+0。数据库至少16G内存,15k sas raid 1+0。备份服务器最好跟数据库服务器同等配置。硬件可以自己买品牌的底板,也就是机箱配主板和硬盘盒,CPU内存硬盘都自己配,也可以上整套品牌,也可 以兼容机。三台机器,市场行情6、7万也就配齐了。 web服务器可以既跑程序又当内存缓存,数据库服务器则只跑主数据库(假如是MySQL的话),备份服务器干的活就相对多一些,web配置、缓存配置、数据库配置都要跟前两台一致,这样WEB和数据库任意一台出问题,把备份服务器换个ip就切换上去了。备份策略,可以drbd,可以rsync,或者其他的很多很多的开源备份方案可选择。rsync最简单,放cron里自己跑就行。备份和切换,建议多做测试,选最安全最适合业务的,并且尽可能异地备份。 四、机房 三种机房尽量不要选:联通访问特别慢的电信机房、电信访问特别慢的联通机房、电信联通访问特别慢的移动或铁通机房。那网通机房呢?亲,网通联通N久 以前合并改叫联通了。多多寻找,实地参观,多多测试,多方打探,北京、上海、广州等各个主节点城市,还是有很多优质机房的,找个网络质量好,管理严格的机 房,特别是管理要严格,千万别网站无法访问了,打个电话过去才知道别人维护时把你网线碰掉了,这比DOS都头疼。自己扯了几根光纤就称为机房的,看您抗风 险程度和心理素质了。机房可以说是非常重要,直接关系到网站访问速度,网站访问速度直接关系到用户体验,我可以F墙看风景,但买个网游vpn才能打开你这 个还不怎么知名的网站就有难度了。或许您网站的ajax很出色,可是document怎么也不ready,一些代码永远绝缘于用户。 五、架构 初期架构一般比较简单,web负载均衡+数据库主从+缓存+分布式存储+队列。大方向上也确实就这几样东西,细节上也无数文章都重复过了,按照将来 会有N多WEB,N多主从关系,N多缓存,N多xxx设计就行,基本方案都是现成的,只是您比其他人厉害之处就在于设计上考虑到缓存失效时的雪崩效应、主 从同步的数据一致性和时间差、队列的稳定性和失败后的重试策略、文件存储的效率和备份方式等等意外情况。缓存总有一天会失效,数据库复制总有一天会断掉, 队列总有一天会写不进去,电源总有一天会烧坏。根据墨菲定律,如果不考虑这些,网站早晚会成为茶几。 六、服务器软件 Linux、nginx、php、mysql,几乎是标配,我们除了看名字,还得选版本。Linux发行版众多,只要没特殊要求,就选个用的人最多的,社区最活跃的,配置最方便的,软件包最全最新的,例如debian、ubuntu。 至于RHEL之类的嘛,你用只能在RHEL上才能运行的软件么?剩下的nginx、php、mysql、activemq、其他的等等,除非你改过这些软 件或你的程序真的不兼容新版本,否则尽量版本越新越好,版本新,意味着新特性增多、BUG减少、性能增加。总有些道听途说的人跟你说老的版本稳定。所谓稳 定,是相对于特殊业务来说的,而就一个php写的网站,大多数人都没改过任何服务器软件源代码,绝大多数情况是能平稳的升级到新版本的。类似于jdk5到 jdk6,python2到python3这类变动比较大的升级还是比较少见的。看看ChangeLog,看看升级说明,结合自己情况评估一下,越早升级 越好,别人家都用php6写程序了这边还php4的逛游呢。优秀的开源程序升级还是很负责任的,看好文档,别怕。 以上这六点准备完毕,现在我们有了运行环境,有了基本架构骨架,有了备份和切换方案,应该开始着手设计开发方面的事情了。开发方面的事情无数,下一篇会先说一些重点。 原文地址 七、数据库 几乎所有操作最后都要落到数据库身上,它又最难扩展(存储也挺难)。对于mysql,什么样的表用myisam,什么样的表用innodb,在开发 之前要确定。复制策略、分片策略,也要确定。表引擎方面,一般,更新不多、不需要事务的表可以用myisam,需要行锁定、事务支持的,用innodb。 myisam的锁表不一定是性能低下的根源,innodb也不一定全是行锁,具体细节要多看相关的文档,熟悉了引擎特性才能用的更好。现代WEB应用越来 越复杂了,我们设计表结构时常常设计很多冗余,虽然不符合传统范式,但为了速度考虑还是值得的,要求高的情况下甚至要杜绝联合查询。编程时得多注意数据一 致性。 复制策略方面,多主多从结构也最好一开始就设计好,代码直接按照多主多从来编写,用一些小技巧来避免复制延时问题,并且还要解决多数据库数据是否一致,可以自己写或者找现成的运维工具。 分片策略。总会有那么几个表数据量超大,这时分片必不可免。分片有很多策略,从简单的分区到根据热度自动调整,依照具体业务选择一个适合自己的。避免自增ID作为主键,不利于分片。 用存储过程是比较难扩展的,这种情形多发生于传统C/S,特别是OA系统转换过来的开发人员。低成本网站不是一两台小型机跑一个数据库处理所有业务的模式,是机海作战。方便水平扩展比那点预分析时间和网络传输流量要重要的多的多。 NoSQL。这只是一个概念。实际应用中,网站有着越来越多的密集写操作、上亿的简单关系数据读取、热备等,这都不是传统关系数据库所擅长的,于是 就产生了很多非关系型数据库,比如Redis/TC&TT/MongoDB/Memcachedb等,在测试中,这些几乎都达到了每秒至少一万次 的写操作,内存型的甚至5万以上。例如MongoDB,几句配置就可以组建一个复制+自动分片+failover的环境,文档化的存储也简化了传统设计库 结构再开发的模式。很多业务是可以用这类数据库来替代mysql的。 八、缓存。 数据库很脆弱,一定要有缓存在前面挡着,其实我们优化速度,几乎就是优化缓存,能用缓存的地方,就不要再跑到后端数据库那折腾。缓存有持久化缓存、 内存缓存,生成静态页面是最容易理解的持久化缓存了,还有很多比如varnish的分块缓存、前面提到的memcachedb等,内存缓 存,memcached首当其冲。缓存更新可用被动更新和主动更新。被动更新的好处是设计简单,缓存空了就自动去数据库取数据再把缓存填上,但容易引发雪 崩效应,一旦缓存大面积失效,数据库的压力直线上升很可能挂掉。主动缓存可避免这点但是可能引发程序取不到数据的问题。这两者之间如何配合,程序设计要多 动脑筋。 九、队列。 用户一个操作很可能引发一系列资源和功能的调动,这些调动如果同时发生,压力无法控制,用户体验也不好,可以把这样一些操作放入队列,由另几个模块 去异步执行,例如发送邮件,发送手机短信。开源队列服务器很多,性能要求不高用数据库当做队列也可以,只要保证程序读写队列的接口不变,底层队列服务可随 时更换就可以,类似Zend Framework里的Zend_Queue类,java.util.Queue接口等。 十、文件存储。 除了结构化数据,我们经常要存放其他的数据,像图片之类的。这类数据数量繁多、访问量大。典型的就是图片,从用户头像到用户上传的照片,还要生成不 同的缩略图尺寸。存储的分布几乎跟数据库扩展一样艰难。不使用专业存储的情况下,基本都是靠自己的NAS。这就涉及到结构。拿图片存储举例,图片是非常容 易产生热点的,有些图片上传后就不再有人看,有些可能每天被访问数十万次,而且大量小文件的异步备份也很耗费时间。 为了将来图片走cdn做准备,一开始最好就将图片的域名分开,且不用主域名。很多网站都将cookie设置到了.domain.ltd,如果图片也在这个域名下,很可能因为cookie而造成缓存失效,并且占多余流量,还可能因为浏览器并发线程限制造成访问缓慢。 如果用普通的文件系统存储图片,有一个简单的方法。计算文件的hash值,比如md5,以结果第一位作为第一级目录,这样第一级有16个目录。从0 到F,可以把这个字母作为域名,0.yourimg.com到f.yourimg.com(客户端dns压力会增大),还可以扩展到最多16个NAS集群 上。第二级可用年月例如,201011,第三级用日,第四级可选,根据上传量,比如am/pm,甚至小时。最终的目录结构可能会是 e/201008/25/am/e43ae391c839d82801920cf.jpg。rsync备份时可以用脚本只同步某年某日某时的文件,避免计 算大量文件带来的开销。当然最好是能用专门的分布式文件系统或更专业点的存储解决方案。 下面,我们要谈谈代码了。 这一系列的最后一篇写给普通编程人员,如果不感兴趣可直接看本文最后几段。开始设计代码结构之前,先回顾一下之前准备过的事情:我们有负载均衡的 WEB服务器,有主从DB服务器并可能分片,有缓存,有可扩展的存储。在组织代码的各个方面,跟这些准备息息相关,我一二三的列出来分别说,并且每一条都 以“前面讲到”这个经典句式开头,为了方便对照。 别着急看经典句式,我思维跳跃了,插一段。实际开发中,我们总会在性能和代码优雅性上作折中。对于当今的计算机和语言解释器,多几层少几层对象调 用、声明变量为Map还是HashMap这种问题是最后才需要考虑的问题,永远要考虑系统最慢的部分,从最慢的部分解决。例如看看你用的ORM是不是做了 很多你用不到的事情,是不是有重复的数据调用。我们做的是web应用开发,不是底层框架API,代码易读易懂是保证质量很重要的一方面,你的程序是为了什 么而设计,有不同的方法……算了,这个话题另起一篇文章来说,扯远了,想交流可关注我的微博 http://t.sina.com.cn/liuzhiyi,咱继续…… 前面讲到,WEB 服务器是要做负载均衡的,图片服务器是要分开的。对于这点,代码在处理客户端状态时,不要把状态放到单机上,举例,不要用文件session,嗯,常识。 如果有可能,最好在一开始就做好用户单点认证的统一接口,包括跨域如何判断状态、静态页面如何判断状态,需要登录时的跳转和返回参数定义,底层给好接口, 应用层直接就用(可参考GAE的 user服务)。登录方面的设计要考虑移动设备的特性,比如电脑可以用浮动层窗口,但NOKIA自带的浏览器或UCWEB就无法处理这种表现形式,程序一 定既能处理AJAX请求又能直接通过URL来处理请求。图片服务器分开,资源文件最好也布局到图片服务器,也就是WEB服务器只服务动态程序。虽然开发测 试时稍微复杂(因为需要绝对URI才能访问),但将来页面前端优化上会轻松许多,并且你的WEB服务器IO优化也轻松许多。程序引用资源文件时,要有一个 统一的处理方法,在方法内部可以自动完成很多事情,例如将css/js根据组合,拼成一个文件,或者自动在生成的URI后面加上QUERYSTRING, 如果将来前端用了缓存服务,那生成QUERYSTRING是最简单的刷新服务端缓存和客户端缓存的办法。 前面讲到, 数据库会有复制,可能会多主多从,可能会分片。我们程序在处理数据的过程中,最好能抽象出来单独放做一层。拿现在流行的MVC模式来说,就是在M层下方再 放一个数据层,这个数据层不是通常所说的JDBC/PDO/ActiveRecord等,而是你自己的存取数据层,仅对外暴露方法,隐藏数据存取细节。这 个数据层内部不要怕写的难看,但一定要提供所有的数据存储功能,其他任何层次不要看到跟数据库打交道的字眼。之所以这样做,是因为在单关系数据库的情况 下,可能会SELECT…JOIN…或直接INSERT…INTO…,可你可能会将一些表放到key-value数据库里存储,或者分片,这么做之后原来 的语句和方式要全部改变,如果过于分散,则移植时会耗费很大精力,或得到一个很大的Model。在数据层面的设计上,尽量避免JOIN查询,我们可以多做 冗余,多做缓存,每种数据尽量只需要一次查询,然后在你的程序里面进行组合。对于比较复杂的数据组合,在实时性要求不高的情况下,可采用异步处理,用户访 问时只取处理后的结果。在对于主键的处理上,避免使用自增ID,可以用一定规则生成的唯一值当做主键,这种主键是最简单的分片分布策略。即使用自增ID, 也最好用一个自增ID发生器,否则从数据库不小心被写了一下,那主键很容易冲突。 前面讲到,咱数据库前面还有某些缓存挡着。别把 mysql的query cache当缓存,应用稍复杂的时候QUERY CACHE反而会成为累赘。缓存跟数据库和业务结合的很紧密,正因为跟业务关系紧密,所以这点没有放之四海而皆准的方法。但我们还是有一些规则可参照。规 则一:越接近前端,缓存的颗粒度越大。例如在WEB最前端缓存整个页面,再往后一层缓存部分页面区域,再往后缓存区域内的单条记录。因为越靠近后端,我们 的可操作性越灵活,并且变化最多的前端代码也比较方便编写。在实践中,因为产品需求变化速度非常快,迭代周期越来越短,有时很难将Controller和 Model分的那么清楚,Controller层面处理部分缓存必不可免,但要保证如果出现这种情况,Controller所操作的缓存一定不要影响其他 数据需求方,也就是要保证这个缓存数据只有这一个Controller在用。规则二:没有缓存时程序不能出错。在不考虑缓存失效引发的雪崩效应时,你的程 序要有缓存跟没缓存一个样,不能像新浪微博一样,缓存一失效,粉丝微博全空,整个应用都乱套了。在缓存必不可少的情况下,给用户出错信息都比给一个让人误 解的信息强。规则三,缓存更新要保证原子性或称作线程安全,特别是采用被动缓存的方式时,很可能两个用户访问时导致同一个缓存被更新,通常情况这不是大问 题,可缓存失效后重建时很可能是引发连锁反应的原因之一。规则四:缓存也是有成本的。不只是技术成本,还有人工时间成本。如果一个功能使用缓存和不使用, 在可预见的访问量情况下区别微小,但使用缓存会使复杂度增加,那就不用,我们可以加个TODO标注,在下次迭代的时候加上缓存处理。 前 面讲到,文件存储是独立的,那么所有的文件操作就都是远程调用。可以在文件服务器上提供一个很简单的RESTful接口,也可以提供xmlrpc 或json serveice,WEB服务器端所生成和处理的文件,全部通过接口通知文件服务器去处理,WEB服务器本身不要提供任何文件存储。你会发现很多大网站的 上传图片跟保存文章是分两步完成的,就是基于这个原因。 以上几条“前面讲到”,其实无数人都讲过,我也只是结合前几篇文章用自己的话重 复了一遍,真正分析起来精髓很简单——除了良好的功能逻辑分层,我们 还要为数据库存储、缓存、队列、文件服务等程序外层资源调用单独设计接口,你可以把你的程序想象成是运行在 Amazon EC2 上并用他的所有web service服务,你的数据库就是它的SimpleDB,你的队列就是他的SQS,你的存储就是他的S3,唯一不同是amazon的接口是远程调用,你的是内部调用。 将支撑服务接口化,意味着将MySQL更换到PostgreSQL不需要更改业务处理程序,移植团队甚至不需要跟业务开发团队过多沟通;意味着业务开发团队是对接口编程而不是对数据库编程;意味着不会因为某个业务开发人员的失误而拖垮性能。 对程序扫盲不感兴趣的直接看这里—— 产 品设计完了,程序框架搭完了,可能有矛盾在这个节骨眼儿产生了。不断有产品设计抱怨说他的创意没实现到预期效果,有程序员抱怨说产品设计不切实 际。这种抱怨多缘于产品人员不懂技术,技术人员不理解产品。从广义上来讲,产品包含市场策略、营销手段、功能设计,产品和技术在争论时往往把焦点放在功能 上,而实际重点是,实现这个功能所消耗的成本跟能这个功能带来的利益能否换算,能否取其轻重。若可以,争议解决。若不能,则抛硬币看运气。因为一个功能的 加强而引发指标井喷,或因项目拖延而导致贻误战机的例子比比皆是。激进的决策者注重利益,保守的决策者注重损失,聪明的决策者会考虑这个问题是否真的那么 严重。 关系到未来的事情谁都说不准,要不怎么说创业一半靠运气呢。不过总有能说的准的事情,那就得靠数据说话。 没有100%也有99.9%的网站安装了访问统计代码,连我的 http://zhiyi.us 也不例外,新闻联播也总说科学决策科学发展的。有了统计,能确定的事情就很多了。例如,可以根据来源-目标转化率来分析哪类渠道的人均获取成本低,根据来 源-内容访问猜测用户跳出率原因,根据用户点击行为判断链接位置是否合理等。将数据以不同方式组合起来,找到内在联系,分析内因外因,制定对应策略,减少 拍脑门决策。靠数据支撑运营是个非常专业的事情,虽然不懂深奥的数学模型不会复杂的公式计算,渐渐学会因为A所以B,因为A和B所以C还是相对简单的。 全系列完毕。老话,大半夜连抽烟带码字的挺伤身,转载请注明出处 文章来源:


企业级项目实战(带源码)地址**:**http://zz563143188.iteye.com/blog/1825168

收集五年的开发资料下载地址: http://pan.baidu.com/share/link?shareid=372668&uk=4076915866/#dir/path=%2F%E5%AD%A6%E4%B9%A0%E6%96%87%E4%BB%B6 http://zhiyi.us/internet/thinking-twice-before-building-your-site-one.html http://zhiyi.us/internet/thinking-twice-before-building-your-site-two.html http://zhiyi.us/internet/thinking-twice-before-building-your-site-final.html

分享到:

主流服务器apache、IIS、tomcat、jboss、 ... | 高性能网站性能优化与系统架构

评论

14 楼 shenfuli 3 小时前

NB,需要加大学习。 13 楼 xyz5201314 2013-05-27

好人一个。d一下。

12 楼 zz563143188 2013-04-28

桃花源记 写道

这得多牛,才能总结出这么多知识啊! 有些只需要知道 11 楼 桃花源记 2013-04-28

这得多牛,才能总结出这么多知识啊!

10 楼 zz563143188 2013-04-18

thrillerzw 写道

有些词不懂,看来我还得努力。 厚积薄发,先把基础知识搞扎实。 9 楼 thrillerzw 2013-04-18

有些词不懂,看来我还得努力。

8 楼 zz563143188 2013-04-16

tss0823 写道

看完了,我是一个字节看下去的,真心觉得不错,有些东西感同身受,当时无法用语言来描述,现在看了楼主的文章,才觉得那些东西我貌似也经历过。总之,谢谢。 可能实际中运用不到这么多知识,但这样可以让我们的知识全面。 7 楼 tss0823 2013-04-16

看完了,我是一个字节看下去的,真心觉得不错,有些东西感同身受,当时无法用语言来描述,现在看了楼主的文章,才觉得那些东西我貌似也经历过。总之,谢谢。

6 楼 zz563143188 2013-04-13

chenhjzn 写道

非常不错 多学习了解 5 楼 chenhjzn 2013-04-13

非常不错

4 楼 zz563143188 2013-04-09

jayluns 写道

非常不错,赞。 只供学习参考 3 楼 jayluns 2013-04-08

非常不错,赞。

2 楼 zz563143188 2013-04-07

shichuanliujie 写道

不错 只供参考引用,扩展眼界 1 楼 shichuanliujie 2013-04-07

不错

发表评论

您还没有登录,请您登录后再发表评论

zz563143188的博客

zz563143188

软件架构师的12项修炼

Posted on

软件架构师的12项修炼

既然来了就要多看几篇博客, 因为每一篇都适合你。如果收藏重复看,你一定能感受到我的正能量。

软件架构师的12项修炼 **

博客分类:

《软件架构师的12项修炼》内容简介:每一位软件开发人员都有一个架构师的梦,但为何真正的软件架构师却寥寥无几?软件开发人员更容易在技术上有所积累和突破,但是技术上的精湛并不足以使你成为一位优秀的软件架构师。合格的软件架构师究竟应该具备哪些能力和素养?本书科学而系统地归纳出软件架构师应该具备的完整能力模型,该能力模型呈一金字塔结构,共分为4层:位于最底层的是技术技能,是软件架构师的基石,属于硬技能;从下往上的三层分别是关系技能、个人技能和商务技能,这些都属于软技能。由于硬技能会随着具体技术领域的不同而千差万别,因此本书假定读者已经具备了这方面的技能;但其他3大方面的软技能却在每个技术领域都适用,是每一位软件架构师的必修课,这是《软件架构师的12项修炼》的核心内容。

为了便于认知和实践,《软件架构师的12项修炼》将3大方面的软技能分为12项:关系技能包含文雅的举止(在任何环境下都能与人文雅相处的能力)、沟通(与人有效交互的能力)、协商(将事情办成的能力)、领导力(通过施加影响力将事情办成的能力)和政治(“政治场合”与人交互的能力)等5项;个人技能包含透明化(使自我、团队关系和项目透明化的能力)、激情(激发和保护激情的能力)和语境切换(将注意力迅速切换到新语境并保持专注的能力)等3项;商务技能包括商务知识(读懂商务语言的能力和了解产品与顾客的能力)、创新(如何通过学习和思考来创新的能力)、实用主义(抓住关键问题的能力)、认知(认知目标、战略及合作伙伴的能力)等4项。 《软件架构师的12项修炼》不仅帮助软件开发人员系统地学习如何修炼这12项软技能,而且还能让他们进一步理解软件架构师的角色和本质,使他们最终突破技术的“天花板”,成为一名合格的软件架构师。

译者序

前 言 致 谢

第一部分 关系技能修炼 第1章 文雅的举止3

1.1 别人怎样评价你3 1.2 技术之天花板4

1.3 变得文雅、专业的途径6 1.3.1 注重关系甚于争执孰对孰错6

1.3.2 学会委派8 1.3.3 生活是有反作用的9

1.3.4 有效沟通之生与死11 1.3.5 要正直诚实而不是率直13

1.3.6 不要掩盖问题—它们以后还会冒出来的14 1.3.7 提供专业的服务16

1.3.8 忘掉以前的冒犯17 1.4 小结19

1.5 参考资料19 第2章 沟通22

2.1 沟通原则23 2.1.1 先听后说24

2.1.2 专心致志24 2.1.3 正面思考25

2.1.4 尽早道歉25 2.1.5 不要在缺陷上招致恼羞成怒26

2.2 沟通策略27 2.2.1 多说“是”,少说“不是”27

2.2.2 在销售过程中建立起信任关系28 2.2.3 特殊场合才说“不”29

2.2.4 抑制想自卫的冲动31 2.2.5 倾听建议来改善合作31

2.2.6 了解别人和自己的沟通需求32 2.2.7 才思敏捷34

2.3 与执行官沟通35 2.3.1 执行官需要信任、忠诚和连贯性35

2.3.2 清晰性甚于完整性36 2.3.3 不要让执行官感到惊讶37

2.4 小结38 2.5 参考资料39

第3章 协商41 3.1 协商原则42

3.1.1 不要让人惊讶42 3.1.2 不要模棱两可43

3.1.3 委派权威而不是义务43 3.1.4 有困难时寻求帮助44

3.1.5 不要掩盖问题44 3.1.6 即使很难,也要坚持做正确的事45

3.2 协商策略45 3.2.1 倾听你的内心呼唤45

3.2.2 设法同意45 3.2.3 不要找分歧47

3.2.4 寻找共同点47 3.2.5 如果无法达到一致,就让所有人稍微不满吧48

3.2.6 将协商作为一种改进措施49 3.3 协商前的工作49

3.3.1 知道哪些是可协商的49 3.3.2 了解如何在单位里游刃有余51

3.3.3 关键决定上寻求合作氛围52 3.3.4 学习文化53

3.3.5 让别人明白你的想法53 3.4 协商的收尾54

3.4.1 捍卫决策的执行54 3.4.2 维护架构决定记录54

3.4.3 你有时会赢,有时会输55 3.4.4 从委派中学习56

3.5 小结56 3.6 参考资料58

第4章 领导力60 4.1 领导力的原则61

4.1.1 建立信任关系61 4.1.2 建立共识62

4.1.3 建立战略伙伴关系(通过关系带来安全)62 4.1.4 要身体力行(为你所说的话带来安全)63

4.1.5 感知风险、评估影响、做出行动(明确风险的清晰度)64 4.1.6 适当处理风险:什么是鞭炮,什么是原子弹(明确影响的清晰度)65

4.2 领导策略66 4.2.1 奥卡姆剃刀法66

4.2.2 展现可视化信息66 4.2.3 领导者要确保事情不跑题67

4.2.4 基于环境推销68 4.2.5 随大流(找机会利用已有的资源)69

4.2.6 关注执行官于认知,而非解决冲突69 4.3 领导的时机70

4.3.1 利用单位的动量70 4.3.2 知道何时伸出援手71

4.3.3 允许其他人学习71 4.3.4 知道何时该卓尔不群72

4.3.5 请求原谅还是征求允许73 4.4 领导别人73

4.4.1 允许别人奉献(不要命令)74 4.4.2 通过影响力激励别人76

4.4.3 确保别人能做主76 4.4.4 处理冲突77

4.5 小结77 4.6 参考资料79

第5章 政治81 5.1 政治的定义81

5.2 政治市场82 5.3 政治环境85

5.3.1 与公司的战略方向保持一致85 5.3.2 理解你所处的文化环境86

5.3.3 及早处理别人关注的问题87 5.3.4 相信你所推销的东西89

5.3.5 不关我的事90 5.3.6 关系很重要(与别人的关系)90

5.4 政治原则91 5.4.1 宽宏大量91

5.4.2 不要为你的价值妥协92 5.4.3 光明正大地竞争92

5.4.4 透明地操作92 5.4.5 你是怎样的人就怎样表现93

5.4.6 帮助别人,不求回报93 5.4.7 认识到生活是反身的93

5.5 政治策略94 5.5.1 帮助别人达成其目标94

5.5.2 学会享受过程而不是目标94 5.5.3 在关键之处力争出色95

5.5.4 愿意就低优先级目标妥协95 5.5.5 不要对别人的糟糕举止采取冒犯的行动96

5.5.6 私下处理人际问题97 5.6 政治时机97

5.6.1 以适时的作风执行事情97 5.6.2 今天失利并不代表明天不会成功98

5.6.3 要认识到政治上你不会是常胜将军99 5.6.4 积极参与政治游戏99

5.7 成为一名好的政治人物100 5.8 参考资料101

第二部分 个人技能修炼 第6章 透明化105

6.1 住在玻璃房中的架构师105 6.2 透明化的类型106

6.3 自我透明化107 6.3.1 表现自然真诚107

6.3.2 承认自己的弱点108 6.3.3 承认你的实力和兴趣109

6.3.4 赶在人前与上司沟通110 6.4 项目透明化111

6.4.1 让执行官看到你手里所有的扑克牌111 6.4.2 架构师把透明化和清晰性带到许多领域112

6.4.3 架构师将“发现”变成“收获”113 6.5 关系透明化116

6.5.1 该信任时就给别人信任116 6.5.2 你说的话长久不变117

6.5.3 道歉表明你的透明化118 6.5.4 学会在做出反应前倾听(寻求透明化)118

6.5.5 允许别人对你透明化119 6.6 成为一名透明的架构师119

6.7 参考资料120 第7章 激情122

7.1 什么是激情123 7.2 发现激情124

7.2.1 如何找到激情124 7.2.2 恒心与激情:终极的杀手组合125

7.2.3 岗位上的激情126 7.2.4 重新点燃激情127

7.3 将激情作为向导127 7.3.1 等待机遇:它经常在找你,说话非常轻128

7.3.2 跟着直觉走129 7.3.3 选择你有激情的领域129

7.3.4 改变会督促你前行130 7.3.5 缺乏激情会成为你事业上升的天花板131

7.3.6 把难事做好,尽心尽力投入131 7.3.7 激情是提供动力的内在燃料132

7.4 保护你的激情132 7.4.1 忽略批评:这是你的激情、你的认知,不是他们的132

7.4.2 不要分神133 7.5 今天能做什么来追求你的激情134

7.6 学会投入并享受过程135 7.7 成为一名激情四射的架构师135

7.8 参考资料136 第8章 语境切换138

8.1 自我意识语境140 8.1.1 专心致志140

8.1.2 明白你的弱项141 8.1.3 生命中不仅仅有工作141

8.1.4 多任务工作的效率奥秘141 8.1.5 控制你的肾上腺素:慢下来142

8.2 架构意识语境142 8.2.1 使用“可/有…性”的字眼142

8.2.2 寻求适当的耦合性和内聚性142 8.2.3 持续构建你的语境143

8.3 “大象”语境144 8.3.1 哪些事没有提到144

8.3.2 提问一些难题145 8.3.3 早些发出坏消息145

8.3.4 如果他们拥有这个公司,他们会怎么做146 8.4 决策意识语境146

8.4.1 他们真的已经把问题解决了146 8.4.2 他们知道哪些替代方案可行吗147

8.4.3 别人是否已经权衡过此技术147 8.4.4 作为中立的第三方,即便这样做是个缺点147

8.5 交谈语境148 8.5.1 不要开会和用电子邮件148

8.5.2 如果需要,(马上)让别人参与进来148 8.6 谈话者语境148

8.6.1 了解你的谈话对象148 8.6.2 中庸之道149

8.6.3 有时要唱红脸,有时要唱白脸149 8.6.4 提供背景信息149

8.7 项目语境150 8.7.1 提出预算150

8.7.2 带来实用性151 8.7.3 学会在雪崩中冲浪151

8.7.4 挑出专门的资源151 8.7.5 你做出了哪些假设条件152

8.8 成为一名善于察言观色、见风使舵的架构师152 8.9 参考资料154

第三部分 商务技能修炼 第9章 商务知识157

9.1 了解商务159 9.1.1 营销、财务(投入产出比)和销售159

9.1.2 考虑拿一个商务学位161 9.2 了解你的公司162

9.2.1 了解产品对客户的价值所在162 9.2.2 知道你的公司如何赚钱163

9.2.3 了解你公司的历史、文化163 9.3 了解你的顾客164

9.3.1 考虑拜访顾客、打电话给销售或者在门面上帮员工干活164 9.3.2 考虑参与可用性研究,参与产品概念访谈或其他客户产品评估167

9.3.3 考虑使用敏捷技术167 9.4 了解你的领域167

9.4.1 收集领域知识168 9.4.2 在商务环境中了解你的领域169

9.5 帮助公司更好地了解技术169 9.6 成为一名谙熟商务的架构师170

9.7 参考资料171 第10章 创新173

10.1 创新的定义174 10.2 建立边界条件175

10.2.1 找出边界条件175 10.2.2 在边界内创新176

10.2.3 你会做什么(假如没有约束条件,不必故作姿态)178 10.2.4 鼓励别人思考、开放178

10.2.5 应对那些唱反调的人179 10.2.6 避开唱反调的人,找个安全的地方来思考179

10.3 发展内心准则179 10.3.1 顺从你的直觉179

10.3.2 学会信任自己180 10.3.3 认真倾听客户的声音,但要保持自己的认知180

10.3.4 听听别人的话(协作)181 10.3.5 你今天能迈出一小步吗181

10.3.6 今天不行没关系:继续埋头苦干,早晚会成功的182 10.4 组合基本概念182

10.4.1 阅读、阅读、还是阅读183 10.4.2 疯狂的主意让你发现真正的边界183

10.4.3 要有大眼光184 10.4.4 创新者的困难抉择184

10.4.5 创新与集聚:将事情按正确分组整合在一起184 10.4.6 选择简洁185

10.4.7 简洁性是知识产权的根本185 10.4.8 在着手解决前先思考问题186

10.4.9 定义问题186 10.4.10 睡觉时思考187

10.4.11 战略问题还是战术问题187 10.5 成为一名能创新的架构师187

10.6 参考资料189 第11章 实用主义191

11.1 实用型架构的定义191 11.2 范围管理192

11.2.1 与商务伙伴一起确定特性的优先级192 11.2.2 帮助执行官做出正确决策193

11.2.3 处理不确定性193 11.2.4 有些时候,你只需要一个概念就能开始干了193

11.2.5 使用敏捷过程作为一种实用主义方法194 11.3 风险管理194

11.3.1 区分可能性和可行性194 11.3.2 对于每个决定,都自问一些重要的问题196

11.3.3 应对可能的风险197 11.3.4 架构刺探197

11.3.5 与运营人员一起确定效率197 11.3.6 观察其他项目,决定有哪些地方是可牺牲的198

11.4 沟通198 11.4.1 记录下大家一致同意的决议199

11.4.2 提供多种替代方案,并推荐其中一种199 11.4.3 用透明性拉平期望值199

11.4.4 发展经验方法来估量项目200 11.5 成为一名实用主义的架构师200

11.6 参考资料201 第12章 认知203

12.1 认知之定义204 12.2 找寻和创立引人注目的目标204

12.2.1 发现认知204 12.2.2 从混沌现实编造出有说服力的故事206

12.2.3 克服障碍207 12.3 开发与建立战略路线图208

12.3.1 将路线映射至认知208 12.3.2 制定支持认知的战略209

12.4 确定志同道合的伙伴210 12.4.1 认知需要齐心协力210

12.4.2 认知要求有关键的利益相关者211 12.4.3 认知需要资金支持212

12.5 实践认知213 12.5.1 将认知当做增加投入产出比的战略213

12.5.2 使用认知灌输目标感213 12.5.3 在项目评估时就应用认知214

12.5.4 采用支出信封(界定认知范围)215 12.6 成为一名有远见的架构师215

12.7 参考资料216

企业级项目实战(带源码)地址http://zz563143188.iteye.com/blog/1825168 资料下载地址: http://pan.baidu.com/share/link?shareid=372668&uk=4076915866 收集五年的开发资料下载地址: http://pan.baidu.com/share/link?shareid=372668&uk=4076915866/#dir/path=%2F%E5%AD%A6%E4%B9%A0%E6%96%87%E4%BB%B6

全国(大学)高等教育各学科视频教学全集

Posted on

既然来了就要多看几篇博客, 因为每一篇都适合你。如果收藏重复看,你一定能感受到我的正能量。

全国(大学)高等教育各学科视频教学全集 **

博客分类:

  • 编程经验 并行编程并发阻塞非阻塞编程

    为了方便已就业的朋友再学学习,提供一篇覆盖的教程有计算机类全部,机械类,土木建筑类,财经管类 ,电气类,法学类 ,广告类,医学,心理学,大学英语,大学物理,高等数学,大学化学,哲学 应有尽有。常言道:"书山有路勤为径,学海无涯苦作舟。"无止境地学习,是每一个智者所必需的。人要想不断地进步,就得活到老、学到老。这是我无意中看到的收藏了,欢迎有兴趣的朋友学习。

企业级项目实战(带源码升级版本)地址:http://zz563143188.iteye.com/blog/1845469 收集五年的开发资料及源码下载地址: http://pan.baidu.com/share/link?shareid=372668&uk=4076915866/#dir/path=%2F%E5%AD%A6%E4%B9%A0%E6%96%87%E4%BB%B6

请下载codeFactory20130321,lib20130321文件,

J2EE整个视频教程下载地址:http://www.verycd.com/topics/93279/

北京尚学堂视频教程下载地址 http://www.bjsxt.com/shipinxiazai/

私塾视频教程下载地址 http://sishuok.com/

传智博客视频教程下载地址 http://www.itcast.cn/channel/video.shtml

张孝详视频教程下载地址 http://www.verycd.com/topics/239368/

计算机类 计算机类 数据结构(37课时) http://www.da-fan-shu.cn/20100415_952/ 汇编语言 (44课时) http://www.da-fan-shu.cn/20100415_948/ 计算机组成原理 (50课时) http://www.da-fan-shu.cn/20100327_905/ 计算机文化基础(28课时) http://www.da-fan-shu.cn/20100326_902/ 程序设计基础(42 课时) http://www.da-fan-shu.cn/20100326_900/ IBM-PC汇编语言程序(44课时) http://www.da-fan-shu.cn/20100303_593/ 信息科学基础(49课时) http://www.da-fan-shu.cn/20091022_450/ 线性代数与数理统计(51课时) http://www.da-fan-shu.cn/20100303_595/ 计算机专业英语 (48课时) http://www.da-fan-shu.cn/20100303_589/ web技术基础(38课时) http://www.da-fan-shu.cn/20100303_588/ 数据库原理及应用(25课时) http://www.da-fan-shu.cn/20091022_448/ internet实用技术(37课时) http://www.da-fan-shu.cn/20091022_447/ 编译原理(40课时) http://www.da-fan-shu.cn/20091022_446/ 汇编语言(64课时) http://www.da-fan-shu.cn/20091022_445/ 计算机软件基础(54课时) http://www.da-fan-shu.cn/20091022_444/ 有限元及程序设计(54课时) http://www.da-fan-shu.cn/20091022_443/ 微机原理(47课时) http://www.da-fan-shu.cn/20091022_442/ 网络营销(49课时) http://www.da-fan-shu.cn/20091022_441/ 操作系统(47课时) http://www.da-fan-shu.cn/20091022_440/ 数据通信与网络(40课时) http://www.da-fan-shu.cn/20091022_439/ 信息管理学(27课时) http://www.da-fan-shu.cn/20091022_438/ 网页设计与制作(53课时) http://www.da-fan-shu.cn/20091022_437/ 数据库语言(55课时) http://www.da-fan-shu.cn/20091022_436/ C语言(32课时) http://www.da-fan-shu.cn/20091022_435/ 软件工程(40课时) http://www.da-fan-shu.cn/20091022_434/ 嵌入式系统(25课时) http://www.da-fan-shu.cn/20100310_652/ 机械类 互换性与测量技术(38课时) http://www.da-fan-shu.cn/20100417_959/ 机械制造工艺学(35课时) http://www.da-fan-shu.cn/20100415_950/ 工程热力学(53课时) http://www.da-fan-shu.cn/20100331_922/ 工程材料(40课时) http://www.da-fan-shu.cn/20100330_919/ 自动控制原理(25课时) http://www.da-fan-shu.cn/20100330_918/ 汽车理论基础(36课时) http://www.da-fan-shu.cn/20100329_911/ 工程力学(48课时) http://www.da-fan-shu.cn/20091022_281/ 计算机辅助设计(38课时) http://www.da-fan-shu.cn/20091022_280/ 机械制图(40课时) http://www.da-fan-shu.cn/20091022_279/ 弹性力学(58课时) http://www.da-fan-shu.cn/20100327_906/ 理论力学 (72课时) http://www.da-fan-shu.cn/20100322_879/ 机械设计(64课时) http://www.da-fan-shu.cn/20091022_278/ 控制工程(60课时) http://www.da-fan-shu.cn/20091022_277/ 数控机床故障诊断与维修(8课时) http://www.da-fan-shu.cn/20100320_823/ 电机学(32课时) http://www.da-fan-shu.cn/20091022_275/ 机床概论(26课时) http://www.da-fan-shu.cn/20091022_274/ 工程测试技术基础(12课时) http://www.da-fan-shu.cn/20100325_897/ 土木建筑类 土木工程概论(22课时) http://www.da-fan-shu.cn/20100416_957/ 桥梁施工技术(26课时) http://www.da-fan-shu.cn/20100416_958/ 工程地质(20课时) http://www.da-fan-shu.cn/20100416_956/ 建筑制图(上)(35课时) http://www.da-fan-shu.cn/20091022_421/ l 建筑制图(下)(26课时) http://www.da-fan-shu.cn/20091022_422/ 材料力学(48课时) http://www.da-fan-shu.cn/20091022_420/ 混凝土结构(31课时) http://www.da-fan-shu.cn/20100402_926/ 抗震结构设计(30课时) http://www.da-fan-shu.cn/20091022_418/ 钢结构(31课时) http://www.da-fan-shu.cn/20091022_417/ 建筑设备(32课时) http://www.da-fan-shu.cn/20091022_416/ 土力学与地基基础(64课时) http://www.da-fan-shu.cn/20091022_415/ 工程监督概论(48课时) http://www.da-fan-shu.cn/20091022_414/ 建筑环境学(30课时) http://www.da-fan-shu.cn/20100323_886/ 工程概预算(37课时) http://www.da-fan-shu.cn/20091022_412/ 钢筋混泥土结构(52课时) http://www.da-fan-shu.cn/20091022_411/ 结构力学(45课时) http://www.da-fan-shu.cn/20091022_410/ 房屋建筑学(51课时) http://www.da-fan-shu.cn/20091022_409/ 混泥土结构与砌体结构(50课时) http://www.da-fan-shu.cn/20091022_408/ 结构计算软件(15课时) http://www.da-fan-shu.cn/20091022_425/ 定性结构力学(12课时) http://www.da-fan-shu.cn/20100323_883/ 财经管类 市场营销学(60课时) http://www.da-fan-shu.cn/20100409_939/ 会计学基础(58课时) http://www.da-fan-shu.cn/20091022_326/ 经贸知识英语(57课时) http://www.da-fan-shu.cn/20091022_325/ 国际市场营销(43课时) http://www.da-fan-shu.cn/20091022_327/ 网络营销模拟(49课时) http://www.da-fan-shu.cn/20091022_441/ 政府与事业单位会计(64课时) http://www.da-fan-shu.cn/20091022_329/ 西方财务会计(45课时) http://www.da-fan-shu.cn/20091022_329/ 高级财务会计(47课时) http://www.da-fan-shu.cn/20091022_331/ 高级审计学(48课时) http://www.da-fan-shu.cn/20091022_332/ 成本会计(42课时) http://www.da-fan-shu.cn/20091022_334/ 电气类 电子信息工程导论 (24课时) http://www.da-fan-shu.cn/20100417_963/ 集成电路及应用(32课时) http://www.da-fan-shu.cn/20100417_962/ 电子线路EDA (35课时) http://www.da-fan-shu.cn/20100417_961/ 电路基础(54课时) http://www.da-fan-shu.cn/20091022_538/ 电工技术(45课时) http://www.da-fan-shu.cn/20091022_536/ 电子技术(64课时) http://www.da-fan-shu.cn/20091022_537/ 现代检测技术(37课时) http://www.da-fan-shu.cn/20100417_960/ 法学类 律师实务(48课时) http://www.da-fan-shu.cn/20091022_284/ 法理学(64课时) http://www.da-fan-shu.cn/20091022_302/ 公司法(48课时) http://www.da-fan-shu.cn/20091022_298/ 合同法(48课时) http://www.da-fan-shu.cn/20091022_299/ 劳动法学(48课时) http://www.da-fan-shu.cn/20091022_297/ 证据法(48课时) http://www.da-fan-shu.cn/20091022_296/ 国际技术贸易法(36课时) http://www.da-fan-shu.cn/20091022_309/ 广告类 影视广告设计与制作(10课时) http://www.da-fan-shu.cn/20100319_812/ 广告摄影(24课时) http://www.da-fan-shu.cn/20100316_772/ 广告设计(20课时) http://www.da-fan-shu.cn/20100316_771/ 广告概论(6课时) http://www.da-fan-shu.cn/20100316_770/ 广播电视广告业务(8课时) http://www.da-fan-shu.cn/20100316_767/ 广告策划(20课时) http://www.da-fan-shu.cn/20091022_505/ 广告经营(20课时) http://www.da-fan-shu.cn/20091022_487/ 医学 金匮要略(25课时) http://www.da-fan-shu.cn/20100401_923/ 中医美容学(40课时) http://www.da-fan-shu.cn/20100331_920/ 推拿治疗学(26课时) http://www.da-fan-shu.cn/20100330_916/ 成人护理学(16课时) http://www.da-fan-shu.cn/20100330_915/ 妇产科(16课时) http://www.da-fan-shu.cn/20100324_892/ 药用植物学(43课时) http://www.da-fan-shu.cn/20100324_889/ 定量生理学(46课时) http://www.da-fan-shu.cn/20100311_657/ 传染病学(16课时) http://www.da-fan-shu.cn/20100308_641/ 心理学 管理心理学(35课时) http://www.da-fan-shu.cn/20091022_363/ 社会心理学(32课时) http://www.da-fan-shu.cn/20091022_475/ 消费心理学(20课时) http://www.da-fan-shu.cn/20091022_492/ 教育心理学(20课时) http://www.da-fan-shu.cn/20091022_535/ 儿童发展心理学(12课时) http://www.da-fan-shu.cn/20100316_764/ 旅游心理学(8课时) http://www.da-fan-shu.cn/20100321_854/ 其它视频 大学英语 http://www.da-fan-shu.cn/20091022_461/ 大学语文 http://www.da-fan-shu.cn/20091022_462/ 大学物理 http://www.da-fan-shu.cn/20091022_467/ 高等数学 (44课时) http://www.da-fan-shu.cn/20100306_612/ 离散数学(55课时) http://www.da-fan-shu.cn/20091022_468/ 美术基础(2课时) http://www.da-fan-shu.cn/20091022_495/ 素描(10课时) http://www.da-fan-shu.cn/20091022_494/ 大学化学 http://www.da-fan-shu.cn/20091022_500/ 硬笔书法 http://www.da-fan-shu.cn/20091022_516/ 变化中的英语 http://www.da-fan-shu.cn/20091022_512/ 高级日常英语 http://www.da-fan-shu.cn/20091022_511/ 哲学 http://www.da-fan-shu.cn/20091022_478/

//////////////////////一些牛人的博客://///////////////////////////////////////// ID 博客地址 v_JULY_v http://blog.csdn.net/v_JULY_v luozhuang http://blog.csdn.net/luozhuang norains http://blog.csdn.net/norains tianlesoftware http://blog.csdn.net/tianlesoftware haoel http://blog.csdn.net/haoel/ 27 http://blog.csdn.net/csh624366188 26 http://felixyan.blog.51cto.com/ 25 http://wangchunhai.blog.51cto.com/ 24 http://21cnbao.blog.51cto.com/ 23 http://yunli.blog.51cto.com/ 22 http://blog.csdn.net/muge0913 21 http://blog.csdn.net/cheny_com 20 http://blog.csdn.net/java2000_net 19 http://blog.csdn.net/lfsf802 18 http://blog.csdn.net/zhoufoxcn 17 http://blog.csdn.net/mzlqh/article/details/7621307 16 http://blog.csdn.net/MoreWindows 15 http://blog.csdn.net/lee576 14 http://blog.csdn.net/luozhuang 13 http://blog.csdn.net/sunboy_2050 12 http://blog.csdn.net/aomandeshangxiao 11 http://blog.csdn.net/linlin80230619 10 http://hexiaini235.blog.51cto.com/ 9 http://itmydream.blog.51cto.com/ 8 http://johnwang.blog.51cto.com/ 7 http://cwtea.blog.51cto.com/ 6 http://blog.csdn.net/v_JULY_v 5 http://blog.csdn.net/roy_88 4 http://blog.csdn.net/conmajia 3 http://blog.csdn.net/lishehe 2 http://blog.csdn.net/liutengteng130 1 http://blog.csdn.net/lzh1110

/////////////////////一些牛人的博客:////////////////////////////////////////////




专报各大网站漏洞: http://lcx.cc/

专报各大网站漏洞: http://www.wooyun.org/

9854 2126 1941 1705 1560 1378 1259 1177 1058 1001 484 247 186 171 PKAV技术宅交流小组 http://www.pkav.net 网络尖刀(McBang.Com)) http://www.mcbang.com 90Sec http://www.90sec.org freebuf http://www.freebuf.com Insight-Labs http://insight-labs.org shell2us http://shell2us.org 天马行空 http://tmxk.org INSAFE http://www.insafe.xxx HelloWorld(乌云分舵) http://zone.wooyun.org/zone/java 80sec http://www.80sec.com NEURON http://bbs.ngsst.com/ 暗影团队 http://www.anying.org 08安全团队 http://www.08sec.com Pax.Mac-Team http://www.paxmac.org

/////////////////////////////////////////////数据库/////////////////////////////////////*

数据库

Oracle

常用的oracle 语句宝典.doc - Oracle - OPEN开源文档 ORA-01033 ORACLE initialization or shutdown in progress错误正解_gugelu新浪博客 oracle 创建表空间,表,以及用户?海底苍鹰(tank)博客 Oracle数据库备份与还原常用批处理命令usench百度空间 Oracle经验集锦 - - ITeye技术网站 [书摘]Oracle PL_SQL程序设计 - CSDN.NET - CSDN软件研发频道 Windows 7 SP1无法安装oracle10g 11g的解决办法(转) - wawlian的学习笔记 - ITeye技术网站 10203vista_w2k8_x86_production_db.zip在win7上的安装方法原 来 是 爱_百度空间 如何写批处理文件自动将数据导入oracle数据库 - 开发笔记 - ITeye技术网站 导入命令出错,咋回事呢?急求。。 - Oracle _ 基础和管理 解决在Windows7下Oracle10G无法安装问题 - alex - ITeye技术网站 乌托邦博客-ORA-12514_ TNS_listener does not currently know of service requested in connect oracle数据库文件中的导入_导出(imp_exp命令)-Oracle教程-www.knowsky.com oracle 创建表空间,表,以及用户«海底苍鹰(tank)博客 Oracle笔记 五、创建表、约束、视图、索引、序列、同义词、表空间 - hoojo - 博客园 110个oracle常用函数总结 - Oracle _ 开发 Oracle SQL 内置函数大全(1) - 51CTO.COM oracle中的表空间(tablespace)、方案(schema)、段(segment)、区(extent)、块(block) - gskcc - 博客园 在oracle中查看用户的对象 - 寒惜祉的日志 - 网易博客 数据库Oracle中分区表的使用 - oracle技术 - bealla oracle 创建表时 如何指定将表创建到哪个表空间_百度知道 未公开的Oracle数据库秘密(大师秘笈助你内外兼修) - china-pub网上书店 Oracle用户权限 - cosio的专栏 - CSDN博客 请教如何使得一个Oracle用户访问指定的多个表空间(非使用同义词) - 其他数据库开发 _ SQL Anywhere Studio 使用Oracle Imp和Exp工具实现导入和导出数据心灵净土百度空间 ORACLE学习中常用SQL技巧(下)_技术资料 ORACLE常用命令-我的知识库 转载----PL_SQL Developer技巧 - huozhicheng的专栏 - CSDN博客 iSQL_Plus 发行版 10.1.0.2 oracle sqlplus 常用命令大全,Oracle技术教程,Oracle系列教程,Oracle oracle中ERROR - ORA-12541 TNS无监听程序的解决办法就该这样百度空间 Oracle Enterprise Manager Oracle Enterprise Manager - 编辑 表空间_ UNDOTBS1 David Dai -- Focus on Oracle - 博客频道 - CSDN.NET Win7 下 Oracle 11g 安装步骤(图文).pdf - Oracle - OPEN开源文档

MySQl

java 连接 mysql 避免中文乱码的相关文章推荐 - - ITeye专栏频道 下载详细信息_ Microsoft SQL Server 2000 Service Pack 4 四大主流数据库比较 - MySQL - 51CTO技术论坛_中国领先的IT技术社区 Mysql和SqlServer互相转换 - losesea - 博客园

SQL

SQL MSSQL 常用代码大全MsSql脚本之家 sql 2005 用户 sa 登录失败,该用户与可信SQL Server连接无关联 错误18452 - SjrHero - 博客园 SQL Server常用小代码收藏 . - 夏楚枫 - 博客园 Sql Server 2005 用户 'sa' 登录失败。该用户与可信 SQL Server 连接无关联_百度文库 怎么使Sql Server的存储过程为不能修改状态或不能打开? - MS-SQL Server _ 基础类 SQL优化 - - ITeye技术网站 一些不错的sql语句 - 点点知识小屋 - ITeye技术网站 SQL Server函数大全 - 热学沸腾的专栏 - CSDN博客 SQL 函数 函数大全 - EWang - 博客园 sql中英文对照_百度文库 在SQL Server中通过SQL语句实现分页查询 JDBC连接SqlServer2000出现Connection refused connect_的处理 - 水乡情的日志 - 网易博客 利用SQL注入漏洞登录后台 SQL 连接 JOIN 例解。(左连接,右连接,全连接,内连接,交叉连接,自连接) - 冯岩 - 博客园 SQL Server 2000Microsoft SQL Server 2000(SQL2000)官方简体中文版下载 - 下载吧[WwW.XiaZaiBa.Com]绿色下载吧_软件下载:提供最新最安全的绿色软件下载! SQL server 2000个人版 个人版

noSql

NoSQL,关系数据库终结者? NoSQL数据库探讨之一 - 为什么要用非关系数据库? - robbin的自言自语 - JavaEye技术网站

sqlite

Sqlite新手教程 转贴:SQLITE数据类型介绍 百度空间_应用平台

mongdb

MongoDB学习笔记(一) MongoDB介绍及安装 - lipan - 博客园

Access

关于ibatis配置sqlmapconfig.xml连接access数据库成长百度空间

powerdesinger

概念数据模型,逻辑数据模型,物理数据模型(转) - SeekerLee - 博客园 业务模型、数据模型、面向对象模型介绍_网易数码论坛 SQL语句大全大全(经典珍藏版)_百度文库 ////////////////////////////////////////////数据库/////////////////////////////////////

/////////////////////////////////////////////java基础/////////////////////////////////* 常见数据结构的Java实现.pdf - OPEN开源文档 Java 词汇大全.doc - OPEN开源文档 [Charset]UTF-8, UTF-16, UTF-16LE, UTF-16BE的区别_百度文库 原码、补码和反码 - 图码网 - 博客园 软件开发实践的24条军规-CSDN.NET Java之美[从菜鸟到高手演变]之设计模式 - 智慧演绎,无处不在 - 博客频道 - CSDN.NET 专栏:Java基础研究 - 博客频道 - CSDN.NET Java之美[从菜鸟到高手演练]之Comparator和Comparable在排序中的应用 - 智慧演绎,无处不在 - 博客频道 - CSDN.NET Java之美[从菜鸟到高手演变]之字符串 - 智慧演绎,无处不在 - 博客频道 - CSDN.NET 深入浅出CGlib-打造无入侵的类代理 - llying - ITeye技术网站 UML书写的需求规格说明书_百度文库 Java注释规范哦灵魂百度空间 java开发变量命名规范随风去新浪博客 JAVA中String.format的用法 - 云淡风轻、仅此一抹 - 博客频道 - CSDN.NET java中进行二进制,八进制,十六进制,十进制间进行相互转换_百度文库 做项目时需要考虑的安全性问题 - 我期望的世界 - ITeye技术网站 java 之 注册表操作篇 - jimmy - BlogJava 【博客搬家】JAVA如何读写windows注册表 - aboykoy的专栏 - 博客频道 - CSDN.NET java map 遍历的三种简单的办法 - 未来是个梦 - 博客园 Stirng,Stringbuffer,Stringbuild的区别浅淡 - - ITeye技术网站 java.math.BigDecimal类的用法 - - ITeye技术网站 JAVA中数组、链表实现的队列的增加,返回长度,插入,删除 - - ITeye技术网站 javadoc - jinc - 博客园 双链表插入自动排序 - langzhe - ITeye技术网站 环形双链表与蛋疼的链表反转 - langzhe - ITeye技术网站 原码、反码、补码和移码其实很简单 - 刘水镜 快乐编程,无压工作 - 博客频道 - CSDN.NET Java网络编程-编码、构建与集成-文库-火龙果软件 Java类集对Enum的支持玲珑齐百度空间 JDK源码研究TreeMap(红黑树)上篇 - wsc - ITeye技术网站 Comparable Comparator具体区别 - ITeye问答 优先队列与堆的解析 - - ITeye技术网站 Java中堆内存和栈内存详解 - 蛊惑Into - 博客园 JAVA中實現鏈表--LinkedList的使用 - 用心做事,诚信做人! - ITeye技术网站 JAVA实现双向链表 - 冯立彬的博客 - 博客频道 - CSDN.NET java 判断类和实例的关系(instanceof,isInstance,isAssignableFrom) - feiling - 博客园 Hibernate中Criteria的完整用法 - 溺水的鱼 - Later equals never. - 博客频道 - CSDN.NET 软件开发模式对比(瀑布、迭代、螺旋、敏捷) - OYK - 博客园

Collection , List , Set 和 Map 用法和区别 - JeamKing的专栏 - CSDN博客

Java语言中链表和双向链表 Java,链表,双向链表 [程序开发Java] IT.com.cn IT世界网

JAVA经典算法40例.doc - OPEN开源文档 Java 中Iterator 、Vector、ArrayList、List 使用深入剖析 - Aaron的笔记 - 51CTO技术博客 ////////////////////////////////////////////基础///////////////////////////////*/

智慧

关于易经的几点启示(刘文长)_百度文库 鬼谷子的启示之一:纵横捭阖培训实战家新浪博客 《道德经》的启示---序言目录邹范平_新浪博客 易经的智慧 (世界文明讲坛) 曾仕强 - 视频豆单合集 - 土豆网 鬼谷子纵横智慧 - 专辑 - 优酷视频 说话就是生产力 - 专辑 - 优酷视频 鬼谷子纵横智慧 - 视频豆单合集 - 土豆网 五行之术(基础篇) - 专辑 - 优酷视频 求五行之术,奇门遁甲之术 - 已解决 - 搜搜问问 宇宙速度_百度百科 吉林大学视频 - 吉大 吉林大学 国际商务管理 视频教程第20讲 - 视频 - 优酷视频 - 在线观看 哲学论文:逻辑学,中国哲学,西方哲学,思想哲学,科技哲学,美学,国学等论文 中国地理 道德经读后感_百度文库 鬼谷子七十二计术_百度文库 论中国人和西方人的思维方式_英语论文网 所队领导应有多种思维方式_英语论文网 阿q精神_百度百科 丑陋的中国人_百度百科 中庸思想的核心是什么_百度知道 四书五经指的是什么?_百度知道 于丹论语感悟1czdjy6613新浪播客 百度搜索_于丹论语视频

中国社会工程学联盟 Metasploit 鑫宇网络论坛 易我网安 道哥的黑板报 FreebuF.COM 小伟'S blog 河马安全网 BlackWidow7's Blog Coolboy'blog 猴子'Blog 雨路博客 网络安全资讯 胡士斌‘s Blog YesCK's Blog 乐乐's Blog 狗一样的男人's Blog sh3llc0de安全小组 n42b luom 3HACK 独狼博客 Txmg'Blog DisKill 'Blog 华西安全 邪红色组织 90' s Blog clzzy's blog fate's blog BccSafe's Blog 小马's Blog Cr0ss1n's Blog 最爱保时捷911 y0umer HuGtion's Blog 安全基地 imlonghao C 网络 Tr0jan's Blog 魅影博客 中国八一黑客军区 LinuxNote Volltin's Blog Foraya'blog iceforce's blog 冰刀博客 leo108's blog kissthink 破冰's Blog dashige's 捕捞歌 ITLEAF's BLOG Koohik' Bolg Yaseng' Bolg 安全团队导航 非安全中国网 混世魔王 羽翼's blog 情'S Blog xahzad 博客 信息安全集结 piaoyu's blog 黑阔站长吧 WebShell'S Blog 落雪依然' blog 末日'blog 陈可逆 's Blog 羽落's Blog Ay暗影'blog ITrobin(IT.知更鸟) 安静的石头 iick's blog 彼岸花 ┽低調X﹏X Mr.DzY VB技巧 F4ust 黑帽Seo 神刀网 oldjun

6

1

分享到:

Spring mvc+hibernate+freemarker(开源项目 ... | 基于SSH框架多层结构的代码生成工具

评论

6 楼 lizheng19922 2 小时前

感谢分享这么多知识。 5 楼 zz563143188 前天

greatwqs 写道

慢慢学习吧

4 楼 greatwqs 前天

3 楼 xumin198908 2013-05-10

源码包里面缺少类:cn.org.rapid_framework.generator.provider.db.sql.model.Sql; import cn.org.rapid_framework.generator.provider.db.sql.model.Sql; import cn.org.rapid_framework.generator.provider.db.sql.model.SqlParameter;

2 楼 zz563143188 2013-04-24

zbz 写道

可以生成一对一关系的JPA实体吗 可以,不过要自己写代码实现,模板有。 1 楼 zbz 2013-04-24

可以生成一对一关系的JPA实体吗

我心目中最好的框架组合是

Posted on

我心目中最好的框架组合是

既然来了就要多看几篇博客, 因为每一篇都适合你。如果收藏重复看,你一定能感受到我的正能量。

我心目中最好的框架组合是:

表示层:spring mvc 3.1 + annotation 控制层:spring 3.1 持久层:hibernate 3.6 +jdbcTemplate 后台列表控件:displaytag 1.2 Ajax框架: DWR 3 JS框架 : Jquery 缓存机制:spring 3.1 cache + ehcache/memcached 静态化机制: Freemarker静态化/spring mvc伪静态化 页面技术: EL + JSTL +JSP 安全框架 spring security 搜索引擎: Lucene 中文分词:IKAnalyzer 模板引擎: apache tiles 2.22 Linux、nginx、php、mysql,几乎是标配 部署视图所需: 数据库: mysql Web 服务器: windows 下用apache, linux 下用ngnix 应用服务器: Tomcat Jboss,tomcat,weblogic

常用的系统架构是: Linux + Apache + PHP + MySQL + web负载均衡+数据库主从+缓存+分布式存储+队列 Linux + Apache + Java (WebSphere) + Oracle Windows Server 2003/2008 + IIS + C/#/ASP.NET + 数据库

大型动态应用系统又可分为几个子系统: 1)Web前端系统 2)负载均衡系统 3)数据库集群系统 4)缓存系统 5)分布式存储系统 6)分布式服务器管理系统 7)代码分发系统

常用的工具列表

集成ORM hibernate ,jdo,toplink,apache ojb ,ibatis,jpa 集成视图 jsp ,jstl ,tiles,velocity, freemarker,xslt ,pdf/excel,jaseperreports 集成web框架 jsf struts tapestry webwork 整合其它J2EE webserives,ejb jms jmx jca 邮件抽象层,定时调度和线程池,java注解 数据库 mysql ,sqlsever,oralce,sqlite,db2 Ajax框架 ext,jquery ,prototype,dojo,yui, 容器 Jboss,tomcat,weblogic

高级软件工程师的招聘条件

技能技巧要求:

◆熟练使用css语言,对css布局,编写有一定经验; ◆熟练使用jquery语言,能够编写jquery通用插件,且能够阅读复杂的jquery插件; ◆熟练使用spring framework,且阅读过部分sping相关源码; ◆熟悉Web应用多层架构设计; ◆熟悉OO分析设计方法和J2EE 设计模式,具备良好的沟通能力与表达能力; ◆有mongodb,RabbitMQ,Lucence等技术经验更佳; ◆熟悉tocmat,nginx基本工作原理,能够阅读nginx源代码;或者熟悉tcp/ip协议细节; ◆能正常使用linux操作系统,简单管理linux系统; ◆能够根据产品需求文档,编写开发详细文档; ◆能够分析系统基本性能问题,能够mysql性能调优; ◆英语四级以上,能熟练阅读英文技术资料。

学习Web基础(HTML/CSS/JS)+服务器端技术(LAMP)

未来必然是Web的世界,学习Web基础的最佳网站是W3School

  • 学习HTML基本语法
  • 学习CSS如何选中HTML元素并应用一些基本样式(关键词:box model)
  • 学会用 Firefox + Firebug 或 Chrome 查看你觉得很炫的网页结构,并动态修改。
  • 学习使用Javascript操纵HTML元件。理解DOM和动态网页(http://oreilly.com/catalog/9780596527402)网上有免费的章节,足够用了。或参看 DOM
  • 学会用 Firefox + Firebug 或 Chrome 调试 Javascript 代码(设置断点,查看变量,性能,控制台等)
  • 在一台机器上配置ApacheNginx
  • 学习PHP,让后台PHP和前台HTML进行数据交互,对服务器相应浏览器请求形成初步认识。实现一个表单提交和反显的功能。
  • 把PHP连接本地或者远程数据库 MySQL(MySQL 和 SQL现学现用够了)
  • 跟完一个名校的网络编程课程(例如:http://www.stanford.edu/~ouster/cgi-bin/cs142-fall10/index.php )不要觉得需要多于一学期时间,大学生是全职一学期选3-5门课,你业余时间一定可以跟上
  • 学习一个Javascript库(例如jQuery或ExtJS)+ Ajax(异步读入一个服务器端图片或者数据库内容)+ JSON数据格式。
  • HTTP: The Definite Guide 读完前4章你就明白你每天上网用浏览器的时候发生的事情了(proxy, gateway, browsers)
  • 做个小网站(例如:一个小的留言板,支持用户登录,Cookie/Session,增、删、改、查,上传图片附件,分页显示)
  • 买个域名,租个空间,做个自己的网站。
 此学习备忘录只是我工作之外收集的一些资料,只希望能够扩大IT从业人员的知识面。IT的知识很繁多,有此只需要了解知道。此备忘录有硬件方面的,也有软件方面的,也有大IT公司要求的技能。作为新手你可以阅览一下,知识有哪些知识。作为高手,你可以补充一下自己的知识面。

企业级项目实战(带源码升级版本)地址: http://zz563143188.iteye.com/blog/1825168 收集五年的开发资料及源码下载地址: http://pan.baidu.com/share/link?shareid=372668&uk=4076915866/#dir/path=%2F%E5%AD%A6%E4%B9%A0%E6%96%87%E4%BB%B6 13

7

分享到:

关于《深入理解并行编程》一书 | 比较全的OA系统功能模块列表

评论

52 楼 zz563143188 2013-05-23

yaozhuan 写道

yaozhuan 写道

从您百度网盘下载的源码jeecms 运行后碰到一个问题 其他都功能没问题 在后台点 栏目 这个版块的时候tomcat后台报错 root 获取不到值 不知道你又碰到这个问题没 [framework] 2013-05-23 11:28:48,340 -414609 [http-bio-8080-exec-2] ERROR freemarker.runtime - Error on line 34, column 59 in jeecms_sys/channel/list.html Expecting a string, date or number here, Expression root is instead a freemarker.template.SimpleSequence Error on line 34, column 59 in jeecms_sys/channel/list.html Expecting a string, date or number here, Expression root is instead a freemarker.template.SimpleSequence

The problematic instruction:

==> ${root} [on line 34, column 57 in jeecms_sys/channel/list.html]

Java backtrace for programmers:

freemarker.core.NonStringException: Error on line 34, column 59 in jeecms_sys/channel/list.html Expecting a string, date or number here, Expression root is instead a freemarker.template.SimpleSequence 已经解决 if (root == null) { list = manager.getTopList(CmsUtils.getSiteId(request), false); root=0;//加这句代码 } else { list = manager.getChildList(root, false); } 你真厉害,继续努力。 51 楼 yaozhuan 2013-05-23

yaozhuan 写道

从您百度网盘下载的源码jeecms 运行后碰到一个问题 其他都功能没问题 在后台点 栏目 这个版块的时候tomcat后台报错 root 获取不到值 不知道你又碰到这个问题没 [framework] 2013-05-23 11:28:48,340 -414609 [http-bio-8080-exec-2] ERROR freemarker.runtime - Error on line 34, column 59 in jeecms_sys/channel/list.html Expecting a string, date or number here, Expression root is instead a freemarker.template.SimpleSequence Error on line 34, column 59 in jeecms_sys/channel/list.html Expecting a string, date or number here, Expression root is instead a freemarker.template.SimpleSequence

The problematic instruction:

==> ${root} [on line 34, column 57 in jeecms_sys/channel/list.html]

Java backtrace for programmers:

freemarker.core.NonStringException: Error on line 34, column 59 in jeecms_sys/channel/list.html Expecting a string, date or number here, Expression root is instead a freemarker.template.SimpleSequence 已经解决 if (root == null) { list = manager.getTopList(CmsUtils.getSiteId(request), false); root=0;//加这句代码 } else { list = manager.getChildList(root, false); }

50 楼 yaozhuan 2013-05-23

从您百度网盘下载的源码jeecms 运行后碰到一个问题 其他都功能没问题 在后台点 栏目 这个版块的时候tomcat后台报错 root 获取不到值 不知道你又碰到这个问题没 [framework] 2013-05-23 11:28:48,340 -414609 [http-bio-8080-exec-2] ERROR freemarker.runtime - Error on line 34, column 59 in jeecms_sys/channel/list.html Expecting a string, date or number here, Expression root is instead a freemarker.template.SimpleSequence Error on line 34, column 59 in jeecms_sys/channel/list.html Expecting a string, date or number here, Expression root is instead a freemarker.template.SimpleSequence

The problematic instruction:

==> ${root} [on line 34, column 57 in jeecms_sys/channel/list.html]

Java backtrace for programmers:

freemarker.core.NonStringException: Error on line 34, column 59 in jeecms_sys/channel/list.html Expecting a string, date or number here, Expression root is instead a freemarker.template.SimpleSequence 49 楼 zengguoqin520 2013-05-20

很欣赏楼主的分享精神,正能量已收到。

48 楼 zz563143188 2013-05-20

zz563143188 写道

teasp 写道

diggywang 写道

liqingyuan 写道

MrLee23 写道

ajax为什么要用dwr呢?它的优点又是什么呢?想听一听,学习学习 DWR主要是能直接调用后台JAVA方法,而且能够自动封装后台对象为JSON数据。个人观点,DWR最好别用,在前端直接调后台方法这个想法就非常不好——一切设计模式都是为了解耦,DWR反而想去追求把前端和后台耦合到一起,这个想法太奇葩。 所以,还是gwt好,这东西就是开发的时候太耗资源,整个设计架构是非常好超前的。 另外,开发了那么多年,绝大部分情况下ibatis/mybatis足够了。 GWT好在哪里?你怎么用它做项目的?我在08年的时候用它做过一个网站前端,它有个很大的毛病就是第一次访问的时候要下载大量的js代码,因此会等很久,这是很坏的体验。不知道GWT现在是个什么情况了,能否多讲点? 这个内部访问还是可以的,现在ext也不错 用ext太多了,有时看到ext会一种很腻的感觉。 47 楼 zz563143188 2013-05-20

diggywang 写道

teasp 写道

diggywang 写道

liqingyuan 写道

MrLee23 写道

ajax为什么要用dwr呢?它的优点又是什么呢?想听一听,学习学习 DWR主要是能直接调用后台JAVA方法,而且能够自动封装后台对象为JSON数据。个人观点,DWR最好别用,在前端直接调后台方法这个想法就非常不好——一切设计模式都是为了解耦,DWR反而想去追求把前端和后台耦合到一起,这个想法太奇葩。 所以,还是gwt好,这东西就是开发的时候太耗资源,整个设计架构是非常好超前的。 另外,开发了那么多年,绝大部分情况下ibatis/mybatis足够了。 GWT好在哪里?你怎么用它做项目的?我在08年的时候用它做过一个网站前端,它有个很大的毛病就是第一次访问的时候要下载大量的js代码,因此会等很久,这是很坏的体验。不知道GWT现在是个什么情况了,能否多讲点? GWT第一次访问下载js过多问题,你可以根据需要进行分解的,如多module。用google plugin这种自动建的项目默认会第一次下载所有js,你也可以根据需要手动在那个初始html里改掉。 我GWT应用得最多的是企业内部的系统,带宽不是问题,而且一次性加载之后,用户体验非常好。 随着宽带的改善,以后这些问题可能考虑的少了。

46 楼 zz563143188 2013-05-20

teasp 写道

diggywang 写道

liqingyuan 写道

MrLee23 写道

ajax为什么要用dwr呢?它的优点又是什么呢?想听一听,学习学习 DWR主要是能直接调用后台JAVA方法,而且能够自动封装后台对象为JSON数据。个人观点,DWR最好别用,在前端直接调后台方法这个想法就非常不好——一切设计模式都是为了解耦,DWR反而想去追求把前端和后台耦合到一起,这个想法太奇葩。 所以,还是gwt好,这东西就是开发的时候太耗资源,整个设计架构是非常好超前的。 另外,开发了那么多年,绝大部分情况下ibatis/mybatis足够了。 GWT好在哪里?你怎么用它做项目的?我在08年的时候用它做过一个网站前端,它有个很大的毛病就是第一次访问的时候要下载大量的js代码,因此会等很久,这是很坏的体验。不知道GWT现在是个什么情况了,能否多讲点? 这个内部访问还是可以的,现在ext也不错 45 楼 zz563143188 2013-05-20

white_crucifix 写道

几年前用过GWT-ext,感觉还不错,总体来说我还是比较有兴趣的。 不过后来自从用了原生Extjs,就再也懒得用GWText了,呵呵 我现在也用ext js多一些。

44 楼 white_crucifix 2013-05-20

几年前用过GWT-ext,感觉还不错,总体来说我还是比较有兴趣的。 不过后来自从用了原生Extjs,就再也懒得用GWText了,呵呵 43 楼 teasp 2013-05-20

diggywang 写道

teasp 写道

diggywang 写道

liqingyuan 写道

MrLee23 写道

ajax为什么要用dwr呢?它的优点又是什么呢?想听一听,学习学习 DWR主要是能直接调用后台JAVA方法,而且能够自动封装后台对象为JSON数据。个人观点,DWR最好别用,在前端直接调后台方法这个想法就非常不好——一切设计模式都是为了解耦,DWR反而想去追求把前端和后台耦合到一起,这个想法太奇葩。 所以,还是gwt好,这东西就是开发的时候太耗资源,整个设计架构是非常好超前的。 另外,开发了那么多年,绝大部分情况下ibatis/mybatis足够了。 GWT好在哪里?你怎么用它做项目的?我在08年的时候用它做过一个网站前端,它有个很大的毛病就是第一次访问的时候要下载大量的js代码,因此会等很久,这是很坏的体验。不知道GWT现在是个什么情况了,能否多讲点? GWT第一次访问下载js过多问题,你可以根据需要进行分解的,如多module。用google plugin这种自动建的项目默认会第一次下载所有js,你也可以根据需要手动在那个初始html里改掉。 我GWT应用得最多的是企业内部的系统,带宽不是问题,而且一次性加载之后,用户体验非常好。 你们是不是把系统做成web桌面这样了?

42 楼 diggywang 2013-05-19

teasp 写道

diggywang 写道

liqingyuan 写道

MrLee23 写道

ajax为什么要用dwr呢?它的优点又是什么呢?想听一听,学习学习 DWR主要是能直接调用后台JAVA方法,而且能够自动封装后台对象为JSON数据。个人观点,DWR最好别用,在前端直接调后台方法这个想法就非常不好——一切设计模式都是为了解耦,DWR反而想去追求把前端和后台耦合到一起,这个想法太奇葩。 所以,还是gwt好,这东西就是开发的时候太耗资源,整个设计架构是非常好超前的。 另外,开发了那么多年,绝大部分情况下ibatis/mybatis足够了。 GWT好在哪里?你怎么用它做项目的?我在08年的时候用它做过一个网站前端,它有个很大的毛病就是第一次访问的时候要下载大量的js代码,因此会等很久,这是很坏的体验。不知道GWT现在是个什么情况了,能否多讲点? GWT第一次访问下载js过多问题,你可以根据需要进行分解的,如多module。用google plugin这种自动建的项目默认会第一次下载所有js,你也可以根据需要手动在那个初始html里改掉。 我GWT应用得最多的是企业内部的系统,带宽不是问题,而且一次性加载之后,用户体验非常好。 41 楼 teasp 2013-05-18

diggywang 写道

liqingyuan 写道

MrLee23 写道

ajax为什么要用dwr呢?它的优点又是什么呢?想听一听,学习学习 DWR主要是能直接调用后台JAVA方法,而且能够自动封装后台对象为JSON数据。个人观点,DWR最好别用,在前端直接调后台方法这个想法就非常不好——一切设计模式都是为了解耦,DWR反而想去追求把前端和后台耦合到一起,这个想法太奇葩。 所以,还是gwt好,这东西就是开发的时候太耗资源,整个设计架构是非常好超前的。 另外,开发了那么多年,绝大部分情况下ibatis/mybatis足够了。 GWT好在哪里?你怎么用它做项目的?我在08年的时候用它做过一个网站前端,它有个很大的毛病就是第一次访问的时候要下载大量的js代码,因此会等很久,这是很坏的体验。不知道GWT现在是个什么情况了,能否多讲点?

40 楼 zz563143188 2013-05-15

zz563143188 写道

kjj 写道

nonocast 写道

我心目中最好的框架组合是DIY,呵呵,全部自己写。 全部自己写有那么多时间和精力吗,质量如何呢,还要考时间检验吧 哈哈,是开玩笑的啦 开玩笑的,我们当然不会因为欣赏花就要一个一个细胞的去组合,而只需要找种子慢慢培育。 39 楼 zz563143188 2013-05-15

kjj 写道

nonocast 写道

我心目中最好的框架组合是DIY,呵呵,全部自己写。 全部自己写有那么多时间和精力吗,质量如何呢,还要考时间检验吧 哈哈,是开玩笑的啦

38 楼 kjj 2013-05-14

nonocast 写道

我心目中最好的框架组合是DIY,呵呵,全部自己写。 全部自己写有那么多时间和精力吗,质量如何呢,还要考时间检验吧 37 楼 zz563143188 2013-05-14

white_crucifix 写道

楼主太牛了,所学的知识面超级广啊,从传统web编程,到分布式,还有nosql,以及新型的ngnix似乎也是楼主的心爱。膜拜! PS. 感觉linux上用的最多的web服务器还是apache,除非是处理大数据量高并发可能会力不从心 呵呵,我一个人怎么可能会这么多呢,还都是网络的功效。nosql有前景,以前有sqlite和delphi一起做过项目。

36 楼 white_crucifix 2013-05-14

楼主太牛了,所学的知识面超级广啊,从传统web编程,到分布式,还有nosql,以及新型的ngnix似乎也是楼主的心爱。膜拜! PS. 感觉linux上用的最多的web服务器还是apache,除非是处理大数据量高并发可能会力不从心 35 楼 zz563143188 2013-05-14

xnk9499 写道

博主,可否给个 静态化机制: Freemarker静态化/spring mvc伪静态化 这方面的列子看看 你去看一下这个吧 http://zz563143188.iteye.com/blog/1825168

34 楼 xnk9499 2013-05-14

博主,可否给个 静态化机制: Freemarker静态化/spring mvc伪静态化 这方面的列子看看 33 楼 zz563143188 2013-05-14

galfordliu 写道

jQuery已经有强大的ajax了.为何还要用dwr? 你通过dwr在js脚本中调用业务类,这不是违背了前后台分离的原则么. 金山公司和快玩游戏公司开发项目用Jquery比较多,这也证明了JQuery的强大和优势。Jquery的前后兼容不是很完善,稳定和支持动画方面还有空间。SpringMVC、struts2.0零配置功能让dwrd在js脚本中调用业务类方法显得有意义。

Java开发中的23种设计模式详解

Posted on

Java开发中的23种设计模式详解

设计模式(Design Patterns)

——可复用面向对象软件的基础

设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。 毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样。项目中合理的运用设计模式可以完美的解决很多问题,每种模式在现在中都有相应的原理来与之对应,每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的核心解决方案,这也是它能被广泛应用的原因。本章系Java之美[从菜鸟到高手演变]系列之设计模式,我们会以理论与实践相结合的方式来进行本章的学习,希望广大程序爱好者,学好设计模式,做一个优秀的软件工程师!

在阅读过程中有任何问题,请及时联系:egg。

邮箱:xtfggef@gmail.com 微博:http://weibo.com/xtfggef**

如有转载,请说明出处:http://blog.csdn.net/zhangerqing

企业级项目实战(带源码)地址**http://zz563143188.iteye.com/blog/1825168 23种模式java实现源码下载地址** http://pan.baidu.com/share/link?shareid=372668&uk=4076915866/#dir/path=%2F%E5%AD%A6%E4%B9%A0%E6%96%87%E4%BB%B6

一、设计模式的分类

总体来说设计模式分为三大类:

创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。

结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。

行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

其实还有两类:并发型模式和线程池模式。用一个图片来整体描述一下:

二、设计模式的六大原则

1、开闭原则(Open Close Principle)

开闭原则就是说对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。所以一句话概括就是:为了使程序的扩展性好,易于维护和升级。想要达到这样的效果,我们需要使用接口和抽象类,后面的具体设计中我们会提到这点。

2、里氏代换原则(Liskov Substitution Principle)

里氏代换原则(Liskov Substitution Principle LSP)面向对象设计的基本原则之一。 里氏代换原则中说,任何基类可以出现的地方,子类一定可以出现。 LSP是继承复用的基石,只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为。里氏代换原则是对“开-闭”原则的补充。实现“开-闭”原则的关键步骤就是抽象化。而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。—— From Baidu 百科

3、依赖倒转原则(Dependence Inversion Principle)

这个是开闭原则的基础,具体内容:真对接口编程,依赖于抽象而不依赖于具体。

4、接口隔离原则(Interface Segregation Principle)

这个原则的意思是:使用多个隔离的接口,比使用单个接口要好。还是一个降低类之间的耦合度的意思,从这儿我们看出,其实设计模式就是一个软件的设计思想,从大型软件架构出发,为了升级和维护方便。所以上文中多次出现:降低依赖,降低耦合。

5、迪米特法则(最少知道原则)(Demeter Principle)

为什么叫最少知道原则,就是说:一个实体应当尽量少的与其他实体之间发生相互作用,使得系统功能模块相对独立。

6、合成复用原则(Composite Reuse Principle)

原则是尽量使用合成/聚合的方式,而不是使用继承。

三、Java的23中设计模式

从这一块开始,我们详细介绍Java中23种设计模式的概念,应用场景等情况,并结合他们的特点及设计模式的原则进行分析。

1、工厂方法模式(Factory Method)

工厂方法模式分为三种:

11、普通工厂模式,就是建立一个工厂类,对实现了同一接口的一些类进行实例的创建。首先看下关系图:

举例如下:(我们举一个发送邮件和短信的例子)

首先,创建二者的共同接口: [java] view plaincopy

  1. public interface Sender {
  2. public void Send();
  3. }

其次,创建实现类:

[java] view plaincopy

  1. public class MailSender implements Sender {
  2. @Override
  3. public void Send() {
  4. System.out.println("this is mailsender!");
  5. }
  6. }

[java] view plaincopy

  1. public class SmsSender implements Sender { 1.
  2. @Override
  3. public void Send() {
  4. System.out.println("this is sms sender!");
  5. }
  6. }

最后,建工厂类: [java] view plaincopy

  1. public class SendFactory { 1.
  2. public Sender produce(String type) {
  3. if ("mail".equals(type)) {
  4. return new MailSender();
  5. } else if ("sms".equals(type)) {
  6. return new SmsSender();
  7. } else {
  8. System.out.println("请输入正确的类型!");
  9. return null;
  10. }
  11. }
  12. }

我们来测试下:

  1. public class FactoryTest { 1.
  2. public static void main(String[] args) {
  3. SendFactory factory = new SendFactory();
  4. Sender sender = factory.produce("sms");
  5. sender.Send();
  6. }
  7. }

输出:this is sms sender!

22、多个工厂方法模式,是对普通工厂方法模式的改进,在普通工厂方法模式中,如果传递的字符串出错,则不能正确创建对象,而多个工厂方法模式是提供多个工厂方法,分别创建对象。关系图:

将上面的代码做下修改,改动下SendFactory类就行,如下: [java] view plaincopypublic class SendFactory {

public Sender produceMail(){

  1. return new MailSender();
  2. } 1.
  3. public Sender produceSms(){
  4. return new SmsSender();
  5. }
  6. }

测试类如下:

[java] view plaincopy

  1. public class FactoryTest { 1.
  2. public static void main(String[] args) {
  3. SendFactory factory = new SendFactory();
  4. Sender sender = factory.produceMail();
  5. sender.Send();
  6. }
  7. }

输出:this is mailsender!

33、静态工厂方法模式,将上面的多个工厂方法模式里的方法置为静态的,不需要创建实例,直接调用即可。 [java] view plaincopy

  1. public class SendFactory { 1.
  2. public static Sender produceMail(){
  3. return new MailSender();
  4. } 1.
  5. public static Sender produceSms(){
  6. return new SmsSender();
  7. }
  8. }

[java] view plaincopy

  1. public class FactoryTest { 1.
  2. public static void main(String[] args) {
  3. Sender sender = SendFactory.produceMail();
  4. sender.Send();
  5. }
  6. }

输出:this is mailsender!

总体来说,工厂模式适合:凡是出现了大量的产品需要创建,并且具有共同的接口时,可以通过工厂方法模式进行创建。在以上的三种模式中,第一种如果传入的字符串有误,不能正确创建对象,第三种相对于第二种,不需要实例化工厂类,所以,大多数情况下,我们会选用第三种——静态工厂方法模式。

2、抽象工厂模式(Abstract Factory)

工厂方法模式有一个问题就是,类的创建依赖工厂类,也就是说,如果想要拓展程序,必须对工厂类进行修改,这违背了闭包原则,所以,从设计角度考虑,有一定的问题,如何解决?就用到抽象工厂模式,创建多个工厂类,这样一旦需要增加新的功能,直接增加新的工厂类就可以了,不需要修改之前的代码。因为抽象工厂不太好理解,我们先看看图,然后就和代码,就比较容易理解。

请看例子: [java] view plaincopy

  1. public interface Sender {
  2. public void Send();
  3. }

两个实现类:

[java] view plaincopy

  1. public class MailSender implements Sender {
  2. @Override
  3. public void Send() {
  4. System.out.println("this is mailsender!");
  5. }
  6. }

[java] view plaincopy

  1. public class SmsSender implements Sender { 1.
  2. @Override
  3. public void Send() {
  4. System.out.println("this is sms sender!");
  5. }
  6. }

两个工厂类: [java] view plaincopy

  1. public class SendMailFactory implements Provider { 1.
  2. @Override
  3. public Sender produce(){
  4. return new MailSender();
  5. }
  6. }

[java] view plaincopy

  1. public class SendSmsFactory implements Provider{ 1.
  2. @Override
  3. public Sender produce() {
  4. return new SmsSender();
  5. }
  6. }

在提供一个接口: [java] view plaincopy

  1. public interface Provider {
  2. public Sender produce();
  3. }

测试类:

[java] view plaincopy

  1. public class Test { 1.
  2. public static void main(String[] args) {
  3. Provider provider = new SendMailFactory();
  4. Sender sender = provider.produce();
  5. sender.Send();
  6. }
  7. }

其实这个模式的好处就是,如果你现在想增加一个功能:发及时信息,则只需做一个实现类,实现Sender接口,同时做一个工厂类,实现Provider接口,就OK了,无需去改动现成的代码。这样做,拓展性较好!

3、单例模式(Singleton

单例对象(Singleton)是一种常用的设计模式。在Java应用中,单例对象能保证在一个JVM中,该对象只有一个实例存在。这样的模式有几个好处:

1、某些类创建比较频繁,对于一些大型的对象,这是一笔很大的系统开销。

2、省去了new操作符,降低了系统内存的使用频率,减轻GC压力。

3、有些类如交易所的核心交易引擎,控制着交易流程,如果该类可以创建多个的话,系统完全乱了。(比如一个军队出现了多个司令员同时指挥,肯定会乱成一团),所以只有使用单例模式,才能保证核心交易服务器独立控制整个流程。

首先我们写一个简单的单例类: [java] view plaincopy

  1. public class Singleton { 1.
  2. // 持有私有静态实例,防止被引用,此处赋值为null,目的是实现延迟加载 //
  3. private static Singleton instance = null; 1.
  4. // 私有构造方法,防止被实例化 //
  5. private Singleton() {
  6. } 1.
  7. // 静态工程方法,创建实例 //
  8. public static Singleton getInstance() {
  9. if (instance == null) {
  10. instance = new Singleton();
  11. }
  12. return instance;
  13. } 1.
  14. // 如果该对象被用于序列化,可以保证对象在序列化前后保持一致 //
  15. public Object readResolve() {
  16. return instance;
  17. }
  18. }

这个类可以满足基本要求,但是,像这样毫无线程安全保护的类,如果我们把它放入多线程的环境下,肯定就会出现问题了,如何解决?我们首先会想到对getInstance方法加synchronized关键字,如下:

[java] view plaincopy

  1. public static synchronized Singleton getInstance() {
  2. if (instance == null) {
  3. instance = new Singleton();
  4. }
  5. return instance;
  6. }

但是,synchronized关键字锁住的是这个对象,这样的用法,在性能上会有所下降,因为每次调用getInstance(),都要对对象上锁,事实上,只有在第一次创建对象的时候需要加锁,之后就不需要了,所以,这个地方需要改进。我们改成下面这个:

[java] view plaincopy

  1. public static Singleton getInstance() {
  2. if (instance == null) {
  3. synchronized (instance) {
  4. if (instance == null) {
  5. instance = new Singleton();
  6. }
  7. }
  8. }
  9. return instance;
  10. }

似乎解决了之前提到的问题,将synchronized关键字加在了内部,也就是说当调用的时候是不需要加锁的,只有在instance为null,并创建对象的时候才需要加锁,性能有一定的提升。但是,这样的情况,还是有可能有问题的,看下面的情况:在Java指令中创建对象和赋值操作是分开进行的,也就是说instance = new Singleton();语句是分两步执行的。但是JVM并不保证这两个操作的先后顺序,也就是说有可能JVM会为新的Singleton实例分配空间,然后直接赋值给instance成员,然后再去初始化这个Singleton实例。这样就可能出错了,我们以A、B两个线程为例:

a>A、B线程同时进入了第一个if判断

b>A首先进入synchronized块,由于instance为null,所以它执行instance = new Singleton();

c>由于JVM内部的优化机制,JVM先画出了一些分配给Singleton实例的空白内存,并赋值给instance成员(注意此时JVM没有开始初始化这个实例),然后A离开了synchronized块。

d>B进入synchronized块,由于instance此时不是null,因此它马上离开了synchronized块并将结果返回给调用该方法的程序。

e>此时B线程打算使用Singleton实例,却发现它没有被初始化,于是错误发生了。

所以程序还是有可能发生错误,其实程序在运行过程是很复杂的,从这点我们就可以看出,尤其是在写多线程环境下的程序更有难度,有挑战性。我们对该程序做进一步优化: [java] view plaincopy

  1. private static class SingletonFactory{
  2. private static Singleton instance = new Singleton();
  3. }
  4. public static Singleton getInstance(){
  5. return SingletonFactory.instance;
  6. }

实际情况是,单例模式使用内部类来维护单例的实现,JVM内部的机制能够保证当一个类被加载的时候,这个类的加载过程是线程互斥的。这样当我们第一次调用getInstance的时候,JVM能够帮我们保证instance只被创建一次,并且会保证把赋值给instance的内存初始化完毕,这样我们就不用担心上面的问题。同时该方法也只会在第一次调用的时候使用互斥机制,这样就解决了低性能问题。这样我们暂时总结一个完美的单例模式:

[java] view plaincopy

  1. public class Singleton { 1.
  2. // 私有构造方法,防止被实例化 //
  3. private Singleton() {
  4. } 1.
  5. // 此处使用一个内部类来维护单例 //
  6. private static class SingletonFactory {
  7. private static Singleton instance = new Singleton();
  8. } 1.
  9. // 获取实例 //
  10. public static Singleton getInstance() {
  11. return SingletonFactory.instance;
  12. } 1.
  13. // 如果该对象被用于序列化,可以保证对象在序列化前后保持一致 //
  14. public Object readResolve() {
  15. return getInstance();
  16. }
  17. }

其实说它完美,也不一定,如果在构造函数中抛出异常,实例将永远得不到创建,也会出错。所以说,十分完美的东西是没有的,我们只能根据实际情况,选择最适合自己应用场景的实现方法。也有人这样实现:因为我们只需要在创建类的时候进行同步,所以只要将创建和getInstance()分开,单独为创建加synchronized关键字,也是可以的:

[java] view plaincopy

  1. public class SingletonTest { 1.
  2. private static SingletonTest instance = null; 1.
  3. private SingletonTest() {
  4. } 1.
  5. private static synchronized void syncInit() {
  6. if (instance == null) {
  7. instance = new SingletonTest();
  8. }
  9. } 1.
  10. public static SingletonTest getInstance() {
  11. if (instance == null) {
  12. syncInit();
  13. }
  14. return instance;
  15. }
  16. }

考虑性能的话,整个程序只需创建一次实例,所以性能也不会有什么影响。

补充:采用"影子实例"的办法为单例对象的属性同步更新 [java] view plaincopy

  1. public class SingletonTest { 1.
  2. private static SingletonTest instance = null;
  3. private Vector properties = null; 1.
  4. public Vector getProperties() {
  5. return properties;
  6. } 1.
  7. private SingletonTest() {
  8. } 1.
  9. private static synchronized void syncInit() {
  10. if (instance == null) {
  11. instance = new SingletonTest();
  12. }
  13. } 1.
  14. public static SingletonTest getInstance() {
  15. if (instance == null) {
  16. syncInit();
  17. }
  18. return instance;
  19. } 1.
  20. public void updateProperties() {
  21. SingletonTest shadow = new SingletonTest();
  22. properties = shadow.getProperties();
  23. }
  24. }

通过单例模式的学习告诉我们:

1、单例模式理解起来简单,但是具体实现起来还是有一定的难度。

2、synchronized关键字锁定的是对象,在用的时候,一定要在恰当的地方使用(注意需要使用锁的对象和过程,可能有的时候并不是整个对象及整个过程都需要锁)。

到这儿,单例模式基本已经讲完了,结尾处,笔者突然想到另一个问题,就是采用类的静态方法,实现单例模式的效果,也是可行的,此处二者有什么不同?

首先,静态类不能实现接口。(从类的角度说是可以的,但是那样就破坏了静态了。因为接口中不允许有static修饰的方法,所以即使实现了也是非静态的)

其次,单例可以被延迟初始化,静态类一般在第一次加载是初始化。之所以延迟加载,是因为有些类比较庞大,所以延迟加载有助于提升性能。

再次,单例类可以被继承,他的方法可以被覆写。但是静态类内部方法都是static,无法被覆写。

最后一点,单例类比较灵活,毕竟从实现上只是一个普通的Java类,只要满足单例的基本需求,你可以在里面随心所欲的实现一些其它功能,但是静态类不行。从上面这些概括中,基本可以看出二者的区别,但是,从另一方面讲,我们上面最后实现的那个单例模式,内部就是用一个静态类来实现的,所以,二者有很大的关联,只是我们考虑问题的层面不同罢了。两种思想的结合,才能造就出完美的解决方案,就像HashMap采用数组+链表来实现一样,其实生活中很多事情都是这样,单用不同的方法来处理问题,总是有优点也有缺点,最完美的方法是,结合各个方法的优点,才能最好的解决问题!

4、建造者模式(Builder)

工厂类模式提供的是创建单个类的模式,而建造者模式则是将各种产品集中起来进行管理,用来创建复合对象,所谓复合对象就是指某个类具有不同的属性,其实建造者模式就是前面抽象工厂模式和最后的Test结合起来得到的。我们看一下代码:

还和前面一样,一个Sender接口,两个实现类MailSender和SmsSender。最后,建造者类如下: [java] view plaincopy

  1. public class Builder { 1.
  2. private List list = new ArrayList(); 1.
  3. public void produceMailSender(int count){
  4. for(int i=0; i<count; i++){
  5. list.add(new MailSender());
  6. }
  7. } 1.
  8. public void produceSmsSender(int count){
  9. for(int i=0; i<count; i++){
  10. list.add(new SmsSender());
  11. }
  12. }
  13. }

测试类:

[java] view plaincopy

  1. public class Test { 1.
  2. public static void main(String[] args) {
  3. Builder builder = new Builder();
  4. builder.produceMailSender(10);
  5. }
  6. }

从这点看出,建造者模式将很多功能集成到一个类里,这个类可以创造出比较复杂的东西。所以与工程模式的区别就是:工厂模式关注的是创建单个产品,而建造者模式则关注创建符合对象,多个部分。因此,是选择工厂模式还是建造者模式,依实际情况而定。

5、原型模式(Prototype)

原型模式虽然是创建型的模式,但是与工程模式没有关系,从名字即可看出,该模式的思想就是将一个对象作为原型,对其进行复制、克隆,产生一个和原对象类似的新对象。本小结会通过对象的复制,进行讲解。在Java中,复制对象是通过clone()实现的,先创建一个原型类: [java] view plaincopy

  1. public class Prototype implements Cloneable { 1.
  2. public Object clone() throws CloneNotSupportedException {
  3. Prototype proto = (Prototype) super.clone();
  4. return proto;
  5. }
  6. }

很简单,一个原型类,只需要实现Cloneable接口,覆写clone方法,此处clone方法可以改成任意的名称,因为Cloneable接口是个空接口,你可以任意定义实现类的方法名,如cloneA或者cloneB,因为此处的重点是super.clone()这句话,super.clone()调用的是Object的clone()方法,而在Object类中,clone()是native的,具体怎么实现,我会在另一篇文章中,关于解读Java中本地方法的调用,此处不再深究。在这儿,我将结合对象的浅复制和深复制来说一下,首先需要了解对象深、浅复制的概念:

浅复制:将一个对象复制后,基本数据类型的变量都会重新创建,而引用类型,指向的还是原对象所指向的。

深复制:将一个对象复制后,不论是基本数据类型还有引用类型,都是重新创建的。简单来说,就是深复制进行了完全彻底的复制,而浅复制不彻底。

此处,写一个深浅复制的例子: [java] view plaincopy

  1. public class Prototype implements Cloneable, Serializable { 1.
  2. private static final long serialVersionUID = 1L;
  3. private String string; 1.
  4. private SerializableObject obj; 1.
  5. // 浅复制 //
  6. public Object clone() throws CloneNotSupportedException {
  7. Prototype proto = (Prototype) super.clone();
  8. return proto;
  9. } 1.
  10. // 深复制 //
  11. public Object deepClone() throws IOException, ClassNotFoundException { 1.
  12. // 写入当前对象的二进制流 //
  13. ByteArrayOutputStream bos = new ByteArrayOutputStream();
  14. ObjectOutputStream oos = new ObjectOutputStream(bos);
  15. oos.writeObject(this); 1.
  16. // 读出二进制流产生的新对象 //
  17. ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
  18. ObjectInputStream ois = new ObjectInputStream(bis);
  19. return ois.readObject();
  20. } 1.
  21. public String getString() {
  22. return string;
  23. } 1.
  24. public void setString(String string) {
  25. this.string = string;
  26. } 1.
  27. public SerializableObject getObj() {
  28. return obj;
  29. } 1.
  30. public void setObj(SerializableObject obj) {
  31. this.obj = obj;
  32. } 1.
  33. } 1.
  34. class SerializableObject implements Serializable {
  35. private static final long serialVersionUID = 1L;
  36. }

要实现深复制,需要采用流的形式读入当前对象的二进制输入,再写出二进制数据对应的对象。 我们接着讨论设计模式,上篇文章我讲完了5种创建型模式,这章开始,我将讲下7种结构型模式:适配器模式、装饰模式、代理模式、外观模式、桥接模式、组合模式、享元模式。其中对象的适配器模式是各种模式的起源,我们看下面的图:

适配器模式将某个类的接口转换成客户端期望的另一个接口表示,目的是消除由于接口不匹配所造成的类的兼容性问题。主要分为三类:类的适配器模式、对象的适配器模式、接口的适配器模式。首先,我们来看看类的适配器模式,先看类图:

核心思想就是:有一个Source类,拥有一个方法,待适配,目标接口时Targetable,通过Adapter类,将Source的功能扩展到Targetable里,看代码: [java] view plaincopy

  1. public class Source { 1.
  2. public void method1() {
  3. System.out.println("this is original method!");
  4. }
  5. }

[java] view plaincopy

  1. public interface Targetable { 1.
  2. // 与原类中的方法相同 //
  3. public void method1(); 1.
  4. // 新类的方法 //
  5. public void method2();
  6. } [java] view plaincopy

  7. public class Adapter extends Source implements Targetable { 1.

  8. @Override
  9. public void method2() {
  10. System.out.println("this is the targetable method!");
  11. }
  12. }

Adapter类继承Source类,实现Targetable接口,下面是测试类:

[java] view plaincopy

  1. public class AdapterTest { 1.
  2. public static void main(String[] args) {
  3. Targetable target = new Adapter();
  4. target.method1();
  5. target.method2();
  6. }
  7. }

输出:

this is original method! this is the targetable method!

这样Targetable接口的实现类就具有了Source类的功能。

对象的适配器模式

基本思路和类的适配器模式相同,只是将Adapter类作修改,这次不继承Source类,而是持有Source类的实例,以达到解决兼容性的问题。看图:

只需要修改Adapter类的源码即可: [java] view plaincopy

  1. public class Wrapper implements Targetable { 1.
  2. private Source source; 1.
  3. public Wrapper(Source source){
  4. super();
  5. this.source = source;
  6. }
  7. @Override
  8. public void method2() {
  9. System.out.println("this is the targetable method!");
  10. } 1.
  11. @Override
  12. public void method1() {
  13. source.method1();
  14. }
  15. }

测试类:

[java] view plaincopy

  1. public class AdapterTest { 1.
  2. public static void main(String[] args) {
  3. Source source = new Source();
  4. Targetable target = new Wrapper(source);
  5. target.method1();
  6. target.method2();
  7. }
  8. }

输出与第一种一样,只是适配的方法不同而已。

第三种适配器模式是接口的适配器模式,接口的适配器是这样的:有时我们写的一个接口中有多个抽象方法,当我们写该接口的实现类时,必须实现该接口的所有方法,这明显有时比较浪费,因为并不是所有的方法都是我们需要的,有时只需要某一些,此处为了解决这个问题,我们引入了接口的适配器模式,借助于一个抽象类,该抽象类实现了该接口,实现了所有的方法,而我们不和原始的接口打交道,只和该抽象类取得联系,所以我们写一个类,继承该抽象类,重写我们需要的方法就行。看一下类图:

这个很好理解,在实际开发中,我们也常会遇到这种接口中定义了太多的方法,以致于有时我们在一些实现类中并不是都需要。看代码: [java] view plaincopy

  1. public interface Sourceable { 1.
  2. public void method1();
  3. public void method2();
  4. }

抽象类Wrapper2:

[java] view plaincopy

  1. public abstract class Wrapper2 implements Sourceable{ 1.
  2. public void method1(){}
  3. public void method2(){}
  4. }

[java] view plaincopy

  1. public class SourceSub1 extends Wrapper2 {
  2. public void method1(){
  3. System.out.println("the sourceable interface's first Sub1!");
  4. }
  5. } [java] view plaincopy

  6. public class SourceSub2 extends Wrapper2 {

  7. public void method2(){
  8. System.out.println("the sourceable interface's second Sub2!");
  9. }
  10. }

[java] view plaincopy

  1. public class WrapperTest { 1.
  2. public static void main(String[] args) {
  3. Sourceable source1 = new SourceSub1();
  4. Sourceable source2 = new SourceSub2(); 1.
  5. source1.method1();
  6. source1.method2();
  7. source2.method1();
  8. source2.method2();
  9. }
  10. }

测试输出:

the sourceable interface's first Sub1! the sourceable interface's second Sub2!

达到了我们的效果!

讲了这么多,总结一下三种适配器模式的应用场景:

类的适配器模式:当希望将一个类转换成满足另一个新接口的类时,可以使用类的适配器模式,创建一个新类,继承原有的类,实现新的接口即可。

对象的适配器模式:当希望将一个对象转换成满足另一个新接口的对象时,可以创建一个Wrapper类,持有原类的一个实例,在Wrapper类的方法中,调用实例的方法就行。

接口的适配器模式:当不希望实现一个接口中所有的方法时,可以创建一个抽象类Wrapper,实现所有方法,我们写别的类的时候,继承抽象类即可。

7、装饰模式(Decorator)

顾名思义,装饰模式就是给一个对象增加一些新的功能,而且是动态的,要求装饰对象和被装饰对象实现同一个接口,装饰对象持有被装饰对象的实例,关系图如下:

Source类是被装饰类,Decorator类是一个装饰类,可以为Source类动态的添加一些功能,代码如下: [java] view plaincopy

  1. public interface Sourceable {
  2. public void method();
  3. }

[java] view plaincopy

  1. public class Source implements Sourceable { 1.
  2. @Override
  3. public void method() {
  4. System.out.println("the original method!");
  5. }
  6. } [java] view plaincopy

  7. public class Decorator implements Sourceable { 1.

  8. private Sourceable source; 1.
  9. public Decorator(Sourceable source){
  10. super();
  11. this.source = source;
  12. }
  13. @Override
  14. public void method() {
  15. System.out.println("before decorator!");
  16. source.method();
  17. System.out.println("after decorator!");
  18. }
  19. }

测试类:

[java] view plaincopy

  1. public class DecoratorTest { 1.
  2. public static void main(String[] args) {
  3. Sourceable source = new Source();
  4. Sourceable obj = new Decorator(source);
  5. obj.method();
  6. }
  7. }

输出:

before decorator! the original method! after decorator!

装饰器模式的应用场景:

1、需要扩展一个类的功能。

2、动态的为一个对象增加功能,而且还能动态撤销。(继承不能做到这一点,继承的功能是静态的,不能动态增删。)

缺点:产生过多相似的对象,不易排错!

8、代理模式(Proxy)

其实每个模式名称就表明了该模式的作用,代理模式就是多一个代理类出来,替原对象进行一些操作,比如我们在租房子的时候回去找中介,为什么呢?因为你对该地区房屋的信息掌握的不够全面,希望找一个更熟悉的人去帮你做,此处的代理就是这个意思。再如我们有的时候打官司,我们需要请律师,因为律师在法律方面有专长,可以替我们进行操作,表达我们的想法。先来看看关系图:

根据上文的阐述,代理模式就比较容易的理解了,我们看下代码: [java] view plaincopy

  1. public interface Sourceable {
  2. public void method();
  3. }

[java] view plaincopy

  1. public class Source implements Sourceable { 1.
  2. @Override
  3. public void method() {
  4. System.out.println("the original method!");
  5. }
  6. } [java] view plaincopy

  7. public class Proxy implements Sourceable { 1.

  8. private Source source;
  9. public Proxy(){
  10. super();
  11. this.source = new Source();
  12. }
  13. @Override
  14. public void method() {
  15. before();
  16. source.method();
  17. atfer();
  18. }
  19. private void atfer() {
  20. System.out.println("after proxy!");
  21. }
  22. private void before() {
  23. System.out.println("before proxy!");
  24. }
  25. }

测试类:

[java] view plaincopy

  1. public class ProxyTest { 1.
  2. public static void main(String[] args) {
  3. Sourceable source = new Proxy();
  4. source.method();
  5. } 1.
  6. }

输出:

before proxy! the original method! after proxy!

代理模式的应用场景:

如果已有的方法在使用的时候需要对原有的方法进行改进,此时有两种办法:

1、修改原有的方法来适应。这样违反了“对扩展开放,对修改关闭”的原则。

2、就是采用一个代理类调用原有的方法,且对产生的结果进行控制。这种方法就是代理模式。

使用代理模式,可以将功能划分的更加清晰,有助于后期维护!

9、外观模式(Facade)

外观模式是为了解决类与类之家的依赖关系的,像spring一样,可以将类和类之间的关系配置到配置文件中,而外观模式就是将他们的关系放在一个Facade类中,降低了类类之间的耦合度,该模式中没有涉及到接口,看下类图:(我们以一个计算机的启动过程为例)

我们先看下实现类: [java] view plaincopy

  1. public class CPU { 1.
  2. public void startup(){
  3. System.out.println("cpu startup!");
  4. } 1.
  5. public void shutdown(){
  6. System.out.println("cpu shutdown!");
  7. }
  8. }

[java] view plaincopy

  1. public class Memory { 1.
  2. public void startup(){
  3. System.out.println("memory startup!");
  4. } 1.
  5. public void shutdown(){
  6. System.out.println("memory shutdown!");
  7. }
  8. } [java] view plaincopy

  9. public class Disk { 1.

  10. public void startup(){
  11. System.out.println("disk startup!");
  12. } 1.
  13. public void shutdown(){
  14. System.out.println("disk shutdown!");
  15. }
  16. }

[java] view plaincopy

  1. public class Computer {
  2. private CPU cpu;
  3. private Memory memory;
  4. private Disk disk; 1.
  5. public Computer(){
  6. cpu = new CPU();
  7. memory = new Memory();
  8. disk = new Disk();
  9. } 1.
  10. public void startup(){
  11. System.out.println("start the computer!");
  12. cpu.startup();
  13. memory.startup();
  14. disk.startup();
  15. System.out.println("start computer finished!");
  16. } 1.
  17. public void shutdown(){
  18. System.out.println("begin to close the computer!");
  19. cpu.shutdown();
  20. memory.shutdown();
  21. disk.shutdown();
  22. System.out.println("computer closed!");
  23. }
  24. }

User类如下: [java] view plaincopy

  1. public class User { 1.
  2. public static void main(String[] args) {
  3. Computer computer = new Computer();
  4. computer.startup();
  5. computer.shutdown();
  6. }
  7. }

输出:

start the computer! cpu startup! memory startup! disk startup! start computer finished! begin to close the computer! cpu shutdown! memory shutdown! disk shutdown! computer closed!

如果我们没有Computer类,那么,CPU、Memory、Disk他们之间将会相互持有实例,产生关系,这样会造成严重的依赖,修改一个类,可能会带来其他类的修改,这不是我们想要看到的,有了Computer类,他们之间的关系被放在了Computer类里,这样就起到了解耦的作用,这,就是外观模式!

10、桥接模式(Bridge)

桥接模式就是把事物和其具体实现分开,使他们可以各自独立的变化。桥接的用意是:将抽象化与实现化解耦,使得二者可以独立变化,像我们常用的JDBC桥DriverManager一样,JDBC进行连接数据库的时候,在各个数据库之间进行切换,基本不需要动太多的代码,甚至丝毫不用动,原因就是JDBC提供统一接口,每个数据库提供各自的实现,用一个叫做数据库驱动的程序来桥接就行了。我们来看看关系图:

实现代码:

先定义接口: [java] view plaincopy

  1. public interface Sourceable {
  2. public void method();
  3. }

分别定义两个实现类:

[java] view plaincopy

  1. public class SourceSub1 implements Sourceable { 1.
  2. @Override
  3. public void method() {
  4. System.out.println("this is the first sub!");
  5. }
  6. }

[java] view plaincopy

  1. public class SourceSub2 implements Sourceable { 1.
  2. @Override
  3. public void method() {
  4. System.out.println("this is the second sub!");
  5. }
  6. }

定义一个桥,持有Sourceable的一个实例: [java] view plaincopy

  1. public abstract class Bridge {
  2. private Sourceable source; 1.
  3. public void method(){
  4. source.method();
  5. } 1.
  6. public Sourceable getSource() {
  7. return source;
  8. } 1.
  9. public void setSource(Sourceable source) {
  10. this.source = source;
  11. }
  12. }

[java] view plaincopy

  1. public class MyBridge extends Bridge {
  2. public void method(){
  3. getSource().method();
  4. }
  5. }

测试类: [java] view plaincopy

  1. public class BridgeTest { 1.
  2. public static void main(String[] args) { 1.
  3. Bridge bridge = new MyBridge(); 1.
  4. //调用第一个对象//
  5. Sourceable source1 = new SourceSub1();
  6. bridge.setSource(source1);
  7. bridge.method(); 1.
  8. //调用第二个对象//
  9. Sourceable source2 = new SourceSub2();
  10. bridge.setSource(source2);
  11. bridge.method();
  12. }
  13. }

output:

this is the first sub! this is the second sub!

这样,就通过对Bridge类的调用,实现了对接口Sourceable的实现类SourceSub1和SourceSub2的调用。接下来我再画个图,大家就应该明白了,因为这个图是我们JDBC连接的原理,有数据库学习基础的,一结合就都懂了。

11、组合模式(Composite)

组合模式有时又叫部分-整体模式在处理类似树形结构的问题时比较方便,看看关系图:

直接来看代码: [java] view plaincopy

  1. public class TreeNode { 1.
  2. private String name;
  3. private TreeNode parent;
  4. private Vector children = new Vector(); 1.
  5. public TreeNode(String name){
  6. this.name = name;
  7. } 1.
  8. public String getName() {
  9. return name;
  10. } 1.
  11. public void setName(String name) {
  12. this.name = name;
  13. } 1.
  14. public TreeNode getParent() {
  15. return parent;
  16. } 1.
  17. public void setParent(TreeNode parent) {
  18. this.parent = parent;
  19. } 1.
  20. //添加孩子节点
  21. public void add(TreeNode node){
  22. children.add(node);
  23. } 1.
  24. //删除孩子节点
  25. public void remove(TreeNode node){
  26. children.remove(node);
  27. } 1.
  28. //取得孩子节点
  29. public Enumeration getChildren(){
  30. return children.elements();
  31. }
  32. }

[java] view plaincopy

  1. public class Tree { 1.
  2. TreeNode root = null; 1.
  3. public Tree(String name) {
  4. root = new TreeNode(name);
  5. } 1.
  6. public static void main(String[] args) {
  7. Tree tree = new Tree("A");
  8. TreeNode nodeB = new TreeNode("B");
  9. TreeNode nodeC = new TreeNode("C"); 1.
  10. nodeB.add(nodeC);
  11. tree.root.add(nodeB);
  12. System.out.println("build the tree finished!");
  13. }
  14. }

使用场景:将多个对象组合在一起进行操作,常用于表示树形结构中,例如二叉树,数等。

12、享元模式(Flyweight)

享元模式的主要目的是实现对象的共享,即共享池,当系统中对象多的时候可以减少内存的开销,通常与工厂模式一起使用。

FlyWeightFactory负责创建和管理享元单元,当一个客户端请求时,工厂需要检查当前对象池中是否有符合条件的对象,如果有,就返回已经存在的对象,如果没有,则创建一个新对象,FlyWeight是超类。一提到共享池,我们很容易联想到Java里面的JDBC连接池,想想每个连接的特点,我们不难总结出:适用于作共享的一些个对象,他们有一些共有的属性,就拿数据库连接池来说,url、driverClassName、username、password及dbname,这些属性对于每个连接来说都是一样的,所以就适合用享元模式来处理,建一个工厂类,将上述类似属性作为内部数据,其它的作为外部数据,在方法调用时,当做参数传进来,这样就节省了空间,减少了实例的数量。

看个例子:

看下数据库连接池的代码: [java] view plaincopy

  1. public class ConnectionPool { 1.
  2. private Vector pool; 1.
  3. //公有属性//
  4. private String url = "jdbc:mysql://localhost:3306/test";
  5. private String username = "root";
  6. private String password = "root";
  7. private String driverClassName = "com.mysql.jdbc.Driver"; 1.
  8. private int poolSize = 100;
  9. private static ConnectionPool instance = null;
  10. Connection conn = null; 1.
  11. //构造方法,做一些初始化工作//
  12. private ConnectionPool() {
  13. pool = new Vector(poolSize); 1.
  14. for (int i = 0; i < poolSize; i++) {
  15. try {
  16. Class.forName(driverClassName);
  17. conn = DriverManager.getConnection(url, username, password);
  18. pool.add(conn);
  19. } catch (ClassNotFoundException e) {
  20. e.printStackTrace();
  21. } catch (SQLException e) {
  22. e.printStackTrace();
  23. }
  24. }
  25. } 1.
  26. // 返回连接到连接池 //
  27. public synchronized void release() {
  28. pool.add(conn);
  29. } 1.
  30. // 返回连接池中的一个数据库连接 //
  31. public synchronized Connection getConnection() {
  32. if (pool.size() > 0) {
  33. Connection conn = pool.get(0);
  34. pool.remove(conn);
  35. return conn;
  36. } else {
  37. return null;
  38. }
  39. }
  40. }

通过连接池的管理,实现了数据库连接的共享,不需要每一次都重新创建连接,节省了数据库重新创建的开销,提升了系统的性能!本章讲解了7种结构型模式,因为篇幅的问题,剩下的11种行为型模式,

本章是关于设计模式的最后一讲,会讲到第三种设计模式——行为型模式,共11种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。这段时间一直在写关于设计模式的东西,终于写到一半了,写博文是个很费时间的东西,因为我得为读者负责,不论是图还是代码还是表述,都希望能尽量写清楚,以便读者理解,我想不论是我还是读者,都希望看到高质量的博文出来,从我本人出发,我会一直坚持下去,不断更新,源源动力来自于读者朋友们的不断支持,我会尽自己的努力,写好每一篇文章!希望大家能不断给出意见和建议,共同打造完美的博文!



先来张图,看看这11中模式的关系:

第一类:通过父类与子类的关系进行实现。第二类:两个类之间。第三类:类的状态。第四类:通过中间类

13、策略模式(strategy)

策略模式定义了一系列算法,并将每个算法封装起来,使他们可以相互替换,且算法的变化不会影响到使用算法的客户。需要设计一个接口,为一系列实现类提供统一的方法,多个实现类实现该接口,设计一个抽象类(可有可无,属于辅助类),提供辅助函数,关系图如下:

图中ICalculator提供同意的方法, AbstractCalculator是辅助类,提供辅助方法,接下来,依次实现下每个类:

首先统一接口: [java] view plaincopy

  1. public interface ICalculator {
  2. public int calculate(String exp);
  3. }

辅助类:

[java] view plaincopy

  1. public abstract class AbstractCalculator { 1.
  2. public int[] split(String exp,String opt){
  3. String array[] = exp.split(opt);
  4. int arrayInt[] = new int[2];
  5. arrayInt[0] = Integer.parseInt(array[0]);
  6. arrayInt[1] = Integer.parseInt(array[1]);
  7. return arrayInt;
  8. }
  9. }

三个实现类:

[java] view plaincopy

  1. public class Plus extends AbstractCalculator implements ICalculator { 1.
  2. @Override
  3. public int calculate(String exp) {
  4. int arrayInt[] = split(exp,"\+");
  5. return arrayInt[0]+arrayInt[1];
  6. }
  7. }

[java] view plaincopy

  1. public class Minus extends AbstractCalculator implements ICalculator { 1.
  2. @Override
  3. public int calculate(String exp) {
  4. int arrayInt[] = split(exp,"-");
  5. return arrayInt[0]-arrayInt[1];
  6. } 1.
  7. } [java] view plaincopy

  8. public class Multiply extends AbstractCalculator implements ICalculator { 1.

  9. @Override
  10. public int calculate(String exp) {
  11. int arrayInt[] = split(exp,"\/*");
  12. return arrayInt[0]/*arrayInt[1];
  13. }
  14. }

简单的测试类:

[java] view plaincopy

  1. public class StrategyTest { 1.
  2. public static void main(String[] args) {
  3. String exp = "2+8";
  4. ICalculator cal = new Plus();
  5. int result = cal.calculate(exp);
  6. System.out.println(result);
  7. }
  8. }

输出:10

策略模式的决定权在用户,系统本身提供不同算法的实现,新增或者删除算法,对各种算法做封装。因此,策略模式多用在算法决策系统中,外部用户只需要决定用哪个算法即可。

14、模板方法模式(Template Method)

解释一下模板方法模式,就是指:一个抽象类中,有一个主方法,再定义1...n个方法,可以是抽象的,也可以是实际的方法,定义一个类,继承该抽象类,重写抽象方法,通过调用抽象类,实现对子类的调用,先看个关系图:

就是在AbstractCalculator类中定义一个主方法calculate,calculate()调用spilt()等,Plus和Minus分别继承AbstractCalculator类,通过对AbstractCalculator的调用实现对子类的调用,看下面的例子: [java] view plaincopy

  1. public abstract class AbstractCalculator { 1.
  2. //主方法,实现对本类其它方法的调用//
  3. public final int calculate(String exp,String opt){
  4. int array[] = split(exp,opt);
  5. return calculate(array[0],array[1]);
  6. } 1.
  7. //被子类重写的方法//
  8. abstract public int calculate(int num1,int num2); 1.
  9. public int[] split(String exp,String opt){
  10. String array[] = exp.split(opt);
  11. int arrayInt[] = new int[2];
  12. arrayInt[0] = Integer.parseInt(array[0]);
  13. arrayInt[1] = Integer.parseInt(array[1]);
  14. return arrayInt;
  15. }
  16. }

[java] view plaincopy

  1. public class Plus extends AbstractCalculator { 1.
  2. @Override
  3. public int calculate(int num1,int num2) {
  4. return num1 + num2;
  5. }
  6. }

测试类: [java] view plaincopy

  1. public class StrategyTest { 1.
  2. public static void main(String[] args) {
  3. String exp = "8+8";
  4. AbstractCalculator cal = new Plus();
  5. int result = cal.calculate(exp, "\+");
  6. System.out.println(result);
  7. }
  8. }

我跟踪下这个小程序的执行过程:首先将exp和"\+"做参数,调用AbstractCalculator类里的calculate(String,String)方法,在calculate(String,String)里调用同类的split(),之后再调用calculate(int ,int)方法,从这个方法进入到子类中,执行完return num1 + num2后,将值返回到AbstractCalculator类,赋给result,打印出来。正好验证了我们开头的思路。

15、观察者模式(Observer)

包括这个模式在内的接下来的四个模式,都是类和类之间的关系,不涉及到继承,学的时候应该 记得归纳,记得本文最开始的那个图。观察者模式很好理解,类似于邮件订阅和RSS订阅,当我们浏览一些博客或wiki时,经常会看到RSS图标,就这的意思是,当你订阅了该文章,如果后续有更新,会及时通知你。其实,简单来讲就一句话:当一个对象变化时,其它依赖该对象的对象都会收到通知,并且随着变化!对象之间是一种一对多的关系。先来看看关系图:

我解释下这些类的作用:MySubject类就是我们的主对象,Observer1和Observer2是依赖于MySubject的对象,当MySubject变化时,Observer1和Observer2必然变化。AbstractSubject类中定义着需要监控的对象列表,可以对其进行修改:增加或删除被监控对象,且当MySubject变化时,负责通知在列表内存在的对象。我们看实现代码:

一个Observer接口: [java] view plaincopy

  1. public interface Observer {
  2. public void update();
  3. }

两个实现类:

[java] view plaincopy

  1. public class Observer1 implements Observer { 1.
  2. @Override
  3. public void update() {
  4. System.out.println("observer1 has received!");
  5. }
  6. }

[java] view plaincopy

  1. public class Observer2 implements Observer { 1.
  2. @Override
  3. public void update() {
  4. System.out.println("observer2 has received!");
  5. } 1.
  6. }

Subject接口及实现类: [java] view plaincopy

  1. public interface Subject { 1.
  2. //增加观察者//
  3. public void add(Observer observer); 1.
  4. //删除观察者//
  5. public void del(Observer observer); 1.
  6. //通知所有的观察者//
  7. public void notifyObservers(); 1.
  8. //自身的操作//
  9. public void operation();
  10. }

[java] view plaincopy

  1. public abstract class AbstractSubject implements Subject { 1.
  2. private Vector vector = new Vector();
  3. @Override
  4. public void add(Observer observer) {
  5. vector.add(observer);
  6. } 1.
  7. @Override
  8. public void del(Observer observer) {
  9. vector.remove(observer);
  10. } 1.
  11. @Override
  12. public void notifyObservers() {
  13. Enumeration enumo = vector.elements();
  14. while(enumo.hasMoreElements()){
  15. enumo.nextElement().update();
  16. }
  17. }
  18. } [java] view plaincopy

  19. public class MySubject extends AbstractSubject { 1.

  20. @Override
  21. public void operation() {
  22. System.out.println("update self!");
  23. notifyObservers();
  24. } 1.
  25. }

测试类:

[java] view plaincopy

  1. public class ObserverTest { 1.
  2. public static void main(String[] args) {
  3. Subject sub = new MySubject();
  4. sub.add(new Observer1());
  5. sub.add(new Observer2()); 1.
  6. sub.operation();
  7. } 1.
  8. }

输出:

update self! observer1 has received! observer2 has received!

这些东西,其实不难,只是有些抽象,不太容易整体理解,建议读者:根据关系图,新建项目,自己写代码(或者参考我的代码),按照总体思路走一遍,这样才能体会它的思想,理解起来容易!**

16、迭代子模式(Iterator)

顾名思义,迭代器模式就是顺序访问聚集中的对象,一般来说,集合中非常常见,如果对集合类比较熟悉的话,理解本模式会十分轻松。这句话包含两层意思:一是需要遍历的对象,即聚集对象,二是迭代器对象,用于对聚集对象进行遍历访问。我们看下关系图:

这个思路和我们常用的一模一样,MyCollection中定义了集合的一些操作,MyIterator中定义了一系列迭代操作,且持有Collection实例,我们来看看实现代码:

两个接口: [java] view plaincopy

  1. public interface Collection { 1.
  2. public Iterator iterator(); 1.
  3. //取得集合元素//
  4. public Object get(int i); 1.
  5. //取得集合大小//
  6. public int size();
  7. }

[java] view plaincopy

  1. public interface Iterator {
  2. //前移
  3. public Object previous(); 1.
  4. //后移
  5. public Object next();
  6. public boolean hasNext(); 1.
  7. //取得第一个元素
  8. public Object first();
  9. }

两个实现: [java] view plaincopy

  1. public class MyCollection implements Collection { 1.
  2. public String string[] = {"A","B","C","D","E"};
  3. @Override
  4. public Iterator iterator() {
  5. return new MyIterator(this);
  6. } 1.
  7. @Override
  8. public Object get(int i) {
  9. return string[i];
  10. } 1.
  11. @Override
  12. public int size() {
  13. return string.length;
  14. }
  15. }

[java] view plaincopy

  1. public class MyIterator implements Iterator { 1.
  2. private Collection collection;
  3. private int pos = -1; 1.
  4. public MyIterator(Collection collection){
  5. this.collection = collection;
  6. } 1.
  7. @Override
  8. public Object previous() {
  9. if(pos > 0){
  10. pos--;
  11. }
  12. return collection.get(pos);
  13. } 1.
  14. @Override
  15. public Object next() {
  16. if(pos<collection.size()-1){
  17. pos++;
  18. }
  19. return collection.get(pos);
  20. } 1.
  21. @Override
  22. public boolean hasNext() {
  23. if(pos<collection.size()-1){
  24. return true;
  25. }else{
  26. return false;
  27. }
  28. } 1.
  29. @Override
  30. public Object first() {
  31. pos = 0;
  32. return collection.get(pos);
  33. } 1.
  34. }

测试类: [java] view plaincopy

  1. public class Test { 1.
  2. public static void main(String[] args) {
  3. Collection collection = new MyCollection();
  4. Iterator it = collection.iterator(); 1.
  5. while(it.hasNext()){
  6. System.out.println(it.next());
  7. }
  8. }
  9. }

输出:A B C D E

此处我们貌似模拟了一个集合类的过程,感觉是不是很爽?其实JDK中各个类也都是这些基本的东西,加一些设计模式,再加一些优化放到一起的,只要我们把这些东西学会了,掌握好了,我们也可以写出自己的集合类,甚至框架!

17、责任链模式(Chain of Responsibility) 接下来我们将要谈谈责任链模式,有多个对象,每个对象持有对下一个对象的引用,这样就会形成一条链,请求在这条链上传递,直到某一对象决定处理该请求。但是发出者并不清楚到底最终那个对象会处理该请求,所以,责任链模式可以实现,在隐瞒客户端的情况下,对系统进行动态的调整。先看看关系图:

Abstracthandler类提供了get和set方法,方便MyHandle类设置和修改引用对象,MyHandle类是核心,实例化后生成一系列相互持有的对象,构成一条链。 [java] view plaincopy

  1. public interface Handler {
  2. public void operator();
  3. }

[java] view plaincopy

  1. public abstract class AbstractHandler { 1.
  2. private Handler handler; 1.
  3. public Handler getHandler() {
  4. return handler;
  5. } 1.
  6. public void setHandler(Handler handler) {
  7. this.handler = handler;
  8. } 1.
  9. } [java] view plaincopy

  10. public class MyHandler extends AbstractHandler implements Handler { 1.

  11. private String name; 1.
  12. public MyHandler(String name) {
  13. this.name = name;
  14. } 1.
  15. @Override
  16. public void operator() {
  17. System.out.println(name+"deal!");
  18. if(getHandler()!=null){
  19. getHandler().operator();
  20. }
  21. }
  22. }

[java] view plaincopy

  1. public class Test { 1.
  2. public static void main(String[] args) {
  3. MyHandler h1 = new MyHandler("h1");
  4. MyHandler h2 = new MyHandler("h2");
  5. MyHandler h3 = new MyHandler("h3"); 1.
  6. h1.setHandler(h2);
  7. h2.setHandler(h3); 1.
  8. h1.operator();
  9. }
  10. }

输出:

h1deal! h2deal! h3deal!

此处强调一点就是,链接上的请求可以是一条链,可以是一个树,还可以是一个环,模式本身不约束这个,需要我们自己去实现,同时,在一个时刻,命令只允许由一个对象传给另一个对象,而不允许传给多个对象。

18、命令模式(Command)

命令模式很好理解,举个例子,司令员下令让士兵去干件事情,从整个事情的角度来考虑,司令员的作用是,发出口令,口令经过传递,传到了士兵耳朵里,士兵去执行。这个过程好在,三者相互解耦,任何一方都不用去依赖其他人,只需要做好自己的事儿就行,司令员要的是结果,不会去关注到底士兵是怎么实现的。我们看看关系图:

Invoker是调用者(司令员),Receiver是被调用者(士兵),MyCommand是命令,实现了Command接口,持有接收对象,看实现代码: [java] view plaincopy

  1. public interface Command {
  2. public void exe();
  3. }

[java] view plaincopy

  1. public class MyCommand implements Command { 1.
  2. private Receiver receiver; 1.
  3. public MyCommand(Receiver receiver) {
  4. this.receiver = receiver;
  5. } 1.
  6. @Override
  7. public void exe() {
  8. receiver.action();
  9. }
  10. } [java] view plaincopy

  11. public class Receiver {

  12. public void action(){
  13. System.out.println("command received!");
  14. }
  15. }

[java] view plaincopy

  1. public class Invoker { 1.
  2. private Command command; 1.
  3. public Invoker(Command command) {
  4. this.command = command;
  5. } 1.
  6. public void action(){
  7. command.exe();
  8. }
  9. } [java] view plaincopy

  10. public class Test { 1.

  11. public static void main(String[] args) {
  12. Receiver receiver = new Receiver();
  13. Command cmd = new MyCommand(receiver);
  14. Invoker invoker = new Invoker(cmd);
  15. invoker.action();
  16. }
  17. }

输出:command received!

这个很哈理解,命令模式的目的就是达到命令的发出者和执行者之间解耦,实现请求和执行分开,熟悉Struts的同学应该知道,Struts其实就是一种将请求和呈现分离的技术,其中必然涉及命令模式的思想! 其实每个设计模式都是很重要的一种思想,看上去很熟,其实是因为我们在学到的东西中都有涉及,尽管有时我们并不知道,其实在Java本身的设计之中处处都有体现,像AWT、JDBC、集合类、IO管道或者是Web框架,里面设计模式无处不在。因为我们篇幅有限,很难讲每一个设计模式都讲的很详细,不过我会尽我所能,尽量在有限的空间和篇幅内,把意思写清楚了,更好让大家明白。本章不出意外的话,应该是设计模式最后一讲了,首先还是上一下上篇开头的那个图:

本章讲讲第三类和第四类。

19、备忘录模式(Memento)

主要目的是保存一个对象的某个状态,以便在适当的时候恢复对象,个人觉得叫备份模式更形象些,通俗的讲下:假设有原始类A,A中有各种属性,A可以决定需要备份的属性,备忘录类B是用来存储A的一些内部状态,类C呢,就是一个用来存储备忘录的,且只能存储,不能修改等操作。做个图来分析一下:

Original类是原始类,里面有需要保存的属性value及创建一个备忘录类,用来保存value值。Memento类是备忘录类,Storage类是存储备忘录的类,持有Memento类的实例,该模式很好理解。直接看源码: [java] view plaincopy

  1. public class Original { 1.
  2. private String value; 1.
  3. public String getValue() {
  4. return value;
  5. } 1.
  6. public void setValue(String value) {
  7. this.value = value;
  8. } 1.
  9. public Original(String value) {
  10. this.value = value;
  11. } 1.
  12. public Memento createMemento(){
  13. return new Memento(value);
  14. } 1.
  15. public void restoreMemento(Memento memento){
  16. this.value = memento.getValue();
  17. }
  18. }

[java] view plaincopy

  1. public class Memento { 1.
  2. private String value; 1.
  3. public Memento(String value) {
  4. this.value = value;
  5. } 1.
  6. public String getValue() {
  7. return value;
  8. } 1.
  9. public void setValue(String value) {
  10. this.value = value;
  11. }
  12. } [java] view plaincopy

  13. public class Storage { 1.

  14. private Memento memento; 1.
  15. public Storage(Memento memento) {
  16. this.memento = memento;
  17. } 1.
  18. public Memento getMemento() {
  19. return memento;
  20. } 1.
  21. public void setMemento(Memento memento) {
  22. this.memento = memento;
  23. }
  24. }

测试类:

[java] view plaincopy

  1. public class Test { 1.
  2. public static void main(String[] args) { 1.
  3. // 创建原始类
  4. Original origi = new Original("egg"); 1.
  5. // 创建备忘录
  6. Storage storage = new Storage(origi.createMemento()); 1.
  7. // 修改原始类的状态
  8. System.out.println("初始化状态为:" + origi.getValue());
  9. origi.setValue("niu");
  10. System.out.println("修改后的状态为:" + origi.getValue()); 1.
  11. // 回复原始类的状态
  12. origi.restoreMemento(storage.getMemento());
  13. System.out.println("恢复后的状态为:" + origi.getValue());
  14. }
  15. }

输出:

初始化状态为:egg 修改后的状态为:niu 恢复后的状态为:egg

简单描述下:新建原始类时,value被初始化为egg,后经过修改,将value的值置为niu,最后倒数第二行进行恢复状态,结果成功恢复了。其实我觉得这个模式叫“备份-恢复”模式最形象。

20、状态模式(State)

核心思想就是:当对象的状态改变时,同时改变其行为,很好理解!就拿QQ来说,有几种状态,在线、隐身、忙碌等,每个状态对应不同的操作,而且你的好友也能看到你的状态,所以,状态模式就两点:1、可以通过改变状态来获得不同的行为。2、你的好友能同时看到你的变化。看图:

State类是个状态类,Context类可以实现切换,我们来看看代码:

[java] view plaincopy

  1. package com.xtfggef.dp.state; 1.
  2. ///
  3. /* 状态类的核心类
  4. /* 2012-12-1
  5. /* @author erqing
  6. /*
  7. /*/
  8. public class State { 1.
  9. private String value; 1.
  10. public String getValue() {
  11. return value;
  12. } 1.
  13. public void setValue(String value) {
  14. this.value = value;
  15. } 1.
  16. public void method1(){
  17. System.out.println("execute the first opt!");
  18. } 1.
  19. public void method2(){
  20. System.out.println("execute the second opt!");
  21. }
  22. }

[java] view plaincopy

  1. package com.xtfggef.dp.state; 1.
  2. ///
  3. /* 状态模式的切换类 2012-12-1
  4. /* @author erqing
  5. /*
  6. /*/
  7. public class Context { 1.
  8. private State state; 1.
  9. public Context(State state) {
  10. this.state = state;
  11. } 1.
  12. public State getState() {
  13. return state;
  14. } 1.
  15. public void setState(State state) {
  16. this.state = state;
  17. } 1.
  18. public void method() {
  19. if (state.getValue().equals("state1")) {
  20. state.method1();
  21. } else if (state.getValue().equals("state2")) {
  22. state.method2();
  23. }
  24. }
  25. } 测试类:

[java] view plaincopy

  1. public class Test { 1.
  2. public static void main(String[] args) { 1.
  3. State state = new State();
  4. Context context = new Context(state); 1.
  5. //设置第一种状态
  6. state.setValue("state1");
  7. context.method(); 1.
  8. //设置第二种状态
  9. state.setValue("state2");
  10. context.method();
  11. }
  12. } 输出:

execute the first opt! execute the second opt!

根据这个特性,状态模式在日常开发中用的挺多的,尤其是做网站的时候,我们有时希望根据对象的某一属性,区别开他们的一些功能,比如说简单的权限控制等。 21、访问者模式(Visitor)

访问者模式把数据结构和作用于结构上的操作解耦合,使得操作集合可相对自由地演化。访问者模式适用于数据结构相对稳定算法又易变化的系统。因为访问者模式使得算法操作增加变得容易。若系统数据结构对象易于变化,经常有新的数据对象增加进来,则不适合使用访问者模式。访问者模式的优点是增加操作很容易,因为增加操作意味着增加新的访问者。访问者模式将有关行为集中到一个访问者对象中,其改变不影响系统数据结构。其缺点就是增加新的数据结构很困难。—— From 百科

简单来说,访问者模式就是一种分离对象数据结构与行为的方法,通过这种分离,可达到为一个被访问者动态添加新的操作而无需做其它的修改的效果。简单关系图:

来看看原码:一个Visitor类,存放要访问的对象,

[java] view plaincopy

  1. public interface Visitor {
  2. public void visit(Subject sub);
  3. }

[java] view plaincopy

  1. public class MyVisitor implements Visitor { 1.
  2. @Override
  3. public void visit(Subject sub) {
  4. System.out.println("visit the subject:"+sub.getSubject());
  5. }
  6. } Subject类,accept方法,接受将要访问它的对象,getSubject()获取将要被访问的属性, [java] view plaincopy

  7. public interface Subject {

  8. public void accept(Visitor visitor);
  9. public String getSubject();
  10. }

[java] view plaincopy

  1. public class MySubject implements Subject { 1.
  2. @Override
  3. public void accept(Visitor visitor) {
  4. visitor.visit(this);
  5. } 1.
  6. @Override
  7. public String getSubject() {
  8. return "love";
  9. }
  10. } 测试:

[java] view plaincopy

  1. public class Test { 1.
  2. public static void main(String[] args) { 1.
  3. Visitor visitor = new MyVisitor();
  4. Subject sub = new MySubject();
  5. sub.accept(visitor);
  6. }
  7. } 输出:visit the subject:love

该模式适用场景:如果我们想为一个现有的类增加新功能,不得不考虑几个事情:1、新功能会不会与现有功能出现兼容性问题?2、以后会不会再需要添加?3、如果类不允许修改代码怎么办?面对这些问题,最好的解决方法就是使用访问者模式,访问者模式适用于数据结构相对稳定的系统,把数据结构和算法解耦, 22、中介者模式(Mediator)

中介者模式也是用来降低类类之间的耦合的,因为如果类类之间有依赖关系的话,不利于功能的拓展和维护,因为只要修改一个对象,其它关联的对象都得进行修改。如果使用中介者模式,只需关心和Mediator类的关系,具体类类之间的关系及调度交给Mediator就行,这有点像spring容器的作用。先看看图:

User类统一接口,User1和User2分别是不同的对象,二者之间有关联,如果不采用中介者模式,则需要二者相互持有引用,这样二者的耦合度很高,为了解耦,引入了Mediator类,提供统一接口,MyMediator为其实现类,里面持有User1和User2的实例,用来实现对User1和User2的控制。这样User1和User2两个对象相互独立,他们只需要保持好和Mediator之间的关系就行,剩下的全由MyMediator类来维护!基本实现:

[java] view plaincopy

  1. public interface Mediator {
  2. public void createMediator();
  3. public void workAll();
  4. }

[java] view plaincopy

  1. public class MyMediator implements Mediator { 1.
  2. private User user1;
  3. private User user2; 1.
  4. public User getUser1() {
  5. return user1;
  6. } 1.
  7. public User getUser2() {
  8. return user2;
  9. } 1.
  10. @Override
  11. public void createMediator() {
  12. user1 = new User1(this);
  13. user2 = new User2(this);
  14. } 1.
  15. @Override
  16. public void workAll() {
  17. user1.work();
  18. user2.work();
  19. }
  20. } [java] view plaincopy

  21. public abstract class User { 1.

  22. private Mediator mediator; 1.
  23. public Mediator getMediator(){
  24. return mediator;
  25. } 1.
  26. public User(Mediator mediator) {
  27. this.mediator = mediator;
  28. } 1.
  29. public abstract void work();
  30. }

[java] view plaincopy

  1. public class User1 extends User { 1.
  2. public User1(Mediator mediator){
  3. super(mediator);
  4. } 1.
  5. @Override
  6. public void work() {
  7. System.out.println("user1 exe!");
  8. }
  9. } [java] view plaincopy

  10. public class User2 extends User { 1.

  11. public User2(Mediator mediator){
  12. super(mediator);
  13. } 1.
  14. @Override
  15. public void work() {
  16. System.out.println("user2 exe!");
  17. }
  18. } 测试类:

[java] view plaincopy

  1. public class Test { 1.
  2. public static void main(String[] args) {
  3. Mediator mediator = new MyMediator();
  4. mediator.createMediator();
  5. mediator.workAll();
  6. }
  7. } 输出:

user1 exe! user2 exe! 23、解释器模式(Interpreter) 解释器模式是我们暂时的最后一讲,一般主要应用在OOP开发中的编译器的开发中,所以适用面比较窄。

Context类是一个上下文环境类,Plus和Minus分别是用来计算的实现,代码如下:

[java] view plaincopy

  1. public interface Expression {
  2. public int interpret(Context context);
  3. }

[java] view plaincopy

  1. public class Plus implements Expression { 1.
  2. @Override
  3. public int interpret(Context context) {
  4. return context.getNum1()+context.getNum2();
  5. }
  6. } [java] view plaincopy

  7. public class Minus implements Expression { 1.

  8. @Override
  9. public int interpret(Context context) {
  10. return context.getNum1()-context.getNum2();
  11. }
  12. }

[java] view plaincopy

  1. public class Context { 1.
  2. private int num1;
  3. private int num2; 1.
  4. public Context(int num1, int num2) {
  5. this.num1 = num1;
  6. this.num2 = num2;
  7. } 1.
  8. public int getNum1() {
  9. return num1;
  10. }
  11. public void setNum1(int num1) {
  12. this.num1 = num1;
  13. }
  14. public int getNum2() {
  15. return num2;
  16. }
  17. public void setNum2(int num2) {
  18. this.num2 = num2;
  19. } 1. 1.
  20. } [java] view plaincopy

  21. public class Test { 1.

  22. public static void main(String[] args) { 1.
  23. // 计算9+2-8的值
  24. int result = new Minus().interpret((new Context(new Plus()
  25. .interpret(new Context(9, 2)), 8)));
  26. System.out.println(result);
  27. }
  28. } 最后输出正确的结果:3。

基本就这样,解释器模式用来做各种各样的解释器,如正则表达式等的解释器等等!

设计模式基本就这么大概讲完了,总体感觉有点简略,的确,这么点儿篇幅,不足以对整个23种设计模式做全面的阐述,此处读者可将它作为一个理论基础去学习,通过这四篇博文,先基本有个概念,虽然我讲的有些简单,但基本都能说明问题及他们的特点,如果对哪一个感兴趣,可以继续深入研究!同时我也会不断更新,尽量补全遗漏、修正不足,欢迎广大读者及时提出好的建议,我们一起学习!项目中涉及到的代码,已经放到了我的资源里:http://download.csdn.net/detail/zhangerqing/4835830(因为我不喜欢不劳而获,所以没有免积分,只设置了5个,如果有人实在没积分又急要,那么联系我吧,我给你发过去)。

在阅读的过程中,有任何问题,请联系:egg。

邮箱:xtfggef@gmail.com 微博:http://weibo.com/xtfggefa

  • 大小: 92.6 KB

  • 大小: 12 KB

  • 大小: 21.3 KB

  • 大小: 28.8 KB

  • 大小: 50.7 KB

  • 大小: 19.2 KB

  • 大小: 20.3 KB

  • 大小: 21.8 KB

  • 大小: 13.1 KB

  • 大小: 14.9 KB

  • 大小: 23.2 KB

  • 大小: 26.6 KB

  • 大小: 17.4 KB

  • 大小: 14.2 KB

  • 大小: 17 KB

  • 大小: 14.8 KB

  • 大小: 51.2 KB

  • 大小: 27.1 KB

  • 大小: 16.9 KB

  • 大小: 33.6 KB

  • 大小: 21 KB

  • 大小: 48 KB

  • 大小: 24.4 KB

  • 大小: 14.4 KB

  • 大小: 18.2 KB

  • 大小: 39.5 KB

  • 大小: 29.7 KB

  • 大小: 34.6 KB

  • 大小: 20.7 KB

  • 查看图片附件

分享到: 一例讲述lang,util,text包50种高级用法| 收集多年的开发资料和开发工具

64 楼 qvp8前天

最近看设计模式,看了几个。感觉还是本主说的清楚。 63 楼 zz563143188 2013-05-14

满手都是炸 写道

今天听老师讲 struts2里的action是非单例, 搜到这个看看 好的,spring单例用的广

62 楼 zz563143188 2013-05-14

勇气魄力 写道

写的不错, 呵呵,多琢磨,有争议的地方提出来。 61 楼 满手都是炸2013-05-13

今天听老师讲 struts2里的action是非单例, 搜到这个看看

60 楼 勇气魄力2013-05-12

写的不错, 59 楼 zz563143188 2013-05-10

qqweixing123 写道

楼主其实文笔不错,讲得比较易懂,但是有些模式的理解确实需要再斟酌一下,然后再发表一下就更好了,不然把别人误了就不好了。 好吧,能具体一些吗。我再重新审视一下

58 楼 qqweixing123 2013-05-10

楼主其实文笔不错,讲得比较易懂,但是有些模式的理解确实需要再斟酌一下,然后再发表一下就更好了,不然把别人误了就不好了。 57 楼 zz563143188 2013-05-08

teasp 写道

zz563143188 写道

teasp 写道

楼主根本就没理解自己要讲的东西就在这里误人子弟。看了前面两个模式工厂和单例。抽象工厂方法模式有问题。单例的除了那个利用私有工厂产生实例的是正确的外,其他的实现方式都错了。 看来你是认真分析或者仔细斟酌过后才得出和结论吧,愿兄台能够具体指出歧义的地方。 当然是仔细斟酌后给出的结论。我只会在付费后给出正确的解,请原谅。因为我指出有错误已经是最大的帮助了,你完全可以自己找到正确的做法。 天下熙熙皆为利来,天下攘攘皆为利往。人为财死,鸟为食亡。道不同则不相为谋;志不合不相与随。虽兄弟厉害,可咱们没相交点。

56 楼 teasp 2013-05-08

zz563143188 写道

teasp 写道

楼主根本就没理解自己要讲的东西就在这里误人子弟。看了前面两个模式工厂和单例。抽象工厂方法模式有问题。单例的除了那个利用私有工厂产生实例的是正确的外,其他的实现方式都错了。 看来你是认真分析或者仔细斟酌过后才得出和结论吧,愿兄台能够具体指出歧义的地方。 当然是仔细斟酌后给出的结论。我只会在付费后给出正确的解,请原谅。因为我指出有错误已经是最大的帮助了,你完全可以自己找到正确的做法。 55 楼 zz563143188 2013-05-07

teasp 写道

楼主根本就没理解自己要讲的东西就在这里误人子弟。看了前面两个模式工厂和单例。抽象工厂方法模式有问题。单例的除了那个利用私有工厂产生实例的是正确的外,其他的实现方式都错了。 看来你是认真分析或者仔细斟酌过后才得出和结论吧,愿兄台能够具体指出歧义的地方。

54 楼 zz563143188 2013-05-07

GLC 写道

来到这里我想自己发现了一座宝库。。。 若遇知已则相见恨晚,若遇同行则相生相克。 53 楼 zz563143188 2013-05-07

qqweixing123 写道

您好,你的单例模式里对于并发情况下的处理感觉弄得过于复杂了,我的想法是: 1.public class Singleton { 2.

  1. // 持有私有静态实例,防止被引用,此处赋值为null,目的是实现延迟加载 //
  2. private static Singleton instance = null; 替换成: private static Singleton instance = new Singleton(); 5.
  3. // 私有构造方法,防止被实例化 //
  4. private Singleton() {
  5. } 9.
  6. // 静态工程方法,创建实例 //
  7. public static Singleton getInstance() {
  8. 将 **if (instance == null) {
  9. instance = new Singleton();
  10. }** 去掉
  11. return instance;
  12. } 17.
  13. // 如果该对象被用于序列化,可以保证对象在序列化前后保持一致 //
  14. public Object readResolve() {
  15. return instance;
  16. } 22.} 每一个模式都是三部分组成的规则,表达的是某一个环境,一个问题以及解决问题的方案。

52 楼 teasp 2013-05-07

qqweixing123 写道

您好,你的单例模式里对于并发情况下的处理感觉弄得过于复杂了,我的想法是: 1.public class Singleton { 2.

  1. // 持有私有静态实例,防止被引用,此处赋值为null,目的是实现延迟加载 //
  2. private static Singleton instance = null; 替换成: private static Singleton instance = new Singleton(); 5.
  3. // 私有构造方法,防止被实例化 //
  4. private Singleton() {
  5. } 9.
  6. // 静态工程方法,创建实例 //
  7. public static Singleton getInstance() {
  8. 将 **if (instance == null) {
  9. instance = new Singleton();
  10. }** 去掉
  11. return instance;
  12. } 17.
  13. // 如果该对象被用于序列化,可以保证对象在序列化前后保持一致 //
  14. public Object readResolve() {
  15. return instance;
  16. } 22.} 你这个是即时加载的,楼主没讲,其实这种是最简单安全的。 51 楼 teasp 2013-05-07

楼主根本就没理解自己要讲的东西就在这里误人子弟。看了前面两个模式工厂和单例。抽象工厂方法模式有问题。单例的除了那个利用私有工厂产生实例的是正确的外,其他的实现方式都错了。

50 楼 GLC 2013-05-04

来到这里我想自己发现了一座宝库。。。 49 楼 qqweixing123 2013-05-02

您好,你的单例模式里对于并发情况下的处理感觉弄得过于复杂了,我的想法是: 1.public class Singleton { 2.

  1. // 持有私有静态实例,防止被引用,此处赋值为null,目的是实现延迟加载 //
  2. private static Singleton instance = null; 替换成: private static Singleton instance = new Singleton(); 5.
  3. // 私有构造方法,防止被实例化 //
  4. private Singleton() {
  5. } 9.
  6. // 静态工程方法,创建实例 //
  7. public static Singleton getInstance() {
  8. 将 **if (instance == null) {
  9. instance = new Singleton();
  10. }** 去掉
  11. return instance;
  12. } 17.
  13. // 如果该对象被用于序列化,可以保证对象在序列化前后保持一致 //
  14. public Object readResolve() {
  15. return instance;
  16. } 22.}

48 楼 zz563143188 2013-04-25

yjingy 写道

zz563143188 写道

yjingy 写道

为毛总感觉合成模式那里有点不对劲的感觉。。。 记得要区分叶子节点和树节点,而且根据树节点中管理方法的定义是否放在公共接口中有两种不同的区分来着。 可以说详细一点吗 这个可以看这个网址:http://eneasy.iteye.com/blog/174889,是同一个作者的博客,也是用的阎宏的《java与模式》书中的例子。 好的,我去看看 47 楼 zz563143188 2013-04-25

yjingy 写道

zz563143188 写道

yjingy 写道

刚看了几个,抽象工厂模式有点问题,抽象工厂应该是对应产品族的情况下使用的。 可以说详细一点 我看设计模式的时候看的是阎宏的《java与模式》一书,在网上搜了下,比较具体的描述可以看这个地方的:http://eneasy.iteye.com/blog/174831,在页面接近底部的位置,抽象工厂方法模式。 好的,我仔细看看

46 楼 yjingy 2013-04-25

zz563143188 写道

yjingy 写道

为毛总感觉合成模式那里有点不对劲的感觉。。。 记得要区分叶子节点和树节点,而且根据树节点中管理方法的定义是否放在公共接口中有两种不同的区分来着。 可以说详细一点吗 这个可以看这个网址:http://eneasy.iteye.com/blog/174889,是同一个作者的博客,也是用的阎宏的《java与模式》书中的例子。 45 楼 yjingy 2013-04-25

zz563143188 写道

yjingy 写道

刚看了几个,抽象工厂模式有点问题,抽象工厂应该是对应产品族的情况下使用的。 可以说详细一点 我看设计模式的时候看的是阎宏的《java与模式》一书,在网上搜了下,比较具体的描述可以看这个地方的:http://eneasy.iteye.com/blog/174831,在页面接近底部的位置,抽象工厂方法模式。

« 上一页 1 2 3 4 下一页 »