软件设计模式

软件工程中,软件设计模式是一种通用的,可重复使用的解决方案,以解决软件设计中给定上下文中常见问题。它不是可以直接转换为源代码机器代码的完成设计。相反,它是如何解决在许多不同情况下可以使用的问题的描述或模板。设计模式是正式的最佳实践,在设计应用程序或系统时,程序员可以用来解决常见问题。

面向对象的设计模式通常显示对象之间的关系和交互,而无需指定最终的应用程序类或所涉及的对象。暗示可变状态的模式可能不适合功能编程语言。某些模式可以在具有内置支持的语言中渲染,这些语言可以解决他们试图解决的问题,而面向对象的模式不一定适合于非对象的语言。

设计模式可以被视为一种结构化方法,用于在编程范式和混凝土算法的级别之间进行中间的计算机编程。

历史

在1977年,克里斯托弗·亚历山大( Christopher Alexander)起源于1977年的建筑概念(CF“街道模式”,《 AIP杂志》,1966年9月,第32卷,第5期,第5期,第273- 278页)。 1987年,肯特·贝克(Kent Beck)沃德·坎宁安(Ward Cunningham)开始尝试将模式应用于编程(特别是图案语言)的想法,并在当年的OOPSLA会议上介绍了他们的结果。在接下来的几年中,贝克,坎宁安和其他人跟进了这项工作。

在书籍设计模式之后,设计模式在计算机科学中广受欢迎:可重复使用的对象软件的元素于1994年由所谓的“四个帮派”(Gamma et al。)出版,该软件经常被缩写为“ GOF”。同年,举行了编程会议的第一种模式语言,第二年,波特兰模式存储库设立了用于设计模式的文档。该术语的范围仍然是争议的问题。设计模式类型中的著名书籍包括:

  • 伽玛,埃里希;赫尔姆,理查德;约翰逊,拉尔夫; Vlissides,John(1994)。设计模式:可重复使用的面向对象软件的元素。 Addison-Wesley。 ISBN 978-0-201-63361-0。
  • Brinch Hansen,Per(1995)。计算科学研究:并行编程范例。 Prentice Hall。 ISBN 978-0-13-439324-7。
  • Buschmann,弗兰克; Meunier,Regine;罗恩特,汉斯; Sommerlad,Peter(1996)。面向模式的软件体系结构,第1卷:模式系统。约翰·威利(John Wiley&Sons)。 ISBN 978-0-471-95869-7。
  • 贝克,肯特(1997)。 SmallTalk最佳实践模式。 Prentice Hall。 ISBN 978-0134769042。
  • 施密特,道格拉斯C。斯塔尔,迈克尔;罗恩特,汉斯; Buschmann,Frank(2000)。面向模式的软件体系结构,第2卷:并发和网络对象的模式。约翰·威利(John Wiley&Sons)。 ISBN 978-0-471-60695-6。
  • 福勒,马丁(2002)。企业应用程序体系结构的模式。 Addison-Wesley。 ISBN 978-0-321-12742-6。
  • Hohpe,Gregor; Woolf,Bobby(2003)。企业集成模式:设计,构建和部署消息传递解决方案。 Addison-Wesley。 ISBN 978-0-321-20068-6。
  • 弗里曼,埃里克·T。罗布森,伊丽莎白;贝茨,伯特;塞拉,凯西(2004)。头部设计模式。 O'Reilly Media。 ISBN 978-0-596-00712-6。
  • Larman,Craig(2004)。应用UML和模式(第三版,第1版,1995年)。皮尔逊。 ISBN 978-0131489066。

尽管设计模式实际上已经使用了很长时间了,但设计模式概念的形式化了几年。

实践

设计模式可以通过提供经过测试的,经过验证的开发范例来加快开发过程。有效的软件设计需要考虑到实施后期可能才能看到的问题。新鲜书面的代码通常可能会遇到隐藏的微妙问题,这些问题需要时间需要检测到,这些问题有时会导致主要问题。重复使用设计模式有助于防止这种微妙的问题,并且还改善了熟悉模式的编码人员和建筑师的代码可读性。

为了实现灵活性,设计模式通常会引入其他级别的间接水平,在某些情况下,这可能会使最终的设计变得复杂并损害了应用程序性能。

根据定义,必须将模式重新编程到使用它的每个应用程序中。由于一些作者将其视为组件提供的软件重复使用的倒退,因此研究人员努力将模式变成组件。 Meyer和Arnout能够提供他们尝试的三分之二模式的完整或部分组件。

软件设计技术很难应用于更广泛的问题。设计模式提供了通用解决方案,该解决方案的格式不需要与特定问题相关的具体细节。

结构

设计模式由几个部分组成(请参见下面的§文档)。特别有趣的是结构,参与者和协作部分。这些部分描述了一个设计主题:一个典型的微观架构,开发人员复制并适应其特定设计,以解决设计模式描述的经常性问题。微构造是一组程序成分(例如,类,方法...)及其关系。开发人员通过在其设计中引入该原型微观架构来使用设计模式,这意味着其设计中的微构造将具有类似于所选设计主题的结构和组织。

