侯æ·çš„Design Patterns培è®æ‚æ„Ÿ
应该是公å¸èŠ±äº†ä¸å°‘钱请æ¥çš„,虽然æ®ä»–说他和趋势一直ä¿æŒç€è‰¯å¥½çš„关系。
今天第一天,åŽé¢è¿˜æœ‰ä¸¤å¤©ï¼Œé¢˜ç›®å…³äºŽDesign Patterns。第一天总体感觉ä¸é”™ï¼Œjjhou确实是一个文å—的高手,也å¯èƒ½æ˜¯çœ‹å¾—多了,翻得多了,写得多了,讲得多了也就自然æˆäº†é«˜æ‰‹ã€‚旧的东西从新的人å£ä¸è®²å‡ºæ¥ï¼Œå¾€å¾€å¯ä»¥æœ‰æ›´å¤šçš„认识。
今天主è¦è®²çš„是一些比较简å•çš„OOæ¦‚å¿µå’Œå‡ ä¸ªç®€å•çš„模å¼ï¼Œè®²æ¨¡å¼ä»ŽTemplate Method开始,引出é‡ç”¨çš„基石:延迟实现;然åŽä»Žå…¶ä¸è¶³å¼•å‡ºStrategy,然åŽè§£é‡ŠOO当ä¸çš„delegation。这个门入的éžå¸¸cool。我们也在åšDesign Patterns的讨论ç,从Factory模å¼å¼€å§‹ï¼Œç»“æžœå‘现éžå¸¸éš¾äºŽå…¥é—¨â€”—ä¸å¤ªç†Ÿæ‚‰çš„人都在问:为什么我们è¦ç”¨Factoryæ¥åˆ›å»ºå¯¹è±¡ï¼Ÿä»Šå¤©å‘现,结构型模å¼ï¼Œå°¤å…¶æ˜¯Template Method确实是一个ä¸é”™çš„切入点。而且jjhou也说,Factory一定程度上也是由于Template Method产生的——当算法骨架当ä¸éœ€è¦åˆ›å»ºobject的时候。
然åŽæ˜¯Adapter。本æ¥æˆ‘一直认为Adapteréžå¸¸çš„简å•ï¼Œå› 而从æ¥æ²¡æœ‰æ·±å…¥çš„考虑过Adapter更深层的东西。今天jjhou的例åå´è®©æˆ‘打开了一个新看待Adapter的视角:STLçš„functor adapter(事åŽæŸ¥äº†ä¸€ä¸‹ã€ŠSTLæºç 剖æžã€‹ï¼Œå‘现其ä¸æœ‰è®²ï¼‰ã€‚其实interfaceä¸ä¸€å®šæ˜¯çº¯è™šåŸºç±»ï¼Œstd::unary_function也是一ç§interface,考虑template meta programming,当ä¸çš„typedef也是一ç§interfaceï¼cool。原æ¥adapterçœŸçš„æ— å¤„ä¸åœ¨ã€‚
åƒè¿‡æ™šé¥ä¸€ç›´åœ¨è®²Reference Countingï¼Œä¼ è¯´ä¸çš„æ¥è‡ªäºŽMore Effective C++。这本书在大二的时候æµè§ˆè¿‡ä¸€ç•ªï¼ŒåŽæ¥å°±å†ä¹Ÿæ²¡æœ‰é‡è¯»ï¼ˆé‚£ä¸ªæ—¶å€™è¿˜ä¸çŸ¥é“什么是Design Patterns)。现在回头å†åŽ»è¯»ä¸€ä¸‹ï¼Œå‘现确实有一些ä¸åŒçš„收获。一个Reference Countingçš„ä¸œè¥¿è®²äº†è¿™ä¹ˆä¹…æ˜¯å› ä¸ºä¾‹å。例å应该还是æ¥è‡ªäºŽä»–的《STLæºç 剖æžã€‹ï¼ŒæºäºŽSGI STL(å¤è€çš„用于写书的那个版本)当ä¸çš„string实现,ä¸é—´ç©¿æ’有copy on write。整个讲述的过程当ä¸æ€è·¯éžå¸¸å¥½ï¼Œå¦‚æžœæ€è·¯è·Ÿçš„上(其实以他讲的速度基本上都å¯ä»¥è·Ÿå¾—上),å¬èµ·æ¥çš„ç¡®æœ‰è¶£ï¼Œå’Œä»–çš„ä¹¦ä¸€ä¸ªé£Žæ ¼ï¼Œä»Žæ•…äº‹å¼€å¤´å¨“å¨“é“æ¥ï¼Œæ·±å…¥æµ…出。ä¸è¿‡æˆ‘一直在考虑这个东西用在string上é¢çš„æ„义。Reference Counting用在string上é¢çš„最大问题在于éžé€æ˜Žæ€§â€”—尤其对于é—留下æ¥çš„代ç çš„å¤ç”¨ï¼šè¯•æƒ³ä¸€ä¸ªç”¨C实现的程åºéœ€è¦ä¸€ä¸ªchar*æŒ‡é’ˆï¼Œå¦‚æžœè¿™ä¸ªæ—¶å€™ä¼ å…¥äº†ä¸€ä¸ªç”¨Reference Counting实现的string.c_str()得到的东西,那么å有八ä¹ä¼šå‡ºçŽ°é—®é¢˜ã€‚é—留下æ¥çš„C程åºå¹¶ä¸çŸ¥é“这个东西是ä¸æ˜¯è¢«share了,或者他的Reference Countingæ˜¯å¤šå°‘ã€‚æœ‰äººè¯´â€œä½ ä¸ç”¨c代ç ä¸å°±è¡Œäº†â€ï¼Œæ²¡é”™ï¼Œéžå¸¸å¥½ï¼Œä½†æ˜¯åœ¨å¤§åž‹é¡¹ç›®å½“ä¸å‡ 乎åšä¸åˆ°ï¼šå¤§åž‹é¡¹ç›®æœ‰å¾ˆå¤šé—留代ç å’Œæ— æ³•æŽ§åˆ¶çš„ç¬¬ä¸‰æ–¹åº“ï¼Œä½ å¯ä»¥åœ¨é‡å†™å’Œå¤ç”¨ä¹‹é—´æƒè¡¡ï¼Œä½†æ˜¯ä¸€æ—¦é€‰æ‹©äº†å¤ç”¨ï¼Œæƒ³è¦ä¸å‡ºé—®é¢˜ï¼Œæ¦‚率大概和å—京一整天ä¸å‡ºçŽ°è½¦ç¥¸çš„å‡ çŽ‡å·®ä¸å¤šï¼ˆå¤§æ¦‚<0.1%)。所以VC8çš„std::stringå·²ç»å½»åº•æŠ›å¼ƒæŽ‰äº†Reference Countingï¼Œå¤§æ¦‚ä¹Ÿå°±æ˜¯å› ä¸ºWindowså¹³å°ä¸Šå¦‚æ¤å¤šçš„é—留程åºå’Œè½¯ä»¶é€ æˆçš„。
但是stringçš„Reference Counting的问题ä¸è¶³ä»¥æŽ©ç›–Reference Counting的价值。但是一个好的Reference Counting的代ç 太难写了,尤其是è¦ä¿è¯çº¿ç¨‹å®‰å…¨çš„时候(比如CComObjectRootå’ŒCComMultiThreadedModel)。感觉还是éžä¾µå…¥å¼çš„Reference Counting比较安全一点,例如shared_ptr,这个应该明天会讲。
仔细想想为什么Reference Counting + Copy on Write这么难æžå®šï¼Œç›´æŽ¥åŽŸå› æ˜¯å› ä¸ºçŽ°å®žå’Œç†æƒ³ä¹‹é—´çš„å·®è·ï¼šå› 为cé£Žæ ¼çš„å—符串处ç†å‡½æ•°æ— 处ä¸åœ¨â€”—虽然guru们建议我们ä¸è¦ç”¨å®ƒä»¬ï¼Œä½†æ˜¯é‚£ä¹‹å‰çš„历å²æ›´é•¿ã€‚而cé£Žæ ¼çš„å—符串处ç†å‡½æ•°æœ‰ä¸€ä¸ªå‡è®¾ï¼Œå³å—符串的二进制布局:以å•å—节零结尾的连ç»å†…å˜ç©ºé—´ã€‚但是string没有这个å‡è®¾ã€‚至于这ç§å¯¹äºŽäºŒè¿›åˆ¶å¸ƒå±€çš„æ”¾å¼ƒï¼Œç¡®å®žå¢žåŠ äº†stringçš„çµæ´»æ€§ï¼Œä½†åŒæ—¶ä¹Ÿå¢žåŠ 了互æ“作性的难度。我感觉在现在的环境当ä¸æ¥çœ‹ï¼Œåœ¨C++程åºå‘˜å¯¹äºŽâ€œç”¨const引用替æ¢ä¼ 值调用â€å·²æˆä¸ºä¸€ç§æ€ç»´å®šåŠ¿ï¼Œå¹¶ä¸”编译器有了更强的优化能力的情况下,在string上é¢ä½¿ç”¨Reference Counting真的是弊大于利。Reference Counting解决的是å‡å°‘å¤åˆ¶string对象的内å˜åˆ†é…开销,而一旦使用了Reference Counting,为了ä¿æŒstring的行为,修改两个共享å˜å‚¨çš„string对象当ä¸çš„任何一个都必须使用Copy-on-Write。但是,当C++程åºå‘˜å¤åˆ¶ä¸€ä¸ªstring对象的时候,他的目的在ç»å¤§å¤šæ•°æ—¶å€™éƒ½æ˜¯ä¸ºäº†ä¿®æ”¹å®ƒï¼ˆæˆ‘相信对于大多数有ç»éªŒçš„C++程åºå‘˜æ¥è¯´ï¼Œè¿™ä¸ªå‘½é¢˜åŸºæœ¬æˆç«‹ï¼‰ï¼Œå¦‚果这个å‡è®¾æˆç«‹çš„è¯ï¼ŒReference Counting的作用其实并ä¸å¤ªå¤§ã€‚ä¸è¿‡ä»ç„¶å˜åœ¨ç€å…¶ä»–çš„å¯èƒ½æ€§ï¼Œä¾‹å¦‚作为类æˆå‘˜çš„string object。ä¸è¿‡æˆ‘认为这ç§ä¸œè¥¿ä¸åº”该会是性能的瓶颈:如果人们需è¦é¢‘ç¹çš„æ‹·è´ä¸€ä¸ªå…·æœ‰stringæˆå‘˜å˜é‡çš„类实例,这ç§è®¾è®¡å¾€å¾€å°±æœ‰é—®é¢˜ï¼Œæœ‰ç»éªŒçš„C++程åºå‘˜åº”该会é¿å…的。剩下的能够从stringçš„Reference Counting当ä¸å¾—利的,也就是很少的一部分case了。这ç§æ—¶å€™åŽ»å¯»æ‰¾ä¸€ä¸ªç”¨Reference Counting实现的专用版本的string,看起æ¥ä¼¼ä¹Žæ›´åŠ åˆç†ã€‚
在我看æ¥ï¼ŒC++ä»Žä¸€å¼€å§‹å°±æ”¾å¼ƒå¯¹äºŒè¿›åˆ¶å’Œçº¿ç¨‹æ¨¡åž‹çš„æ ‡å‡†åŒ–ä¹Ÿè®¸æ˜¯ä¸€ä¸ªé”™è¯¯ï¼ˆè™½ç„¶è¿™æ ·ç¡®å®žè®©C++å¯ä»¥åœ¨æ›´å¤šçš„å¹³å°ä¸Šå‘æŒ¥ä½œç”¨ï¼‰ã€‚å› ä¸ºæ²¡æœ‰äºŒè¿›åˆ¶å’Œçº¿ç¨‹æ¨¡åž‹ï¼ŒC++æ‰ä¸å¾—ä¸åœ¨ç¼–译期åšæ–‡ç« ,于是æ‰æœ‰äº†æ¨¡æ¿å…ƒç¼–程和很多的编译期优化手段。但是对于强调è¿è¡ŒæœŸçš„å¯é…制性的产å“,编译期的手段很难有用æ¦ä¹‹åœ°ã€‚è¿™ç§çŽ¯å¢ƒå½“ä¸ï¼Œæ›´åŠ 动æ€çš„,å¯ä»¥åœ¨è¿è¡ŒæœŸå˜åŒ–的方案更å—欢迎。这么æ¥çœ‹ï¼Œä»‹äºŽç¼–译型è¯è¨€å’Œè„šæœ¬è¯è¨€ä¹‹é—´çš„方案会很有å‰é€”,比如.NETçš„IL+JIT。