大话设计模式-01:代码无错就是优?——简单工厂模式

0. 前言

要求实现一个计算器的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class Program {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);

System.out.println("请输入数字A:");
String A = scanner.nextLine();
System.out.println("请选择运算符号(+、-、*、/):");
String B = scanner.nextLine();
System.out.println("请输入数字C:");
String C = scanner.nextLine();
String D = "";

if (B.equals("+"))
D = String.valueOf(Double.valueOf(A) + Double.valueOf(C));
if (B.equals("-"))
D = String.valueOf(Double.valueOf(A) - Double.valueOf(C));
if (B.equals("*"))
D = String.valueOf(Double.valueOf(A) * Double.valueOf(C));
if (B.equals("/"))
D = String.valueOf(Double.valueOf(A) / Double.valueOf(C));

System.out.println("结果为:" + D);
}
}

1. 代码规范

问题:

  • 1、命名不规范;
  • 2、判断分支,用if写,意味着每个条件都要判断,每次都要做三次无用功
  • 3、如果除数为0或者不是数字,而是其他的字符,如何处理?

修改之后:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class Program {
public static void main(String[] args) {
try {
Scanner scanner = new Scanner(System.in);

System.out.println("请输入数字A:");
String strNumberA = scanner.nextLine();
System.out.println("请选择运算符号(+、-、*、/):");
String strOperate = scanner.nextLine();
System.out.println("请输入数字B:");
String strNumberB = scanner.nextLine();
String strResult = "";

switch (strOperate) {
case "+":
strResult = String.valueOf(Double.valueOf(strNumberA) + Double.valueOf(strNumberB));
break;
case "-":
strResult = String.valueOf(Double.valueOf(strNumberA) - Double.valueOf(strNumberB));
break;
case "*":
strResult = String.valueOf(Double.valueOf(strNumberA) * Double.valueOf(strNumberB));
break;
case "/":
strResult = String.valueOf(Double.valueOf(strNumberA) / Double.valueOf(strNumberB));
break;
}

System.out.println("结果为:" + strResult);
} catch (Exception e) {
System.out.println("输入有误:" + e);
}
}
}

2. 业务封装

程序不单要实现需求,还需要易维护,易扩展,易复用。

面向对象的分析设计编程思想,考虑通过封装、继承、多态把程序的耦合度降低,使用设计模式使程序更加灵活,容易修改,并且易于复用。

让业务逻辑和界面逻辑分开,降低耦合,只有分离开,才能容易维护或扩展。

Operation运算类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class Operation {
public static double getResult(double numberA, double numberB, String operation) {
double result = 0D;

switch (operation) {
case "+":
result = numberA + numberB;
break;
case "-":
result = numberA - numberB;
break;
case "*":
result = numberA * numberB;
break;
case "/":
result = numberA / numberB;
break;
}

return result;
}
}

客户端代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class Program {
public static void main(String[] args) {
try {
Scanner scanner = new Scanner(System.in);

System.out.println("请输入数字A:");
String strNumberA = scanner.nextLine();
System.out.println("请选择运算符号(+、-、*、/):");
String strOperate = scanner.nextLine();
System.out.println("请输入数字B:");
String strNumberB = scanner.nextLine();
String strResult = "";

strResult = String
.valueOf(Operation.getResult(Double.valueOf(strNumberA), Double.valueOf(strNumberB), strOperate));

System.out.println("结果为:" + strResult);
} catch (Exception e) {
System.out.println("输入有误:" + e);
}
}
}

3. 紧耦合 & 松耦合

上面只用到了封装,继承和多态如何使用?

思考:如上,如果需要增加一个新的运算,按照一般方法,就是在switch中新增加一个case,但是这样,为了增加一个新的运算,却要所有的运算都参与编译,另外,如果不小心修改了其他case里面的内容,就会造成程序错误。

所以应该把运算分离,修改其中一个,不会影响到另外几个,增加新的运算,也不会影响其他代码。

修改Operation运算类,接口

1
2
3
public interface IOperation {
double getResult(double numberA, double numberB);
}

加减乘除类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class OperationAdd implements IOperation {
@Override
public double getResult(double numberA, double numberB) {
return numberA + numberB;
}
}

public class OperationSub implements IOperation {
@Override
public double getResult(double numberA, double numberB) {
return numberA - numberB;
}
}

public class OperationMul implements IOperation {
@Override
public double getResult(double numberA, double numberB) {
return numberA * numberB;
}
}

public class OperationDiv implements IOperation {
@Override
public double getResult(double numberA, double numberB) {
if (numberB == 0) {
throw new IllegalArgumentException("除数不能为0");
}
return numberA / numberB;
}
}

4. 简单工厂模式

现在的问题就是如何去实例化对象的问题,可以使用简单工厂模式,即,到底要实例化谁,将来会不会增加实例化的对象,可以考虑使用一个单独的类来做这个创建实例的过程,这就是工厂。

简单运算工厂类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class OperationFactory {
public static Operation createOperation(String operation) {
Operation oper = null;
switch (operation) {
case "+":
oper = new OperationAdd();
break;
case "-":
oper = new OperationSub();
break;
case "*":
oper = new OperationMul();
break;
case "/":
oper = new OperationDiv();
break;
}
return oper;
}
}

这样只需要输入运算符工厂类就会实例化对应的对象,通过多态,返回父类的方法实现计算的结果。

1
2
IOperation operation = OperationFactory.createOperation("-");
operation.getResult(2, 1);
  • Copyrights © 2019-2020 Tyler Liu

请我喝杯咖啡吧~

支付宝
微信