我需要帮助重构代码以符合单一责任原则



我目前正试图通过阅读名为Practical Object Oriented Design in Ruby的书来理解SOLID原理。第一个原则是单一责任,我理解这个概念的方式是,一个类/方法应该只有一个责任或改变的理由。

在下面的代码中,我有一个Calculate类,它负责(4)四种不同的操作,addsubtractmultiplydivide,对我来说,这不符合单一责任理论。

有人能这么友善,以一种符合Single Responsibility的方式重构下面的类吗?

我知道这可能是一个非常固执己见的话题,但我真的需要更好地理解这个概念。

仅供参考-为了简单起见,我只使用Ints,我知道它不适合除法和减法。

class Calculate{
    let num1:Int
    let num2:Int
    init(firstNum:Int, secondNum:Int){
        num1 = firstNum
        num2 = secondNum
    }
    func add()->Int{
        let total = num1 + num2
        return total
    }
    func subtract()->Int{
        let total = num1 - num2
        return total
    }
    func multiply()->Int{
        let total = num1 + num2
        return total
    }
    func divide()->Int{
        let total = num1 / num2
        return total
    }
}

let operation = Calculate(firstNum:5 , secondNum:5)
print(operation.divide())

单一责任意味着类应该只有一个逻辑功能。

所以,如果你有计算器,它是完全可以的,它可以计算。"单一"并不意味着"单一方法"。计算器可以求和、除法等等,对吧?所以,是的,这正是Calculator类方法应该做的

例如,如果要连接两个Calculator类,则添加方法"connectToAnotherCalculator"是违反SRP的。正确的方法是创建连接器类,它应该处理计算器之间的通信。

我想建议更好的设计。想象一下,您必须添加许多其他运算:百分比、平方根,甚至正弦。你的计算器将增长数千行。测试呢?假设,我们已经测试了计算器。现在我们需要在每次手术后再次进行测试。所以,增加新的操作将花费我们更换计算器,更换所有使用它的地方和许多涵盖它的测试

但我们可以制作一个单一责任的计算器——计算(运算):1) 现在我们可以使用无处不在的计算器->计算(运算),用测试来覆盖它并使它们通过。2) 对于每一个新的操作,我们只需添加新的操作类并对其进行测试。我们可以轻松地更改任何操作,甚至不需要触摸计算器和使用它的对象。

@Denis Efimov这是我根据你的建议编写的代码。这段来自Laracasts的视频对我帮助很大,它是用PHP编写的,但很容易将其翻译成Swift。

我只显示了两个操作(AdditionMultiplication),但我可以很容易地添加任意数量的操作。请注意,为了简单起见,我只使用Int s。

protocol Operation{
    func equation()->Int
}
class Calculator{
    func calculate(operation:Operation)->Int{
        return operation.equation()
    }
}
class Addition:Operation{
    var addendOne:Int
    var addendTwo:Int
    init(addendOne:Int, addendTwo:Int){
        self.addendOne = addendOne
        self.addendTwo = addendTwo
    }
    func equation()->Int{
        return self.addendOne + self.addendTwo
    }
}
class Multiplication:Operation{
    var multiplicand:Int
    var multiplier:Int
    init(multiplicand:Int, multiplier:Int){
        self.multiplicand = multiplicand
        self.multiplier = multiplier
    }
    func equation()->Int{
        return self.multiplicand * self.multiplier
    }
}

let addition = Addition(addendOne:5, addendTwo:5)
let multiplication = Multiplication(multiplicand:5, multiplier:5)
let calculator = Calculator()
print(calculator.calculate(addition))
print(calculator.calculate(multiplication))

你们对这个代码有什么看法,这看起来是一个更好的方法吗?这是否更符合SOLID原则(SO)?。

感谢

最新更新