特定于域的模式

还努力将设计模式编纂为特定领域,包括使用现有设计模式以及特定领域的设计模式。示例包括用户界面设计模式,信息可视化,安全设计,“安全可用性”,网页设计和业务模型设计。

编程会议记录的年度模式语言包括许多特定领域模式的示例。

分类和列表

设计模式最初是根据他们解决的哪种问题分为3个子分类的。创建模式提供了根据所需标准和受控方式创建对象的能力。结构模式是关于组织不同的类和对像以形成更大的结构并提供新功能。最后,行为模式是关于识别对象之间的共同通信模式并实现这些模式。

创建模式

姓名描述设计模式代码中完成其他
抽象工厂提供一个界面,用于创建相关对象的家庭,而无需指定其具体类别。是的是的
建筑商将复杂对象的构造与其表示形式分开,从而允许相同的施工过程创建各种表示。是的
依赖注入一个类接受从喷油器那里需要的对象,而不是直接创建对象。
工厂方法定义用于创建单个对象的接口,但让子类决定要实例化的类。工厂方法使课堂延迟实例化为子类。是的是的
懒惰的初始化延迟对象的创建,值的计算或其他昂贵的过程的策略,直到第一次需要。该模式出现在GOF目录中,作为“虚拟代理”,这是代理模式的实现策略。Poeaa
Multiton确保课程仅具有命名实例,并提供与它们的全球访问点。
对像池通过回收不再使用的对象,避免昂贵的获取和释放资源。可以认为是连接池线程池模式的概括。
原型指定使用原型实例创建的对象的种类,并从现有对象的“骨架”中创建新对象,从而提高性能并使内存足迹最小化。是的
资源获取是初始化(RAII)通过将资源绑在合适物体的寿命上,确保资源可以正确释放。
辛格尔顿确保课堂只有一个实例,并提供全球访问点。是的是的

结构模式

姓名描述设计模式代码中完成其他
适配器,包装纸或翻译人员将类的接口转换为另一个接口客户端的期望。适配器可以让课堂一起工作,而这些插入无法兼容。企业集成模式当量是翻译器。是的是的
将其实施的抽象解脱出来,使两者独立变化。是的是的
合成的将对象组合到树结构中以表示部分整体层次结构。综合允许客户统一处理对象的单个对象和组成。是的是的
装饰师将其他职责附加到动态保持相同接口的对像上。装饰器为扩展功能的子类提供了灵活的替代方案。是的是的
代表团通过组合而不是子分类扩展类。该对象通过将委派给第二个对象(委托)来处理请求
扩展对象在不更改层次结构的情况下将功能添加到层次结构。敏捷软件开发,原理,模式和实践
正面向子系统中的一组接口提供统一的接口。立面定义了一个高级接口,使子系统更易于使用。是的是的
轻量级使用共享来有效地支持大量类似对象。是的
前控制器该模式与Web应用程序的设计有关。它为处理请求提供了集中式切入点。

J2EE模式POEAA

标记空界面将元数据与类关联。有效的Java
模块将几个相关元素分组为类,单例,方法,全球使用,分为一个概念实体。
代理人为另一个对象提供对其访问权限的替代或占位符。是的
双胞胎双胞胎允许在不支持此功能的编程语言中对多种继承进行建模。

行为模式

