C++必知必会(三) 设计模式

对于任何还不熟悉设计模式的人来说,在对这个领域进行简短的纵览之后,可能会留下这样的印象:设计模式是一个市场营销大骗局,它不过是一些简单的编程技术,或者不过是计算机科学家的玩物。尽管这些印象都有那么一点道理,然而设计模式的确是职业C++程序员工具箱中不可或缺的组件。

设计模式是一个被反复谈论的架构主题。它为特定上下文中的常见设计问题提供了解决方案,并描述了这种解决方案的结果。设计模式不仅仅是对技术的简单描述,它还是从现有的成功实践一点一滴汇集起来的设计智慧的具名封装,并以窬交流和复用的方式编写而成。模式关乎程序员之间的顺畅交流。

从实践的角度来看,设计模式具有两个重要的属性。首先,它们描述了经过验证的、成功的设计技术,这些技术可以按上下文相关的方式进行定制,以便满足新的设计场合的要求。其次,并且可能更重要的是,在提及某个特定的应用时,不仅包括其中用到的技术,还包括应用该模式的动因以及应用后所达到的效果。

这类事物并不是什么新东西。考虑一个来自算法领域的类比。考虑如下声明:“有一个未排序的序列,必须要进行很多次搜索。因此,希望对其进行快速排序,并且使用二分查找来执行每一个查找。”能够使用术语“快速排序”和“二分查找”,这种价值是不可估量的,不但在设计方面如此,在就该设计与受过教育的同事进行交流时也如此。当我说“快速排序”时,我的同事知道我正在排序的序列具有随机存取结构,并且它的排序时间复杂度的O(nlog2n),同时该序列中的元素可以采用类似小于操作符进行比较。当我说“二分查找”时,我的同事知道序列已经被排序过了,定位感兴趣的元素所执行的比较操作的时间复杂度为O(log2n),并且存在一个适当的操作来对序列中的元素进行比较。标准算法所具有的共享的知识以及标准词汇表,不但允许高效地记录文档,而且允许对设计方案进行有效的评议。比如说,如果我计划对一个单向链接表结构来执行这个查找和排序过程,我的同事立刻会自鸣得意地哈哈大笑,并指出在这种情况下我不能使用快速排序并且可能不希望使用二分查找。

在设计模式出现之前,在对面向对象设计的文档化、交流以及高效地评议方面,这些优点都不具备。我们被迫低水平地描述我们的设计,这种方式低效且不够精确。这并不是说用于复杂面向对象设计的技术尚不存在,而是这些技术尚未以一个共享的、通用术语的方式为整个编程社群所用。设计模式解决了这个问题,我们现在可以像描述算法设计一样高效、毫无歧义地描述面向对象设计。

举个例子,当我们看到Bridge模式被应用到某项设计中时,我们知道在一个简单的机制层面,抽象数据类型实现被分离成一个接口类和一个实现类。此外,我们知道这样做的原因是为了将接口从实现强有力地分离出来,这样,对实现的改变将不会影响到使用接口的用户。我们还知道这种分离会带来运行期开销,知道应该怎样对抽象数据类型的源代码进行布局,还知道许多其它细节。模式的名字是关于某项技术的诸多信息和经验的高效且无歧义的“句柄”,在设计和文档中小心并正确地使用模式和模式术语,可以使代码和设计更加明确。

那些严谨的模式专家有时以某种文献的形式来描述模式,这种描述遵循某种正式的结构。还有几种常见的变体也在使用,但不管哪种描述方式,均包含下面4个必不可少的部分:

首先,设计模式必须具有一个毫无歧义的名字。例如,术语“包装器(Wrapper)“对于设计模式命名来说就没有什么意义,因为它早已被广泛使用并且具有许多不同的含义。使用“Wrapper”这样的术语来命名某种设计模式只会带来混淆和误解。实际做法是:以前在"Wrapper"名下的设计技术指派为"Bridge" "Strategy" "Facade" "Object Adapter"以及其它一些模式名字。使用精确的模式名字比使用不那么精确的名字具有“明显”的优势,就像术语“二分查找”比“查找”更精确一样。

其次,模式描述必须定义该模式所能解决的问题。这种描述可以相对宽泛,也可以相对狭窄。

再次,模式描述要记述该问题的解决方案。根据陈述的问题,该解决方案可以相对高级,也可以相对低级,但无论如何,它应该具有足够的通用性,以便可以根据问题可能出现的不同上下文进行定制。

最后,模式描述要记述将该模式应用于某个上下文的后果。在应用该模式后,该上下文是如何发生改变的?不管是变好,还是变坏。

拥有模式的知识可以使一名糟糕的设计师摇身一变成为一名优秀的设计师吗?呃,是给出另一个类比的时候了,设想你被迫学习某一门让人痛苦的数学课,它的期末考试内容是证明某个领域中的许多定理。如果才能从这门课中死里逃生呢?当然,最显而易见的方式是成为一个天才。它从最初的原理开始,进而研究整个数学分支的基础知识,最终证明那些定理。一个更为实际的途径是,你牢记并消化该数学领域中的大量定理,并使用它所具备的任何天赋的数学能力、灵感以及好运去选择适当的辅助定理,然后以某种逻辑“胶水”将它们粘合在一起,从而最终证明新的定理。是的,甚至对于那些“传送中的天才”来说,这种方式都是很有优势的,因为基于现成的定理来证明会更高效,同“凡夫俗子”交流起来也更容易。当然,熟悉辅助定理并不能保证一个可怜的学数学的学生通过考试,但这类知识至少可以使其能够理解别人给出的证明。

