一、需求
用任意一种面向对象语言实现一个计算器控制台程序,要求输入两个数和运算符号,等到结果。
二、实现
- 程序入口
import org.slf4j.LoggerFactory
import scala.io.StdIn
object Program {
private val logger = LoggerFactory.getLogger(this.getClass)
def main(args: Array[String]): Unit = {
try {
print("请输入数字A:")
val strNumberA = StdIn.readLine()
print("请输入操作符号(+,-,*,/):")
val strOperate = StdIn.readLine()
print("请输入数字B:")
val strNumberB = StdIn.readLine()
val operation = OperationFactory.createOperate(strOperate)
operation._numberA = strNumberA.toDouble
operation._numberB = strNumberB.toDouble
println(operation.getResult())
} catch {
case e:Exception => logger.error("输入的数字非法")
}
}
}
- 操作父类
class Operation {
var _numberA: Double = 0
var _numberB: Double = 0
def getResult(): Double = {
val result = 0
result
}
}
- 操作子类
class OperationAdd extends Operation {
override def getResult(): Double = {
var result: Double = 0
result = _numberA + _numberB
result
}
}
class OperationDiv extends Operation {
override def getResult(): Double = {
var result: Double = 0
if (_numberB == 0) throw new Exception("除数不能为0")
result = _numberA / _numberB
result
}
}
class OperationMul extends Operation {
override def getResult(): Double = {
var result: Double = 0
result = _numberA * _numberB
result
}
}
class OperationSub extends Operation {
override def getResult(): Double = {
var result: Double = 0
result = _numberA - _numberB
result
}
}
- 操作工产类
object OperationFactory {
def createOperate(operate:String): Operation ={
operate match {
case "+"=>new OperationAdd()
case "-"=>new OperationSub()
case "*"=>new OperationMul()
case "/"=>new OperationDiv()
case _=>throw new Exception("无法识别操作符")
}
}
}
三、详解
- 面向对象编程
通过封装,继承和多态把程序的耦合度降低。用设计模式使得程序更加灵活,容易修改,并且易于复用 - 封装
对于这个计算器的例子,就是将业务逻辑和界面逻辑分开,让他们的耦合度下降。只有分离开,才可以达到容易维或扩展(但这还谈不上完全面向对象,这只用到了封装,还有继承和多态) - 继承,多态
如果需要增加一个开根(sqrt)运算,却让其他加减乘除的运算都来参与编译。如果一不小心把加法改成了减法,那不是就糟糕了。
所以我们应该将加减乘除等运算分离,修改其中的一个不影响另外的几个,增加运算的算法也不影响其他的算法。 - 简单工厂模式
有一个问题就是我们如何让计算器知道我是希望用哪一个算法呢?这个问题也就是去实例化对象的问题。也就是说,到底要实例化谁,将来会不会增加实例化的对象,比如增加开跟运算,这是一个很容易变化的地方,应该考虑单独创建一个类来做这个创造实例的过程,这就是工厂。