专业的编程技术博客社区

网站首页 > 博客文章 正文

设计模式1.代码无错就是优?简单工厂模式 (大话设计模式Kotlin版)

baijin 2024-11-20 12:32:37 博客文章 3 ℃ 0 评论

面试受挫

面试题:

“用任意一种面向对象语言实现一个计算器控制台程序,要求输入两个数和运算符号,得到结果。”

初学者的代码

以下的程序是利用计算机的方式去思考。看起来并没有什么大的问题,也能得到正确的结果,但是这种思维却使我们的程序只能满足实现当前的需求,不符合易维护、易扩展、易复用,达不到高质量代码的需求!

/**

* @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

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表