设计模式(Design Pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结,使用设计模式是为了可重用代码、让代码更容易被他人理解并且保证代码可靠性。
虽然GoF设计模式只有23个,但是它们各具特色,每个模式都为某一个可重复的设计问题提供了一套解决方案。根据它们的用途,设计模式可分为创建型(Creational),结构型(Structural)和行为型(Behavioral)三种,其中创建型模式主要用于描述如何创建对象,结构型模式主要用于描述如何实现类或对象的组合,行为型模式主要用于描述类或对象怎样交互以及怎样分配职责,在GoF 23种设计模式中包含5种创建型设计模式、7种结构型设计模式和11种行为型设计模式。此外,根据某个模式主要是用于处理类之间的关系还是对象之间的关系,设计模式还可以分为类模式和对象模式。我们经常将两种分类方式结合使用,如单例模式是对象创建型模式,模板方法模式是类行为型模式。
值得一提的是,有一个设计模式虽然不属于GoF 23种设计模式,但一般在介绍设计模式时都会对它进行说明,它就是简单工厂模式,也许是太“简单”了,GoF并没有把它写到那本经典著作中,不过现在大部分的设计模式书籍都会对它进行专门的介绍。
表1 常用设计模式一览表
类型 | 模式名称 | 学习难度 | 使用频率 |
创建型模式 Creational Pattern | Singleton Pattern | ★☆☆☆☆ | ★★★★☆ |
Simple Factory Pattern | ★★☆☆☆ | ★★★☆☆ | |
Factory Method Pattern | ★★☆☆☆ | ★★★★★ | |
Abstract Factory Pattern | ★★★★☆ | ★★★★★ | |
Prototype Pattern | ★★★☆☆ | ★★★☆☆ | |
Builder Pattern | ★★★★☆ | ★★☆☆☆ | |
结构型模式 Structural Pattern | Adapter Pattern | ★★☆☆☆ | ★★★★☆ |
Bridge Pattern | ★★★☆☆ | ★★★☆☆ | |
Composite Pattern | ★★★☆☆ | ★★★★☆ | |
Decorator Pattern | ★★★☆☆ | ★★★☆☆ | |
Facade Pattern | ★☆☆☆☆ | ★★★★★ | |
Flyweight Pattern | ★★★★☆ | ★☆☆☆☆ | |
Proxy Pattern | ★★★☆☆ | ★★★★☆ | |
行为型模式 Behavioral Pattern | 职责链模式 Chain of Responsibility Pattern | ★★★☆☆ | ★★☆☆☆ |
命令模式 Command Pattern | ★★★☆☆ | ★★★★☆ | |
解释器模式 Interpreter Pattern | ★★★★★ | ★☆☆☆☆ | |
迭代器模式 Iterator Pattern | ★★★☆☆ | ★★★★★ | |
中介者模式 Mediator Pattern | ★★★☆☆ | ★★☆☆☆ | |
备忘录模式 Memento Pattern | ★★☆☆☆ | ★★☆☆☆ | |
观察者模式 Observer Pattern | ★★★☆☆ | ★★★★★ | |
状态模式 State Pattern | ★★★☆☆ | ★★★☆☆ | |
Strategy Pattern | ★☆☆☆☆ | ★★★★☆ | |
Template Method Pattern | ★★☆☆☆ | ★★★☆☆ | |
访问者模式 Visitor Pattern | ★★★★☆ | ★☆☆☆☆ |
1.3 设计模式有什么用
下面我们来回答最后一个问题:设计模式到底有什么用?简单来说,设计模式至少有如下几个用途:
(1) 设计模式来源众多专家的经验和智慧,它们是从许多优秀的软件系统中总结出的成功的、能够实现可维护性复用的设计方案,使用这些方案将可以让我们避免做一些重复性的工作,也许我们冥思苦想得到的一个“自以为很了不起”的设计方案其实就是某一个设计模式。在时间就是金钱的今天,设计模式无疑会为有助于我们提高开发和设计效率,但它不保证一定会提高,。
(2) 设计模式提供了一套通用的设计词汇和一种通用的形式来方便开发人员之间沟通和交流,使得设计方案更加通俗易懂。交流通常很耗时,任何有助于提高交流效率的东西都可以为我们节省不少时间。无论你使用哪种编程语言,做什么类型的项目,甚至你处于一个国际化的开发团队,当面对同一个设计模式时,你和别人的理解并无二异,因为设计模式是跨语言、跨平台、跨应用、跨国界的,。
(3) 大部分设计模式都兼顾了系统的可重用性和可扩展性,这使得我们可以更好地重用一些已有的设计方案、功能模块甚至一个完整的软件系统,避免我们经常做一些重复的设计、编写一些重复的代码。此外,随着软件规模的日益增大,软件寿命的日益变长,系统的可维护性和可扩展性也越来越重要,许多设计模式将有助于提高系统的灵活性和可扩展性,让我们在不修改或者少修改现有系统的基础上增加、删除或者替换功能模块。如果一点设计模式都不懂,我想要做到这一点恐怕还是很困难的,。
(4) 合理使用设计模式并对设计模式的使用情况进行文档化,将有助于别人更快地理解系统。如果某一天因为升职或跳槽等原因,别人接手了你的项目,只要他也懂设计模式,我想他应该能够很快理解你的设计思路和实现方案,让你升职无后患之忧,跳槽也心安理得,何乐而不为呢?。
(5) 最后一点对初学者很重要,学习设计模式将有助于初学者更加深入地理解面向对象思想,让你知道:如何将代码分散在几个不同的类中?为什么要有“接口”?何谓针对抽象编程?何时不应该使用继承?如果不修改源代码增加新功能?同时还让你能够更好地阅读和理解现有类库(如JDK)与其他系统中的源代码,让你早点脱离面向对象编程的“菜鸟期”,。
1.4 个人观点
作为设计模式的忠实粉丝和推广人员,在正式学习设计模式之前,分享几点个人的看法,以作参考:
(1) 掌握设计模式并不是件很难的事情,关键在于多思考,多实践,不要听到人家说懂几个设计模式就很“牛”,只要用心学习,设计模式也就那么回事,你也可以很“牛”的,一定要有信心。
(2) 在学习每一个设计模式时至少应该掌握如下几点:这个设计模式的意图是什么,它要解决一个什么问题,什么时候可以使用它;它是如何解决的,掌握它的结构图,记住它的关键代码;能够想到至少两个它的应用实例,一个生活中的,一个软件中的;这个模式的优缺点是什么,在使用时要注意什么。当你能够回答上述所有问题时,恭喜你,你了解一个设计模式了,至于掌握它,那就在开发中去使用吧,用多了你自然就掌握了。
(3) “如果想体验一下运用模式的感觉,那么最好的方法就是运用它们”。正如在本章最开始所说的,设计模式是“内功心法”,它还是要与“实战招式”相结合才能够相得益彰。学习设计模式的目的在于应用,如果不懂如何使用一个设计模式,而只是学过,能够说出它的用途,绘制它的结构,充其量也只能说你了解这个模式,严格一点说:不会在开发中灵活运用一个模式基本上等于没学。所以一定要做到:少说多做。
(4) 千万不要滥用模式,不要试图在一个系统中用上所有的模式,也许有这样的系统,但至少目前我没有碰到过。每个模式都有自己的适用场景,不能为了使用模式而使用模式?【怎么理解,大家自己思考,】,滥用模式不如不用模式,因为滥用的结果得不到“艺术品”一样的软件,很有可能是一堆垃圾代码。
(5) 如果将设计模式比喻成“三十六计”,那么每一个模式都是一种计策,它为解决某一类问题而诞生,不管这个设计模式的难度如何,使用频率高不高,我建议大家都应该好好学学,多学一个模式也就意味着你多了“一计”,说不定什么时候一不小心就用上了,。因此,模式学习之路上要不怕困难,勇于挑战,有的模式虽然难一点,但反复琢磨,反复研读,应该还是能够征服的。
(6) 设计模式的“上乘”境界:“手中无模式,心中有模式”。模式使用的最高境界是你已经不知道具体某个设计模式的定义和结构了,但你会灵活自如地选择一种设计方案【其实就是某个设计模式】来解决某个问题,设计模式已经成为你开发技能的一部分,能够手到擒来,“内功”与“招式”已浑然一体,要达到这个境界并不是看完某本书或者开发一两个项目就能够实现的,它需要不断沉淀与积累,所以,对模式的学习不要急于求成。
(7) 最后一点来自GoF已故成员、我个人最尊敬和崇拜的软件工程大师之一John Vlissides的著作《设计模式沉思录》(Pattern Hatching Design Patterns Applied):模式从不保证任何东西,它不能保证你一定能够做出可复用的软件,提高你的生产率,更不能保证世界和平,。模式并不能替代人来完成软件系统的创造,它们只不过会给那些缺乏经验但却具备才能和创造力的人带来希望。