Swift语言之命令模式(Command Pattern)实现
今天遇到这样一个问题,我现在有一个整数数组,如:
var numbers = [3, 7, 12, 9, 200]
现需要对其中的每一个数字都执行一系列相同的加减乘除操作,如对每一个数字都加5乘8再减去1,但是这样的操作在编译时并不确定,需要在运行时由用户指定;
一看到这个题目,当然就想到了用设计模式中的命令模式来实现;
于是先写了这样的一个类:
class Calculator {
private(set) var total = 0
required init(value: Int){
total = value
}
func add(amount: Int) {
total += amount
}
func substract(amount: Int) {
total -= amount
}
func multiply(amount: Int) {
total = total * amount
}
func divide(amount: Int) {
total = total / amount
}
}
这个类用于实现对某个数执行不同的操作。
下一步中我创建了一个Command类,用于记录需要执行的操作:
struct Command {
typealias OperationType = (Calculator -> Int -> Void)
let operation: OperationType
let amount: Int
init(operation: OperationType, amount: Int) {
self.operation = operation
self.amount = amount
}
func execute(calculator: Calculator) {
operation(calculator)(amount)
}
}
在该类中我定义了一个名为OperationType的类型别名,从定义中可以看出,OperationType类型的实例是一个Closure,该Closure接受一个Calculator类型的实例,并返回一个类型为Int -> Void的Closure(此Closure的类型就是Calculator中每个方法的类型);
amount为执行那个操作的参数值;
待一切完毕后,由用户来指定要执行的命令,如将数组numbers中的每一个值加5乘8再减去1,则可以这样实现:
var commands = [Command]()
commands.append(Command(operation: Calculator.add, amount: 5))
commands.append(Command(operation: Calculator.multiply, amount: 8))
commands.append(Command(operation: Calculator.substract, amount: 1))
这样做并没有达到Command设计模式想要达到的目的,及实现命令的发出者与命令的执行者之间的脱耦;于是我加入了一个新的enum类型:
enum OperationType {
case Add(Int)
case Substract(Int)
case Multiply(Int)
case Divide(Int)
}
这个enum类型中的每一个成员都自带一个关联值,及要执行操作的参数,于是Command类型可以改变为:
struct Command {
let operationType: OperationType
init(operationType: OperationType) {
self.operationType = operationType
}
func execute(calculator: Calculator) {
switch self.operationType {
case .Add(let value):
calculator.add(value)
case .Substract(let value):
calculator.substract(value)
case .Multiply(let value):
calculator.multiply(value)
case .Divide(let value):
calculator.divide(value)
}
}
}
重新创建Commands数组:
var commands = [Command]()
commands.append(Command(operationType: .Add(5)))
commands.append(Command(operationType: .Multiply(8)))
commands.append(Command(operationType: .Substract(1)))
OK,执行所有命令:
for number in numbers {
var calculator = Calculator(value: number)
for command in commands {
command.execute(calculator)
}
println("\(number) -> \(calculator.total)")
}
这里是结果:

Swift语言之命令模式(Command Pattern)实现的更多相关文章
- 设计模式 - 命令模式(command pattern) 多命令 具体解释
命令模式(command pattern) 多命令 具体解释 本文地址: http://blog.csdn.net/caroline_wendy 參考命令模式: http://blog.csdn.ne ...
- 设计模式 - 命令模式(command pattern) 具体解释
命令模式(command pattern) 详细解释 本文地址: http://blog.csdn.net/caroline_wendy 命令模式(command pattern) : 将请求封装成对 ...
- 设计模式 - 命令模式(command pattern) 宏命令(macro command) 具体解释
命令模式(command pattern) 宏命令(macro command) 具体解释 本文地址: http://blog.csdn.net/caroline_wendy 參考: 命名模式(撤销) ...
- 乐在其中设计模式(C#) - 命令模式(Command Pattern)
原文:乐在其中设计模式(C#) - 命令模式(Command Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 命令模式(Command Pattern) 作者:webabcd ...
- 设计模式 - 命令模式(command pattern) 撤销(undo) 具体解释
命令模式(command pattern) 撤销(undo) 详细解释 本文地址: http://blog.csdn.net/caroline_wendy 參考命令模式: http://blog.cs ...
- 二十四种设计模式:命令模式(Command Pattern)
命令模式(Command Pattern) 介绍将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化:对请求排队或记录请求日志,以及支持可取消的操作. 示例有一个Message实体类,某个 ...
- 设计模式-15命令模式(Command Pattern)
1.模式动机 在软件设计中,我们经常需要向某些对象发送请求,但是并不知道请求的接收者是谁,也不知道被请求的操作是哪个,我们只需在程序运行时指定具体的请求接收者即可,此时,可以使用命令模式来进行设计,使 ...
- 设计模式(六):控制台中的“命令模式”(Command Pattern)
今天的博客中就来系统的整理一下“命令模式”.说到命令模式,我就想起了控制台(Console)中的命令.无论是Windows操作系统(cmd.exe)还是Linux操作系统(命令行式shell(Comm ...
- 十一个行为模式之命令模式(Command Pattern)
定义: 将一个请求封装成对象,使得请求发送者和请求接受者之间相互隔离,消除两者之间的耦合.引入命令类,使得不同请求对客户参数化,并且可以对命令添加附件操作,如:排队.撤销.日志.组合等. 结构图: C ...
随机推荐
- 动态调用WebService(C#) (非常实用)
通常我们在程序中需要调用WebService时,都是通过“添加Web引用”,让VS.NET环境来为我们生成服务代理,然后调用对应的Web服务.这样是使工作简单了,但是却和提供Web服务的URL.方法名 ...
- HDU5769 Substring(后缀数组)
链接:http://acm.hdu.edu.cn/showproblem.php?pid=5769 #include <iostream> #include <stdio.h> ...
- EasyTouch绑定事件在电脑上点击有效Android上无效的解决方法
最近做一个RPG类的游戏发现使用EasyTouch虚拟摇杆插件在电脑上点击有效Android上无效,查找资料发现是Easy Joystick中的一个属性interaction type要设置成 Dir ...
- JQuery 实现锚点链接之间的平滑滚动
24. 解决链接锚点的生硬问题 $('.nav .btn[href*=#],.icon2,.icon3').click(function() { if (location.pathname.repla ...
- C++ 画星号图形——空心梯形(核心代码记录)
b=a; ;c<=a;c++) { ;d<=a-c;d++) printf(" "); ;e<=b;e++) ||c==a) printf("*&quo ...
- ZOJ 2771
Description Considering a light entering three adjacent planes of glass. At any meeting surface, t ...
- Java实现MySQL数据库备份(二)
权声明:本文为博主原创文章,未经博主允许不得转载. 博客<Java实现MySQL数据库备份(一)>使用I/O流的方式实现了MySQL数据库的备份,这种方法比较繁杂,下面介绍另一种备份MyS ...
- http之Session&Cookie
百度了一波session与Cookie,我发现这东西远比我想象中更复杂(可能是因为我不明白底层的运行原理).网上也是一堆的关于Session与Cookie区别/联系的文章,然而,我看完了还是一脸懵逼的 ...
- Another MySQL daemon already running with the same unix socket的解决
问题出现: 每周一需要备份一次数据库,即从服务器MySQL导出sql文件,再导入到我机器上虚拟机的MySQL里.但是今天早上连不上,我进入控制台用#service mysqld start强行启动,报 ...
- 深入理解js的prototype以及prototype的一些应用
上一篇讲了js的prototype概念,在这里回顾一下prototype的定义: prototype是函数的一个属性,并且是函数的原型对象.引用它的必然是函数,这个应该记住. 但是,很奇怪,各位看官, ...