网站首页 > 博客文章 正文
面试受挫
面试题:
“用任意一种面向对象语言实现一个计算器控制台程序,要求输入两个数和运算符号,得到结果。”
初学者的代码
以下的程序是利用计算机的方式去思考。看起来并没有什么大的问题,也能得到正确的结果,但是这种思维却使我们的程序只能满足实现当前的需求,不符合易维护、易扩展、易复用,达不到高质量代码的需求!
/**
* @create on 2020/4/23 22:50
* @description 计算器控制台程序(两个数的运算)
* @author mrdonkey
*/
class Program {
companion object {
@JvmStatic
fun main(vararg args: String) {
val sc = Scanner(System.`in`)
println("请输入数字A")
val strNumberA = sc.nextLine()
println("请输入运算符")
val operate = sc.nextLine()
println("请输入数字B")
val strNumberB = sc.nextLine()
val strResult: String = when (operate) {
"+" -> {
strNumberA.toDouble().plus(strNumberB.toDouble()).toString()
}
"-" -> {
strNumberA.toDouble().minus(strNumberB.toDouble()).toString()
}
"*" -> {
strNumberA.toDouble().times(strNumberB.toDouble()).toString()
}
"/" -> {
if (strNumberB != "0")
strNumberA.toDouble().div(strNumberB.toDouble()).toString()
else
"除数不能为0"
}
else -> {
"不支持该运算"
}
}
println("结果是:$strResult")
}
}
}
测试结果:
请输入数字A
123
请输入运算符
*
请输入数字B
3
结果是:369.0
利用封装的实现
将业务逻辑(计算操作)与界面逻辑(输入结果)分开,让它们 的耦合度降低
Operate操作类
/**
* @create on 2020/4/23 23:11
* @description 把计算的操作类抽出来
* @author mrdonkey
*/
class Operate {
companion object {
@JvmStatic
fun getResult(numberA: Double, numberB: Double, operate: String): Double {
return when (operate) {
"+" -> {
numberA.plus(numberB)
}
"-" -> {
numberA.minus(numberB)
}
"*" -> {
numberA.times(numberB)
}
"/" -> {
numberA.div(numberB)
}
else -> {
0.toDouble()
}
}
}
}
}
封装后的程序
/**
* @create on 2020/4/23 23:09
* @description 利用封装来实现 将页面逻辑与业务逻辑分开
* @author mrdonkey
*/
class PackageProgram {
companion object {
@JvmStatic
fun main(vararg args: String) {
try {
val sc = Scanner(System.`in`)
println("请输入数字A")
val numberA = sc.nextLine().toDouble()
println("请选择运算符(+、-、*、/):")
val operate = sc.nextLine()
println("请输入数字B")
val numberB = sc.nextLine().toDouble()
println("输出结果是:${Operate.getResult(numberA, numberB,operate)}")
} catch (e: Exception) {
println("你输入有错:${e.message}")
}
}
}
}
输出同上
利用继承和多态的方式实现松耦合
如果要在之上的程序中,添加一种sqrt开根的运算,需要在Operate类的switch加多一个分支。问题是加一个开根运算,却需要让加减乘除的运算都得来参与编译,如果把加法运算不小心改成减法,这将是多糟糕。应该把单独的操作运算分离出来,提取父类(继承),修改其中一个一个操作不影响其他几个,每一个操作都有自己不同的实现(多态)。
Operation类
/**
* @create on 2020/4/23 23:26
* @description 利用继承和多态来减少耦合
* @author mrdonkey
*/
abstract class Operation {
abstract fun getResult(numberA: Double, numberB: Double): Double
}
OperationPlus
/**
* @create on 2020/4/23 23:28
* @description TODO
* @author 加法
*/
class OperationPlus : Operation() {
override fun getResult(numberA: Double, numberB: Double) = numberA.plus(numberB)
}
OperationMinus
/**
* @create on 2020/4/23 23:28
* @description TODO
* @author 加法
*/
/**
* @create on 2020/4/23 23:29
* @description 减法
* @author mrdonkey
*/
class OperationMinus : Operation() {
override fun getResult(numberA: Double, numberB: Double) = numberA.minus(numberB)
}
OperationTimes
/**
* @create on 2020/4/23 23:30
* @description 乘法
* @author mrdonkey
*/
class OperationTimes : Operation() {
override fun getResult(numberA: Double, numberB: Double) = numberA.times(numberB)
}
OperationDiv
/**
* @create on 2020/4/23 23:30
* @description 除法
* @author mrdonkey
*/
class OperationDiv : Operation() {
override fun getResult(numberA: Double, numberB: Double) = numberA.div(numberB)
}
1
2
3
4
5
6
7
8
提取了父类,并且提供一个getResult的抽象方法由具体子类来实现不同的运算操作,现在我们的修个任何一个运算方法,都不会影响其他的运算的代码了。但是我如何让计算器知道我希望用哪个运算呢?
简单工厂模式的应用
用一个单独的类来决定实例化谁、用哪个运算!这就是简单工厂的职责。
UML类图结构
OperationFactory
/**
* @create on 2020/4/23 23:33
* @description 操作的工厂,让它知道该实例化哪个操作
* @author mrdonkey
*/
class OperationFactory {
companion object {
@JvmStatic
fun creatOperate(operate: String): Operation? = when (operate) {
"+" -> {
OperationPlus()
}
"-" -> {
OperationMinus()
}
"*" -> {
OperationTimes()
}
"/" -> {
OperationDiv()
}
else -> {
null
}
}
}
}
Client测试
/**
* @create on 2020/4/23 23:37
* @description 客户端测试
* @author mrdonkey
*/
class Client {
companion object {
@JvmStatic
fun main(vararg args: String) {
try {
val sc = Scanner(System.`in`)
println("请输入数字A")
val numberA = sc.nextLine().toDouble()
println("请选择运算符(+、-、*、/):")
val operate = sc.nextLine()
println("请输入数字B")
val numberB = sc.nextLine().toDouble()
val operation = OperationFactory.creatOperate(operate)
println("输出结果是:${operation?.getResult(numberA, numberB)}")
} catch (e: Exception) {
println("你输入有错:${e.message}")
}
}
}
}
输出同上
这样子,你只需要输入相应的运算符号,工厂就实例化对应的运算对象,通过多态返回父类方式实现了计算器的结果。如果以后需要增加各种复杂运算,比如平方根、立方根等,只需要增加对应的子类运算和给工厂添加相应的switch分支即可。
————————————————
版权声明:本文为CSDN博主「mrdonkey3」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_17846019/article/details/105695140
猜你喜欢
- 2024-11-20 Compose Desktop 初体验之踩坑
- 2024-11-20 Android IO 框架 Okio 的实现原理,到底哪里 OK?
- 2024-11-20 Android Jetpack系列(八):WorkManager(使用篇)
- 2024-11-20 事无巨细的Android内存泄漏
- 2024-11-20 Hilt凭什么取代Dagger2成为谷歌官方推荐IOC注入方式
- 2024-11-20 Android Jetpack系列(七):Room(使用篇)
- 2024-11-20 再见吧 buildSrc, 拥抱 Composing builds 提升 Android 编译速度
- 2024-11-20 基于 Kafka 和 Elasticsearch 构建实时站内搜索功能的实践
- 2024-11-20 安卓中的ARCore和Sceneform-处理手势和碰撞
- 2024-11-20 Jetpack系列:Paging组件帮你解决分页加载实现的痛苦
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- powershellfor (55)
- messagesource (56)
- aspose.pdf破解版 (56)
- promise.race (63)
- 2019cad序列号和密钥激活码 (62)
- window.performance (66)
- qt删除文件夹 (72)
- mysqlcaching_sha2_password (64)
- ubuntu升级gcc (58)
- nacos启动失败 (64)
- ssh-add (70)
- jwt漏洞 (58)
- macos14下载 (58)
- yarnnode (62)
- abstractqueuedsynchronizer (64)
- source~/.bashrc没有那个文件或目录 (65)
- springboot整合activiti工作流 (70)
- jmeter插件下载 (61)
- 抓包分析 (60)
- idea创建mavenweb项目 (65)
- vue回到顶部 (57)
- qcombobox样式表 (68)
- vue数组concat (56)
- tomcatundertow (58)
- pastemac (61)
本文暂时没有评论,来添加一个吧(●'◡'●)