同样的道理,从最初的原理进而到复杂的面向对象设计也是颇为无趣的,而且与他人交流最终设计也很困难。组合使用各种设计模式来生成面向对象设计,类似于在数学中使用辅助定理来证明一个新的定理。设计模式常常被描述为“微架构(Micro-architecture)“,它们可以与其它模式进行组合从而生成一个新的架构。当然,选择适当的模式并有效地对其进行组合,也是需要设计方面的专家经验和天资禀赋的。不过,一旦设计完成后,甚至你的经理都能够理解完整的设计方案,只要他具备一些必需的模式方面的知识即可。

时间: 2024-08-05 09:02:14

C++必知必会(三) 设计模式的相关文章

JavaScript必知必会(三) String .的方法来自何方_javascript技巧

String 我们知道javascript 包括:number,string,boolean,null,undefined 基本类型和Object 类型. 在我的认知中,方法属性应该是对象才可以具有的. var str="hello,world"; var s=str.subString(,);//ell alert(typeof(str)+":"+typeof(s));//string:string 从上面的返回类型来看,str是string 类型的. 再看下面的

MYSQL必知必会读书笔记第三章之显示数据库_Mysql

MySQL是一种开放源代码的关系型数据库管理系统(RDBMS),MySQL数据库系统使用最常用的数据库管理语言--结构化查询语言(SQL)进行数据库管理. show column from tablename: 对每一个字段返回一行,行中包含字段名,数据类型.是否允许NULL.键信息.默认值以及其他信息. describe 语句: MySQL支持使用describ作为show columns from 的一种快捷方式.describ tablename 所支持的其他的show语句: show s

Python 程序员必知必会的开发者工具

Python已经演化出了一个广泛的生态系统,该生态系统能够让Python程序员的生活变得更加简单,减少他们重复造轮的工作.同样的理念也适用于工具开发者的工作,即便他们开发出的工具并没有出现在最终的程序中.本文将介绍Python程序员必知必会的开发者工具. 对于开发者来说,最实用的帮助莫过于帮助他们编写代码文档了.pydoc模块可以根据源代码中的docstrings为任何可导入模块生成格式良好的文档.Python包含了两个测试框架来自动测试代码以及验证代码的正确性:1)doctest模块,该模块可

Visual Studio 使用及调试必知必会

原文:Visual Studio 使用及调试必知必会   一:C# CODING 技巧 1:TODO 然后 CTRL + W + T,打开任务列表,选中 Comments,就会显示所有待做的任务 2:打开所在的文件夹 右键单击任何一个文件选项卡, 选择"打开所在的文件夹",或在 Solution Explorer 的文件上面点右键: 3:比对同一个文件 鼠标向下拖动红框内的图标. 4:按意愿编程 我把它定义为:按意愿编程,即,在写代码过程中,如果觉得需要使用到一个新类,可以先不用创建这

Android必知必会-使用Intent打开第三方应用及验证可用性

本文讲的是Android必知必会-使用Intent打开第三方应用及验证可用性,一个普通的应用默认会有一个入口 Activity,它在 AndroidManifest.xml 中一般这样写: <application>      <activity android:name=".MainActivity" >          <intent-filter>              <action android:name="andr

JavaScript必知必会(九)function 说起 闭包问题_javascript技巧

function 函数格式 function getPrototyNames(o,/*optional*/ a) { a = a || []; for(var p in o) { a.push(p); } return a; } caller func.caller 返回函数调用者 function callfunc() { if(callfunc.caller) { alert(callfunc.caller.toString()); }else { alert("没有函数调用");

【web必知必会】—— DOM:四个常用的方法

终于开始复习DOM的知识了,这一阵忙乎论文,基本都没好好看技术的书. 记得去年实习的时候,才开始真正的接触前端,发现原来JS可以使用的如此灵活. 说起DOM就不得不提起javascript的组成了,javascript是由三部分组成的: 1 ECMAScript 2 BOM 3 DOM 最开始,网页是由HTML这种静态的标签语言组成的,后来为了丰富网页,引入了Script脚本语言. 但由于浏览器厂商太多,每个厂商都使用自己的语言,导致script的语言种类繁多,最终由Netscape和sun对S

《Oracle PL/SQL必知必会》——第2章 初识Oracle和PL/SQL 2.1 什么是Oracle

第2章 初识Oracle和PL/SQL Oracle PL/SQL必知必会 在本章中,你将认识Oracle和PL/SQL是什么,以及你可以使用什么工具来操作它们. 2.1 什么是Oracle 在前一章中,你学习了数据库和SQL.如所解释的那样,做所有工作(存储.检索.管理和操作数据)的实际上是数据库软件(DBMS或数据库管理系统[Database Management System]).Oracle DBMS(或者简称为Oracle)就是一个DBMS:也就是说,它是数据库软件. Oracle已经

《Oracle PL/SQL必知必会》导读

前言 Oracle PL/SQL必知必会 Oracle Database(或Oracle RDBMS)是如此流行并且获得了广泛的认可,以至于大多数用户将其简称为"Oracle"(忽略了Oracle公司制作其他软件甚至硬件的事实).Oracle Database(我将像大多数人那样将其简称为"Oracle",以使事情变得简单)从20世纪70年代起就出现了,成为最早的数据库管理系统之一.Oracle是世界上最常用的数据库管理系统(Database Management

【web必知必会】——图解HTTP(上)

原文:[web必知必会]--图解HTTP(上) 本篇总结关于http的相关知识,主要内容参考如下导图: 主要讲解的内容有: 1 URL与URI的区别. 2 请求报文与相应报文的内容. 3 GET与POST的区别. 4 http的cookie.持久化.管道化.多部分对象集合.范围请求等 后续会更新http其他的相关知识. 关键词概念 平时会经常接触到URL,他就是我们访问web的一个字符串地址,那么URI是什么呢?他们是什么关系呢? 先看看官方的解释: URL:uniform resource l