最早读这本《设计模式:可复用面向对象软件的基础》是在大学的时候。读了一些片段,看到了讲文本编辑器的滚动条装饰,觉得有点意思,可以用来做图形界面。
记得有一天晚上上床睡觉后,和两位同寝室室友聊天。一位室友LL说,他为了找工作,把设计模式这本书看了五六遍,把所有设计模式都记住了。另一位室友LHT说,这设计模式究竟有什么用?我说,感觉就是用来做图形界面用的。LHT说,对呢,看到书里面举的例子都是图形界面。LL说,不对,比如State模式就是可以用来做网络通信的状态控制。……后来LL又说,现在好像也不太流行用这个设计模式了。
之后就再也没有翻开过这本书了。直到今年春节才又从头读了一遍。
从书中举的“已知应用”来看,作者用于归类分析的程序,大多是图形界面程序,或者图形界面框架。
Smalltalk可能有同学听说过,是一个早期的面向对象语言,启发了C++,Java等后续的语言。ET++、InterViews我没听说过,问了下deepseek,说ET++ 是一个早期的面向对象应用程序框架,主要用于开发图形用户界面(GUI)应用程序。它由瑞士苏黎世联邦理工学院(ETH Zurich)的计算机科学系在1980年代末和1990年代初开发。InterViews 是一个早期的面向对象图形用户界面(GUI)工具包,主要用于开发交互式图形应用程序。它由斯坦福大学的计算机科学系在1980年代中期开发,后来在1980年代末和1990年代初得到了进一步的发展。
至于Unidraw,书中有介绍,说是一个图形编辑软件的框架。
所以说设计模式主要是用来做图形界面的,应该不算错。
不过23种设计模式中也有一些确实跟图形界面关系不太直接。比如Iterator(迭代器),Visitor(访问者)。Iterator我们知道是用来遍历集合用的,java里面很多啦。Visitor主要是用来遍历抽象语法树并进行处理,这本书部分内容需要懂一点编译原理才能看懂,比如这里涉及到抽象语法树的概念。
用设计模式写出来的代码对于不懂设计模式的人来说阅读比较困难,这可能是导致设计模式不如以前那么流行的原因。我听说Rust,Go语言甚至没有实现类的继承,这明显是反对设计模式的。设计模式大多都需要类的继承。C++、Java、C#语言中都有类继承。
读这本设计模式的书,一个基础的知识是类图的关联关系。
比如在上图中,Window类其实是定义了一个Rectangle对象,名为rectangle,这就用了一个直线连接这两个类来表示,有个箭头指向。意思是窗口中有一个矩形。
有时候一个类中不是定义的一个别的类的对象,而是定义的一个别的类的对象列表,这时在箭头上加一个点来表示。
比如在上图中,Picture里面有一个Graphic类的对象列表,名为graphics。意思是图片里面有很多图形。
之所以今年又想起来读这本书,是因为工作中遇到了一些大量用到设计模式的代码。具体来说就是USStudio的代码,我们公司开发的IVR流程图编辑工具。
早些时候,同事XF也常常给我说,让我去学点设计模式,比如太多if语句怎么优化之类的。这回也注意到了书中的相关内容,主要是Strategy(策略)这个模式。
最后给出书中对23种模式的总结表。
我也总结一下自己理解的模式的用途。
3.1 Abstract Factory(抽象工厂)
可以用来做不同的界面风格,抽象工厂定义返回控件的方法,不同的具体工厂返回不同风格的控件。
3.2 Builder(生成器)
可以用来做语法树的代码生成。
3.3 Factory Method(工厂方法)
其实就是子类方法重载。
3.4 Prototype(原型)
可以用来做各种图形编辑器的工具栏,每个工具带有一个原型,在图上添加的时候,就复制一个工具的原型到图上。
3.5 Singleton(单件)
就是单例,一个类只有一个对象实例。
4.1 Adapter(适配器)
可以用来封装别的平台的控件。比如WinFrom里面用GTK控件,做一个Adapter来封装。
4.2 Bridge(桥接)
可以用来做多平台界面支持。
4.3 Composite(组合)
树状结构的数据结构在面向对象中的体现。
4.4 Decorator(装饰)
可以用来做文档编辑的滚动条。
4.5 Facade(外观)
可以用来做dll的外部接口,或者jar包的外部接口。
4.6 Flyweight(享元)
文档编辑器中复用字符对象,节省内存。
4.7 Proxy(代理)
文档编辑器中,因为一个文档的图片不能一次全部显示,先用一个代理占一块空间,等滚动到图片的时候才显示出来。
5.1 Chain of Responsibility(职责链)
GUI事件向上冒泡。
5.2 Command(命令)
实现文档编辑中的撤销,重做操作。
5.3 Interpreter(解释器)
这个是用来解析语言用的。
5.4 Iterator(迭代器)
遍历集合。
5.5 Mediator(中介者)
把一组对象都放到一个中介者类里面,方便互相通信。界面上如果有一些控件互相有影响,可以用一个中介者来通信。
5.6 Memento(备忘录)
为实现图形编辑器撤销操作,记住之前的状态。
5.7 Observer(观察者)
MVC架构中,View就是Model的观察者,Model变化,会通知所有View改变。不过现在我们用SpringMVC只用到了Controller。另外java里面注册监听器(Listener)这种操作也是观察者模式。
5.8 State(状态)
图形编辑器中,选中一种工具,可以用这个模式来改变状态。
5.9 Strategy(策略)
封装一些可选的算法,减少if语句的使用。
5.10 Template Method(模板方法)
将算法的部分逻辑放到子类中。比如java的Collection.sort()方法,就是一个模板方法,compare逻辑放到了子类中。
5.11 Visitor(访问者)
遍历抽象语法树并进行处理。