被老公埋汰
媳妇儿由于一直做业务系统的开发,所以技术方面已经跟不上时代潮流了。今天就被老公狠狠地羞辱了一番。
起因
媳妇儿的业务需要实现一个计算器控制程序。
package design01;
import java.util.Scanner;
public class Test01 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("请输入数字A: ");
String A = sc.nextLine();
System.out.print("请输入运算符号(+、-、*、/): ");
String B = sc.nextLine();
System.out.print("请输入数字B: ");
String C = sc.nextLine();
String D = "";
if (B.equals("+")) {
D = String.valueOf(Integer.parseInt(A) + Integer.parseInt(C));
} else if (B.equals("-")) {
D = String.valueOf(Integer.parseInt(A) - Integer.parseInt(C));
} else if (B.equals("*")) {
D = String.valueOf(Integer.parseInt(A) * Integer.parseInt(C));
} else if (B.equals("/")) {
D = String.valueOf(Integer.parseInt(A) / Integer.parseInt(C));
} else {
System.out.println("运算符号输入错误!");
}
System.out.println("结果是: " + D);
}
}
问题解析
有错就改,媳妇美德
基于以上问题,媳妇儿重构了一下代码,如下:
package design01;
import java.util.Scanner;
public class Test01 {
public static void main(String[] args) {
try {
System.out.println("请输入数字A: ");
Scanner sc = new Scanner(System.in);
String strNumberA = sc.nextLine();
System.out.println("请输入运算符号(+、-、*、/): ");
String strOperate = sc.nextLine();
System.out.println("请输入数字B: ");
String strNumberB = sc.nextLine();
String result = "";
switch (strOperate) {
case "+":
result = String.valueOf(Integer.parseInt(strNumberA) + Integer.parseInt(strNumberB));
break;
case "-":
result = String.valueOf(Integer.parseInt(strNumberA) - Integer.parseInt(strNumberB));
break;
case "*":
result = String.valueOf(Integer.parseInt(strNumberA) * Integer.parseInt(strNumberB));
break;
case "/":
if (Integer.parseInt(strNumberB) == 0) {
System.out.println("除数不能为0!");
return;
} else {
result = String.valueOf(Integer.parseInt(strNumberA) / Integer.parseInt(strNumberB));
}
break;
}
System.out.println("结果是:" + result);
} catch (Exception ex) {
System.out.println("您的输入有错:" + ex.getMessage());
}
}
}
信心满满的让老公看,结果又被老公教育了一番。既然用了java代码,就要用面向对象编程。
面向对象
教育媳妇儿:面向过程和面向对象的区别。面向过程是以计算机能够理解的逻辑来解决问题,第一步做什么、第二步做什么......,这样写出来的代码不容易维护和扩展。
好处
- 传统印刷术:将所有文字刻在同一个面板上,耦合度太高,如果改其中的一个字,则整个面板都需要重新刻制
- 活字印刷术:每个字都单独刻制,需要修改哪个字就改那个字,活刻活用
业务封装
界面逻辑和业务逻辑分开,让他们的耦合度降低 媳妇儿吭哧瘪肚重新修改一版代码,如下
操作类封装
public class Operation {
public static double getResult(double strNumberA, double strNumberB, String operate) {
double result = 0d;
switch (operate) {
case "+":
result = strNumberA + strNumberB;
break;
case "-":
result = strNumberA - strNumberB;
break;
case "*":
result = strNumberA * strNumberB;
break;
case "/":
result = strNumberA / strNumberB;
break;
}
return result;
}
}
客户端类封装
import java.util.Scanner;
public class Test01 {
public static void main(String[] args) {
try {
System.out.println("请输入数字A: ");
Scanner sc = new Scanner(System.in);
String strNumberA = sc.nextLine();
System.out.println("请输入运算符号(+、-、*、/): ");
String strOperate = sc.nextLine();
System.out.println("请输入数字B: ");
String strNumberB = sc.nextLine();
String result = "";
result = String.valueOf(Operation.getResult(Double.parseDouble(strNumberA), Double.parseDouble(strNumberB), strOperate));
System.out.println("结果是:" + result);
} catch (Exception ex) {
System.out.println("您的输入有错:" + ex.getMessage());
}
}
}
紧耦合/松耦合
媳妇儿:现在界面显示和客户端已经分离,是不是很灵活了 老公:还差的远,现在操作是在一个类中实现的,如果要增加一个开根号算法,怎么弄? 媳妇儿:那还不简单,增加一个判断不就可以了。 老公:有一个开闭原则知道么?面向修改关闭,面向增加开放。再想想怎么通过继承,将Operation类解耦。 媳妇冥思苦想,终于有办法。
修改代码如下:
/**
* 操作抽象类
*/
public abstract class Operation {
private double numberA = 0;
private double numberB = 0;
public Operation(double numberA, double numberB) {
this.numberA = numberA;
this.numberB = numberB;
}
public double getNumberA() {
return numberA;
}
public double getNumberB() {
return numberB;
}
abstract double getResult();
}
/**
* 加法操作类
*/
public class OperationAdd extends Operation {
public OperationAdd(double numberA, double numberB) {
super(numberA, numberB);
}
@Override
public double getResult() {
return super.getNumberA() + super.getNumberB();
}
}
/**
* 除法操作类
*/
public class OperationDiv extends Operation {
public OperationDiv(double numberA, double numberB) {
super(numberA, numberB);
}
@Override
public double getResult() {
if (super.getNumberB() == 0) {
throw new IllegalArgumentException("The divisor cannot be zero.");
}
return super.getNumberA() / super.getNumberB();
}
}
/**
* 乘法操作类
*/
public class OperationMul extends Operation {
public OperationMul(double numberA, double numberB) {
super(numberA, numberB);
}
@Override
public double getResult() {
return super.getNumberA() * super.getNumberB();
}
}
/**
* 减法操作类
*/
public class OperationSub extends Operation {
public OperationSub(double numberA, double numberB) {
super(numberA, numberB);
}
@Override
public double getResult() {
return super.getNumberA() - super.getNumberB();
}
}
如上代码将操作完全解耦了。增加开平方,只需要增加一个继承Operation类就可以实现了。
简单工厂模式
老公:挺不错,现在的问题是如何实例化对象了。告诉你一个简单工厂模式,也就是说,到底要实例化谁。
代码如下:
public class OperationFactory {
public static Operation createOperation(String operation, double numberA, double numberB) {
Operation oper = null;
switch (operation) {
case "+":
oper = new OperationAdd(numberA, numberB);
break;
case "-":
oper = new OperationSub(numberA, numberB);
break;
case "*":
oper = new OperationMul(numberA, numberB);
break;
case "/":
oper = new OperationDiv(numberA, numberB);
break;
}
return oper;
}
}
测试代码:
public class Test01 {
public static void main(String[] args) {
Operation oper = OperationFactory.createOperation("+", 1, 2);
System.out.println(oper.getResult());
oper = OperationFactory.createOperation("*", 1, 2);
System.out.println(oper.getResult());
}
}
总结
简单工厂模式(Simple Factory Pattern)是一种常用的软件设计模式,属于创建型模式之一。它提供了一个创建对象的静态方法,而不必将客户端代码与对象创建过程耦合起来。简单工厂的核心是一个工厂类,该类包含一个静态方法用于实例化产品类的对象,客户端通过传递一个参数来决定创建哪一个具体的产品对象。此模式简化了客户端代码,使其不需要关心具体产品的创建逻辑,但当系统中添加新的产品时,需要修改工厂类,这违背了开闭原则。此外,随着产品类型的增多,工厂类会变得庞大且难以维护。简单工厂模式适用于产品族较少且产品类的公共接口已知的情况。