姓名描述设计模式代码中完成其他
黑板用于结合不同数据源的人工智能模式(请参阅黑板系统
责任链避免将请求的发件人耦合到其接收器,从而给多个对像一个处理请求的机会。炼炼接收对象并沿链条传递请求,直到对象处理。是的
命令将请求封装为对象,从而允许使用不同请求的客户端进行参数化,以及请求的排队或记录。它还允许支持无法使用的操作。是的
流利的界面设计一个用于链接的API,以便它像DSL一样读写。每个方法调用都会返回一个上下文,下一个逻辑方法可以通过该上下文。
口译员给定语言,为语法定义表示形式以及使用表示形式来解释语言句子的解释器。是的
迭代器提供一种方法来依次访问聚合对象的元素,而无需公开其基础表示。是的是的
调解人定义一个封装一组对象交互的对象。调解员通过防止对像明确指向对象来促进松散的耦合,并允许它们的相互作用独立变化。是的
纪念不违反封装,捕获和外部化对象的内部状态,允许稍后将对象恢复到该状态。是的
空对象通过提供默认对象来避免null引用。
观察者发布/订阅定义对象之间的一对多依赖关系,其中一个对像中的状态变化会导致其所有因素被自动通知和更新。是的是的
仆人定义一组类的共同功能。对于给定的一组类,仆人模式也经常称为“助手类”或“公用事业类实现”。辅助类通常没有对象,因此它们具有所有静态方法,它们作用于不同类型的类对象。
规格布尔方式重组的商业逻辑
状态当对象发生内部状态时,允许对象改变其行为。该对像似乎会改变其类。是的
战略定义一个算法家庭,封装每种算法,并使它们可以互换。策略使该算法与使用它的客户的独立性不同。是的是的
模板方法在操作中定义算法的骨骼,将一些步骤推迟到子类。模板方法让子类重新定义算法的某些步骤,而无需更改算法的结构。是的是的
游客表示要在一组类的实例上执行的操作。访问者可以在不更改其操作的元素的类别的情况下定义新操作。是的

并发模式

姓名描述posa2其他
活动对象将方法与存在于其自己的控制线程中的方法调用中执行。目的是通过使用异步方法调用和用于处理请求的调度程序引入并发。是的
balking仅当对象处于特定状态时,仅在对像上执行操作。
结合特性组合多个观察者以迫使不同对像中的属性以某种方式同步或协调。
计算内核同一计算在同一计算中并联,与非分支指针数学用于共享数组的整数参数不同,例如GPU优化的矩阵乘法卷积神经网络
双检查锁定首先以不安全的方式测试锁定标准(“锁提示”),以减少获得锁的开销;只有在成功的情况下,实际锁定逻辑才能继续。

当以某些语言/硬件组合实现时,可能是不安全的。因此,有时可以将其视为反诉图案

是的
基于事件的异步解决了多线程程序中出现的异步模式的问题。
警惕的悬架管理需要获得锁定的操作,并在执行操作之前要满足前提条件。
加入Join-Pattern提供了一种通过消息传递编写并发,并行和分布式程序的方法。与线程和锁的使用相比,这是一个高级编程模型。
一个线程将“锁定”放在资源上,以防止其他线程访问或修改它。Poeaa
消息设计模式(MDP)允许组件和应用程序之间的信息互换(IE消息)。
监视对象一种方法被相互排除的对象,从而阻止多个对象错误地尝试同时使用它。是的
反应堆反应堆对象为必须同步处理的资源提供异步接口。是的
读写锁允许同时读取对对象的访问,但需要独家访问写操作。可以使用基础信号量来写作,并且可能使用或可能不会使用复制机制。
调度程序明确控制线程何时可以执行单线程代码。
服务处理程序模式对于每个请求,服务器都会产生专用的客户处理程序来处理请求。也称为螺纹
线程池创建了许多线程来执行许多任务,这些任务通常在队列中组织。通常,比线程的任务要多。可以认为是对像池模式的特殊情况。
特定于线程的存储线程本地静态或“全局”内存。是的
安全并发与独家所有权避免需要运行时并发机制,因为可以证明独家所有权。这是Rust语言的显著功能,但是编译时间检查不是唯一的手段,程序员通常会在代码中手动将此类模式手动设计为代码- 省略锁定机制的使用,因为程序员评估给定变量永远不会发生同时访问。
CPU原子操作X86和其他CPU体系结构支持一系列原子指令,以保证修改和访问原始值(整数)的内存安全性。例如,两个线程都可以安全地增加一个计数器。这些功能也可以用于实施其他并发模式的机制。 C#语言使用互锁的类来实现这些功能。

文件

设计模式的文档描述了使用模式的上下文,模式寻求解决的上下文中的力以及建议的解决方案。没有用于记录设计模式的单一标准格式。相反,不同的模式作者已经使用了各种不同的格式。但是,根据马丁·福勒(Martin Fowler)的说法,某些模式形式已经比其他模式更为知名,因此成为新的模式写作工作的共同起点。常用文档格式的一个例子是Erich GammaRichard HelmRalph JohnsonJohn Vlissides在其书籍设计模式中使用的一个例子。它包含以下各节:

  • 模式名称和分类:一种描述性和唯一名称,有助于识别和参考模式。
  • 意图:描述模式背后的目标及其使用原因。
  • 也称为:图案的其他名称。
  • 动机(力):由问题和可以使用这种模式的环境组成的场景。
  • 适用性:这种模式可用的情况;模式的上下文。
  • 结构:模式的图形表示。类图互动图可用于此目的。
  • 参与者:在设计中使用的类和对象的列表及其在设计中的角色。
  • 协作:描述模式中使用的类和对像如何相互交互的描述。
  • 后果:对使用模式引起的结果,副作用和贸易折扣的描述。
  • 实施:对模式实现的描述;图案的解决方案部分。
  • 示例代码:如何用编程语言使用该模式。
  • 已知用途:模式的真实用法示例。
  • 相关模式:与模式有一定关系的其他模式;讨论模式和类似模式之间的差异。

批评

已经观察到,设计模式可能只是一个迹象表明某些功能在给定的编程语言(例如JavaC ++ )中缺少。彼得·诺维格(Peter Norvig)证明,在设计模式书中的23个模式中,有16本(主要集中在C ++上)被简化或消除了LISPDylan中的直接语言支持(通过直接语言支持)。相关观察是由汉纳曼(Hannemann)和基萨莱斯(Kiczales)提出的,他们使用面向方面的编程语言(FactiveJ)实施了23种设计模式中的几个,并表明代码级的依赖性是从23种设计模式中的17种的实现中删除的,并且该方面是面向方面的。编程可以简化设计模式的实现。另请参见保罗·格雷厄姆(Paul Graham)的文章《书呆子的复仇》。

不当使用模式可能会不必要地提高复杂性。

也可以看看