斯坦福 iOS c193p 课程学习收获

面试题: 设计并实现一个计算器
正常实现: 在控制器中实现大量的 switch 判断不同操作符.
但是计算相关的代码写到控制器里去, 如果计算一复杂, 控制器会多很多代码, 可读性和逻辑容易混乱, 控制器只应该负责把计算结果显示到相关的视图上去就行, 其他的事情应该交给专门的类去实现.
斯坦福教程中, 使用一个 CalculatorBrain 专门负责接收操作数, 执行运算, 返回结果.
定义属性和方法, accumulator 属性用来存储操作数以及计算结果, setOperand:方法用来接收操作数, performOperation:方法执行运算过程, result 只读属性返回计算结果:

class CalculatorBrain {
    
    var accumulator = 0.0
    
    func setOperand(operand: Double) { }
    
    func performOperation(symbol: String) {  }
    
    var result: Double {
        get {
            return accumulator
        }
    }
}

问题: 每次都要使用根据不同的运算符, 然后在 Switch 中去执行不同的运算.
改进: 使用枚举 Enum 来表示运算类型, 用 Dictionary 来表示和存储不同的运算类型对应的运算.

enum Operation {
    case Constrant(Double)
    case UnaryOperation((Double) -> Double)
    case BinaryOperation((Double, Double) -> Double)
    case Equals
}

该枚举将每一种运算类型对应到每一个枚举成员, 并给枚举成员设置关联值类型,常量运算关联了一个 Double 类型, 一元运算关联了一个 (Double)-> Double 类型的闭包,二元操作运算关联一个 (Double, Double) -> Double 类型的闭包, Equals 运算没有设置关联值类型.

定义一个字典存储不同的运算符以及对应的运算操作

var operations: Dictionary = [
    "π": .Constrant(M_PI),
    "e": .Constrant(M_E),
    "√": Operation.UnaryOperation(sqrt),
    "cos": Operation.UnaryOperation(cos)
 ]

修改 performOperation 中的代码

func performOperation(symbol: String) {
    if let operation = operations[symbol] {
        switch operation {
        case .Constrant(let value): accumulator = value
        case .UnaryOperation(let function): accumulator = function(accumulator)
        default: break
        }
    }
}

在 Switch 语句中, 关联值可以被提取出来作为 switch 语句的一部分. 第一个 case: 关联值是一个 Double 类型的常量, 那么提取出来的关联值就是这个常量的值, 第二个 case: 关联值是一个 (Double) -> Double 类型的闭包, 那么提取出来的关联值就是这个闭包.

考察:
1 Swift 中枚举的使用
2 有简化代码逻辑的意识, 能及时优化自己的代码

follow-up
1 使用链式编程思想实现一个计算器
2 使用面向对象的方式实现一个计算器

你可能感兴趣的:(斯坦福 iOS c193p 课程学习收获)