??xml version="1.0" encoding="utf-8" standalone="yes"?> 雉碎圎ͼ学习q很多轮设计模式。L学过忘。后来就在google docs上做了一pdW记Q方便复习。最q把q些W记搬家到blogjava上了Q一ҎӞ一边又复习一遍。学习设计模式有两个意义Q?/p>
一、学习设计模式最重要的是了解模式的应用场景。编E遇到特定场景的话,要有意识联想到设计模式,哪怕细节忘了也没关p,ȝ书就扑ֈ了?/p>
二、提高设计的思想。学习设计模式的时候,要体会模式精妙之处,当想明白大师思想和自q差距的时候,差距q短了一点儿?/p>
有的模式qxE无奇Q应用却q泛。有的模式设计精巧,应用场景却不易遇到。无论如何,要么掌握工具Q要么学到思想Q都是收莗?/p>
最适合单概括设计模式的是UML图,攉了一个非常好的资源,分n在我的sky drive|络盘上,包含23U设计模式的UML?/p>
http://cid-d8b11f9bf86fecfa.office.live.com/self.aspx/.Public/books/designpatternscard.pdf
设计模式可以分ؓ三类Qbehavioural, structural, creational
behavioural 11 U?/strong>
1. MementoQ备忘录Q?/p>
_yE度Q?5?/p>
应用q泛Q??/p>
memento适合保存/恢复状态的场景。分为宽接口和窄接口。学习就要学H接口! 具体误Q?http://m.tkk7.com/vcycyv/archive/2011/02/08/343949.html 2. Chain of Responsibility(责Q? _yE度Q?3?/p>
应用q泛Q?3?/p>
适合用在"一pdhandler”的场景下。分为纯和不U两U,好像奛_儿也可以q么分? 具体误Q?/p>
http://m.tkk7.com/vcycyv/archive/2011/02/12/344167.html
3. ObserverQ观察者) 因ؓjava里有Obserable和ObserverQ?所以通常在java里不会自p计观察者模式?/p>
4. Command(命o模式) _yE度Q??/p>
应用q泛Q??/p>
command模式用来解耦invoker和receiver. 具体误Q?/p>
http://m.tkk7.com/vcycyv/archive/2011/02/12/344168.html
5. State(状态模? _yE度Q??/p>
应用q泛Q??/p>
OO~程如果出现多个相同的if…else条gQ应该考虑用state模式重构。work flow的状态器也是ZState模式的?/p>
具体误Q?/p>
http://m.tkk7.com/vcycyv/archive/2011/02/09/343998.html
6. Interpreter _yE度Q?N/A 应用q泛Q?1?/p>
据说只有搜烦引擎才用得上q个模式Q反正我每次学设计模式的时候,都把q个跌去,是不喜Ƣ,抱歉?/p>
7. StrategyQ策略模式) _yE度Q?2?/p>
应用q泛Q??/p>
用来装不同法。从uml图上看和state模式一栗?因ؓq个太简单了Q所以没记笔讎ͼq个忘不了?/p>
8. Iterator(q代? Java Collection都可以P代,在java上不需要格外设计iterator?/p>
9. Template Method(模板Ҏ) _yE度Q??/p>
应用q泛Q??/p>
见名知义。太单了Q学q一遍就不会忘。但是这个应用非常广泛! 10. Mediator(仲裁? _yE度Q??/p>
应用q泛Q??/p>
用来解耦多个peer。个得这个模式多半会让mediator十分臃肿Qmediator本n需要有很清晰的设计才能使用。应用场景恐怕也?/p>
具体误Q?/p>
http://m.tkk7.com/vcycyv/archive/2011/02/08/343951.html
11. Visitor(讉K? _yE度Q??/p>
应用q泛Q??/p>
collection里存一个类pȝentryӞ使用visitor模式可以避免instance of的用。更重要的是方便扩展cȝ?/p>
具体误Q?/p>
http://m.tkk7.com/vcycyv/archive/2011/02/13/344194.html
Structure 7U?/strong>
12. adapter(适配? _yE度Q??/p>
应用q泛Q??/p>
个h觉得Adapteeq三方提供的时候才可能用上q个模式。简单应用范围又H,?/p>
13. Proxy(代理) _yE度Q??/p>
应用q泛Q??/p>
aop是代理模式的一U发挥。Spring和Hibernate都大量用proxy。可以引甛_学JDK的dynamic proxy。模式简单,略?/p>
14. Bridge _yE度Q?5?/p>
应用q泛Q?3?/p>
Bridge在技术上是strategy的进一步发挥,但侧重在实现与抽象的解耦?/p>
具体见:
http://m.tkk7.com/vcycyv/archive/2011/02/08/343950.html
15. Composite _yE度Q?4?/p>
应用q泛Q?3?/p>
适用于树状结构?/p>
具体见:
http://m.tkk7.com/vcycyv/archive/2011/02/13/344209.html
16. Decorator(装饰) _yE度Q?5?/p>
应用q泛Q??/p>
在java I/O中广泛用。ؓ了解决“类爆炸”的问题?/p>
具体误Q?/p>
http://m.tkk7.com/vcycyv/archive/2011/02/09/343997.html
17. Facade(门面) q个UMLN没有Q算马模式Q?/p>
18. Flyweight _yE度Q??/p>
应用q泛Q??/p>
分“单U”“复合”两U,本n包含了工厂方法模式。一pd对象如果他们都有某部分属于特定集合,p他们׃nq个特定集合以节省资源?/p>
具体误Q?/p>
http://m.tkk7.com/vcycyv/archive/2011/02/12/344169.html
Creational 6 U?/strong>
19. Factory Method(工厂Ҏ) _yE度Q??/p>
应用q泛Q??/p>
两个变种Q一个是Ҏ参数创徏对象Q一个是factorycȝ对应产品cȝ。面向接口编E在创徏模式的体现?/p>
具体误Q?/p>
http://m.tkk7.com/vcycyv/archive/2011/02/13/344176.html
20. Abstract FactoryQ抽象工厂) _yE度Q??/p>
应用q泛Q??/p>
只有产品有两个类pȝ时候才用得上?/p>
具体误Q?/p>
http://m.tkk7.com/vcycyv/archive/2011/02/15/344390.html
21. Builder _yE度Q?5?/p>
应用q泛Q?2?/p>
产品分部分,q且build的过E不定的时候考虑用这U模式。是模板模式的一U发?/p>
具体误Q?/p>
http://m.tkk7.com/vcycyv/archive/2011/02/09/343995.html
22. Prototype(原型) java有cloneable的支持,所以通常不需要自p计prototype. java用prototype的时候注意深复制复制的问题。prototype之外的一个选择是提供一个constructor接受本类型对象作为参敎ͼq个方式更加实用Q?/p>
23. singleton(单? 古典的singleton分ؓ懒汉Q饿汉两U。JDK1.5之后可以用唯一entry 的enum作ؓsingleton的实现。好处有两点Q一是简单。二是不需要格外处理serializable的情?/p>
Author : 岑文?/span> ( 淘宝花名Q放?/span> )
Email: fangweng@taobao.com
Blog: http://blog.csdn.net/cenwenchu79
Date: 2009-08-26
刚从阿Y到淘宝不久,现在主要负责TOPq_的技术框架设计,同时要肩负“救火”和“防火”的工作Q也需要培d队的同学能够有“防火”意识,减少“救火”次敎ͼ因此今天下午׃一Ҏ_也没于写M?/span>PPTQ就直接自己想的v来的一些自p为应用架构设计“防火”知识做了一下事例分享,q里也想记录下来l更多的同学分n一下,当然很多都是老生常谈的常识,但是有时候不l意׃忘记一些血的教训?/span>
资源是有限的
着火点Q?/span>
pȝ设计的时候L估摸不到会有大数据量从远端传输过来(例如处理HttphӞ对于大附件内容的处理Q全部装载到内存Q结果资源耗尽。从搜烦引擎或?/span>DB或者缓存里面拉数据Q没有分,l果内存被吃?/span>Socket无限建立q接Q结?/span>linux的文件句柄被耗尽。)
防火点:
对业务场景中资源的分配与甌需要做C限控Ӟ以及辑ֈ上限以后的逻辑处理Q排队,丢弃Q告警)。可以采取一些滑动窗口设计来不需要过多处理的内容分段直接送入下一个处理管道中?/span>
依赖是未知的
着火点Q?/span>
事务中嵌入对于第三方pȝ的请求(例如在数据库操作时去发送邮件或者缓存获取内容,l果q接池资源被HoldQ导致系l不可用Q。默认依赖系l会l出l果Q如果出现异常就反复重试Q结果对方被压垮Q自׃牺牲?/span>
防火点:
对于W三方系l的依赖能够异步的就采用异步方式Q能够从LE? 中剥ȝ剥R同时设计好定w的机Ӟ采用本地时效性缓存减对Ҏ的压力和依赖。最重要的就是注意系l间的死锁,甌了一套资源处理业务逻辑Q结果由 于远端系l的不可用,D本地资源的无法释放,最后击垮自ql?/span>
U程安全与性能
着火点Q?/span>
对于U程不安全的对象处理一定要心Q否则业务出现异常的地方其实已经设计出现问题的地方十万八千里,问题时常成ؓ灵异问题Q解军_有靠l验?/span>
防火点:
首先对于自己设计的类和方法需要注释是否是U程安全的。同时明类的用场景,对线E安全及高性能作判断,因ؓ采用U程安全的对象一定会有性能损耗。最q给同学写的一?/span>Http消息?/span>Lazy获取参数Q就是线E不安全的类Q但是这个类只会保存?/span>ThreadLocal中,因此不存在问题。很直观的一点判断是否线E安全,q看你设计的类里面的成员变量在多线E操作时候是否会有ƈ发问题,例如一个普通的MapQ多个线E操作就会导致结果的不可估量性?/span>
资源释放
着火点Q?/span>
正常逻辑都会?/span>IO关闭,Socket关闭Q但是异常抛出时候,没有走到资源释放的流E中Q生了资源泄露问题。另外,资源中可能会有内嵌资源,当内部资源被外部的对象引用,则释攑ְ不成功,内部资源依然会泄霌Ӏ一些需要显式回收的资源Q例?/span>ThreadLocalQ,如果不回Ӟ那么下次U程被操作系l重用,则会出现莫名其妙的问题(Java的线E创建和使用依赖于操作系l的实现Q?/span>
防火点:
Finally的处理。需要释攄资源要做深度查。需要显式回收的资源要确保用完毕以后被回收Q异常情况也需要考虑Q?/span>
创徏与复?/span>
着火点Q?/span>
在以前设?/span>Cache客户端的时候,有同学给我徏议说我对于字节数l利用可以采取复用的方式Q这样可以减对象的甌。但是做了一下测试,q样的重复利用其实效果不像想象的那么好,甚至q不如直接创建?/span>
防火点:
Java的垃圾收集器已经在性能上有了很大的提高Q同时对于对象的复用需要考虑对象复用前的初始化或者是内容重置Q这些得成本及复杂度可能q远要高于复用带来的优势Q因此需要根据具体的业务场景选择复用和创建。当然对于稀~源采用池的方式是最好的?/span>
字符串处理,日志U别的选择
着火点Q?/span>
q两个是问题,但是会带来大ȝ。首先字W串的篏加是老生常谈的问题,但是很多新手不以为然Q当你是一个高速运转的pȝӞ你就会发?/span>1ms的g时在上千万次调用下回被无限放大,10byte的申P在上千万ơ的h下会带来GC多次的操作(带来的短暂处理停滞直接媄响系l的可用性)。日志别的随意性会DU上环境日志q速膨胀Q出错难以查找,影响pȝ的效率。(log4j优化的再好也是要写文件的Q虽然是异步刷页Q?/span>
防火点:
谨慎处理字符串拼接,选择U程安全或者不安全的两?/span>StringBuilder?/span>StringBuffer。日志尽量区分清楚,debug?/span>InfoQ前者纯_调试,可以有v量信息,Info一般用于系l或者模块的状况报告?/span>Warn通常不徏议用了?/span>Error把你需要的关键信息都打出来。附带这里说一下对于日期对象的处理Q在传输和保存的q程中,都还是采?/span>long型,可以很好的提高性能及满_际化的需求?/span>
原子操作与ƈ发控?/span>
着火点Q?/span>
对于本地的对象操作通常情况下通过锁机制保证ƈ发的一致性,当在设计一个对于资源访问控制的{略Ӟ例如集群应用处理某h每天发送短?/span>1000条,q时候计数器保存在远端的集中式缓存中Q采?/span>get?/span>put方式׃有ƈ发问题,因ؓ在应用获得到999q个计数器值的时候,也许正有10000个请求也获得了这个|q样原有的控制就失效了?/span>
防火点:
其实是一个原子操作的支持Q本地数据可以通过锁来辑ֈ原子操作Q远E依赖就需要对方系l提供原子操作接口来实现高ƈ发下的业务处理,例如Memcached Cache提供?/span>incr ?/span>decr。结合黑名单{略Q计数器可以发挥很多用途,包括及时监控告警{?/span>
接口实现与松耦合
着火点:
没有接口提供Q团队间合作困难Q无?/span>MockQ相互之间进度媄响很大。同时业务实现的修改直接影响业务调用方,使得双方耦合性很强,pȝ不稳定性被攑֤?/span>
防火点:
对外提供的服务,或者模块间交互的服务都需要接口化。框架性代码需要在模块载入时考虑是否需要接口化定义Q以便在不同环境可以切换不同实现提供对特D场景的支持Q同时也可以具体实现g后交l用者实玎ͼ使得框架更加灉|?/span>Jdk对于xml的解析就是最好的范例?/span>
灉|性和性能和可l护性的折中
着火点Q?/span>
最q看了一些同学的代码Q看到大量的使用了反,拦截器等。但是在U上环境q行q程中就发现对于一些拦截器的配|疏漏导致系l性能大幅度降低。对于几十个spring文gQ有谁能够很清楚和直观的了解到这些看似灵zd无R入性的设计?/span>
防火点:
对于业务逻辑不复杂,同时场景不多变的程采用单的实现Q不要追求花哨的灉|性,带来的只会是可读性,可维护性,可用性的降低?/span>
要有分布式和q发的观念,但是不要本末倒置
着火点Q?/span>
有些同学在做设计的时候考虑的很清晰Q但是就是没有考虑集群部v的情况,l果pȝ上线以后出现了无法集部|的问题。ƈ发情늚设计也一P仅仅在满业务需求以后,对于多用户ƈ发操作的考虑~失Q导致系l流E错误?/span>
防火点:
设计的时候需要适度考虑q些问题Q但是是在满现有业务逻辑的前提下Q不要ؓ了追求分布式而分布式?/span>
便利性的函数与性能的冲H?/span>
着火点Q?/span>
首先x的是q点适用范围有限Q高速运转的模块Q。对?/span>String,Date{对象的便利性函敎ͼ例如正则匚wQ分ԌFormat{等其实都会有不的性能损耗。例如你只是需要判断文件名最后的后缀是否满需求,采用了正则匹配,l果发现性能在高速运转的情况下大大下降?/span>
防火点:
高速运转的模块量采用原始方式或者半原始方式。例如上面说到的文g后缀Q就?/span>string?/span>endwith来判断。对于一些字W串的替换,能够用字W串拼接拼接。对于一些字节流的处理也可以自己Ҏ需求来订制的写。ȝ一句话Q能够满的q最低成本的Ҏ?/span>
防止pȝ设计的完备性成为攻L者压力的瓉
着火点Q?/span>
在很多设计的时候,对于一些系l设计讲I比较完。例如对于对象的查询会分本地~存Q集中缓存,DB三个阶段。当Ҏd采用不存在的资源名称时候,q种分阶D늚设计反而会增加pȝ负荷?/span>
防火点:
化流E的分支和层ơ,对于消耗性资源的讉K量减少或者没有(采用黑名单本地缓存或者集中缓存的方式Q,同时?/span>Pull?/span>Push方式Q通过控制数据变更Ҏ通知相关pȝQ而非轮询获取更新状态?/span>
多~存和异步缓解异构系l的瓉
着火点Q?/span>
有时候设计系l时Q服务提供方向我们许Ҏpȝ如何高效和健壮,但是当频J访问生网l风暴的时候,我们发现原来带宽和网l?/span>IO本n都会成ؓ瓉?/span>
防火点:
对于W三方系l的依赖Q要做到松耦合p从流E的异步化来实现。同旉过~存的用来辑ֈQ系l的高效性和降低对于W三方系l的依赖E度。这样可以大大降低系l的瓉?/span>
q行期白盒化Q模块可重置
着火点Q?/span>
pȝq行h以后无法在知道内部的状态,也无法对问题lgq行单独处理Q造成U上环境的不可知性和无法部分修复。不得不停机重v和看日志?/span>
防火点:
模块设计q程中考虑q行期可观测和可重置Q提高系l的模块化程度及健壮性?/span>
站在用户角度设计接口Q提升系l可用?/span>
着火点Q?/span>
L从自w业务体pd架构去考虑如何设计对外接口Q但是发现最后用户用的很别扭,同时׃需求不能直接被满Q会多次反复调用接口Q导致自w系l的压力增大。例如对于一个状态的查接口,是否提供一个状态变更通知接口׃极大降低轮询的压?/span>
防火点:
需要从客户角度考虑问题Q设计接口,防止需求和实现pQ导致系l压力增加?/span>
懒惰有时候是件好?/span>
着火点:
业务程中很多耗时的操作在程~排斚w没有考虑清楚Q当耗时工作做完以后Q发CW合最基本的交验,q样׃Dpȝ无谓的增加了开销。对于需要申L资源Q考虑处理程的阶D,阶段性申误优于一ơ申P不过需要注意死锁)?/span>
防火?/span>:
程~排需要合理性,量耗时的工作放到合理的位置Q同时做好基的防d轻量前端屏障逻辑Q提高系l的健壮性?/span>
LE和副流E隔?/span>
着火点Q?/span>
SIP早先的日志分析模块中有分析日志,备䆾Q发邮gQ更新系l缓存,操作数据库等多种操作Q但是一股脑儉K被放C个流E中Q结果当邮g没有发成功导致整个流E的p|?/span>
防火点:
把真正的LE梳理出来,同时对于一些副程可以考虑采用后台异步方式完成Q提高系l稳定性?/span>
模块间接口交互,控制资源直接操作入口
着火点Q?/span>
对于数据库中的资源Q何模块不区分范围都可以访问,最后导致数据结构变更困难,业务对象理混ؕQ模块无法剥ȝ立?/span>
防火点:
模块化设计的基本思想Q模块间通过接口交互获得其他模块辖的数据,接口方式屏蔽了对于后端实现及业务对象的依赖?/span>
学习份外的事情,配置军_成|
着火点Q?/span>
没有SA高不定环境Q也无法了解操作pȝ的配|与Web容器的配|对于应用的影响。没?/span>DBA无法确定如何写SQL避免一些简单的耗时查询。没有测试同学就无法作压力测试,无法了解当前pȝ性能?/span>
防火点:
多学多问Q多了解一些其他岗位的内容Q才能够更加全面的掌握好架构设计?/span>
不要q信
着火点Q?/span>
L看到新技术如何有优点Q但是看不到它的成熟度。L听到很多l验之谈Q但是从来没有真的比较过。结果就是别什么就是什么,pȝ地稳定性和可用性基?/span>Google出来的结果?/span>
防火点:
需要听取各U意见和l验Q同时用试l果说明问题的结果,看代码说明结果背后的问题。这h会走得更加踏实,学的更加实际。其实技术发展来_真正的基性内容还是有限的Q而且各种技术都是触cL通。分布式Q不论是文gpȝQ?/span>DBQ缓存都会遇到分布式的共性问题(负蝲均摊Q容错,数据复制Q动态扩容等{)Q在l合一些文件系l,DBQ缓存的自n特质。因此扎扎实实学好基Q了?/span>Http协议Q了解七层通信协议Q了解文件系l设计,了解MapReduce思\Q了解结构化Q半l构化(bigmapQ,非结构化存储的要点,׃不会让自p失在技术宣传中?/span>
明天晚上d京参加系l架构师会议Q到时候会和大家分享一?/span>TOP的一些商业和技术上的心得,准备得很仓促Q但是个得分享就在于自己自q道的说出来,旉不长Q?/span>45分钟Q能讲的也不多,但是如果对于淘宝开攑^台有兴趣的同学可以来听一下。这里也是做个q告Q不q不要期望过高,免得失望也大^_^。五q没有来北京了,首都应该也变化不了?/span>