1. 命令者模式
它包五个角色:
- 客户端(Client):发出命令;
- 调用者(Invoker):调用抽象命令,还可以记录执行的命令;
- 接受者(Receiver):命令的实际执行者,一个命令会存在一个或多个接收者;
- 抽象命令(Command):定义命令执行方法;
- 具体命令(Concrete Command):调用接收者,执行命令的具体方法。
命令者模式被大量运用在组件化的图形界面系统、撤销功能、线城市、事务和向导中。我们来看一个例子,我们实现一个将一系列命令录制下来的功能,有点类似于 Word 中的撤销功能那样记录每一步的操作。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 1
- 2
- 3
- 4
- 5
以上是一个完整的命令者模式的例子,我们使用 Lambda 表达式来修改客户端:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
我们使用引用方法来修改客户端:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
通过这样的改造,我们的代码意图更加明显了呢,一看就明白具体记录的是哪个操作。
2. 策略模式
常见的策略模式就是文件压缩软件,通常一个压缩软件可以支持多种压缩算法如 zip 、gzip、rar 等,通过策略模式可以让压缩软件根据我们具体的操作来实现不同的压缩算法。我们来看一个压缩数据的策略模式的例子:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 1
- 2
- 3
- 4
- 5
以上就是一个完整的 zip 和 gzip 的压缩策略。现在我们用 Lambda 表达式来优化初始化压缩策略
- 1
- 2
- 3
- 4
- 5
3. 观察者模式
观察者模式被适用于消息通知、触发器之类的应用场景中
观察者模式包含三个类 主题(Subject)、观察者(Observer)和客户端(Client)。Subject 对象带有绑定观察者到 Client 对象和从 Client 对象解绑观察者的方法。
我们来看一个例子:现在我们用观察者模式实现根据输入的数字,自动将输入的数字其转变成对应十六进制和二进制。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
同样我们使用 Lambda 表达式来修改 Demo
类:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
在这个例子中,我们实际上是省去了 BinaryObserver
和 HexObserver
两个类的定义,直接使用 Lambda 表达式来描述二进制和十六进制转化的逻辑。
4. 模板方法模式
通常对于一些重要的复杂方法和多个子类共有的方法且逻辑相同的情况下会使用模板方法模式。比如用户第三方用户认证的时候就比较适合使用模板方法。
我们来看一个例子:假设我们现在需要用到微信、微博的第三方用户授权来获取用户的信息。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 1
- 2
- 3
- 4
- 5
- 6
现在我们使用 Lambda 表达式换个角度来思考模板方法模式。如果我们用函数式接口来组织模板方法中的调用过程,相比使用继承来构建要显得灵活的多。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 1
- 2
- 3
- 4
- 5
- 6
此时,我们的模板方法得到了大幅的简化,同时通过函数接口让模板方法获得了极大的灵活性。
5. 小结
本节我们讨论如何使用 Lambda 表达式让我们的设计模式变得更简单、更好用。这里我们使用了四个例子从不同的角度来。
- 命令者模式:我们使用 Lamabda 表达式的方法引用来进行改造;
- 策略模式:我们使用了 Lambda 表达式的构造器引用来进行改造;
- 观察者模式:我们使用了标准的 Lambda 表达式来进行改造;
- 模板方法模式:我们使用了函数式接口来进行改造。
目的是希望给大家一点启发,在平常的编码过程中去思考如何使用 Lambda 表达式来设计我们的程序。对于其他的设计模式如果感兴趣的话可以自己尝试下去修改它们。