1.1 面试受挫
要求:面向对象编程语言写一个计算器小程序!
下面例子是面向过程编程实现,而且有一些小问题
package com.designPattern.v1;
import java.util.Scanner;
/**
*
*/
public class Cacultor01 {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
double a = 0,b = 0,c = 0;
String op = null;
//输入的类型与想要的不符怎么办?
System.out.println("请输入数字A:");
if(scan.hasNextDouble()) {
a = scan.nextDouble();
} else {
System.out.println("非数字,请重新输入");
}
System.out.println("请输入符号:+ - * /");
if(scan.hasNext()) {
op = scan.next();
}
System.out.println("请输入数字B:");
if(scan.hasNextDouble()) {
b = scan.nextDouble();
}
//else
if(op == "+")
c = a + b;
if(op == "-")
c = a - b;
if(op == "*")
c = a * b;
if(op == "/")
c = a / b; //输入了0怎么办?
System.out.println(a + " " + op + b + " = " + c);
scan.close();
}
}
1.2 初学者代码的毛病
- 命名规范
- if判断
- 异常校验
1.3 代码规范
改进版本:规范了变量命名,分支优化,加了异常捕获
package com.designPattern.v1;
import java.util.Scanner;
public class Cacultor02 {
public static void main(String[] args) {
try {
Scanner scan = new Scanner(System.in);
double number1 = 0,nubmer2 = 0;
String op = null,result = null;
//输入的类型与想要的不符怎么办?
System.out.println("请输入数字A:");
if(scan.hasNextDouble()) {
number1 = scan.nextDouble();
} else {
throw new Exception("数字类型规范");
}
System.out.println("请输入符号:+ - * /");
if(scan.hasNext()) {
op = scan.next();
}
System.out.println("请输入数字B:");
if(scan.hasNextDouble()) {
nubmer2 = scan.nextDouble();
} else {
throw new Exception("数字类型规范");
}
switch(op) {
case "+" : result = number1 + nubmer2 + "";break;
case "-" : result = number1 - nubmer2 + "";break;
case "*" : result = number1 * nubmer2 + "";break;
case "/" :
if(nubmer2 != 0)
result = (number1 / nubmer2) + "";
else
result = "除数不能为0";
break;
default : result = "请按提示输入操作符!";break;
}
System.out.println("结果是 "+ result);
scan.close();
} catch(Exception e) {
e.printStackTrace();
System.out.println("您输入的参数不符合规范");
System.exit(-1);
}
}
}
1.4 面向对象编程
上面是面向过程的计算机处理问题的逻辑,这本身并没有什么错。
只是这使得程序只为满足当前程序需求,程序不容易 维护、扩展、复用。非高质量也!
1.5 活体印刷,面向对象
第一、要改,只需更改要改之字,此为可维护
第二、这些字并非用完这次就无用,完全可以在后来的印刷中重复使用,此乃可复用
第三、此诗若要加字,只需另刻字加入即可,这是可拓展。
第四、字的排列其实可能是竖排,可能是横排,此时只需将活字移动就可做的满
足排列需求,此是灵活性好
1.6面向对象的好处
- 通过封装、继承、多态把程序的耦合度降低
- 使用设计模式使得程序更加灵活、易于修改,且易于复用
1.7 复制VS复用
思考:要求你再写一个计算器?怎么办?
办法:Ctrl + C / Ctrl + V ?
结论:看似简单,当重复代码多到一定程度,维护的时候,可能就是一场灾难。
思路:分一个类出来,
1.8 业务的封装
准确的说,让业务逻辑与界面逻辑分开,让他们直之间的耦合度下降。只有分离开才可以达到容易维护和拓展。
- 业务逻辑运算类 【可复用了哦】
public class Opration {
public static double getResult(double number1, double number2, String op) {
double result = 0;
switch(op) {
case "+" : result = number1 + number2;break;
case "-" : result = number1 - number2;break;
case "*" : result = number1 * number2;break;
case "/" : result = number1 / number2;break;
default: System.out.println("操作符不合法!");break;
}
return result;
}
}
- 客户端代码
//客户端代码
package com.designPattern.v1;
import java.util.Scanner;
public class Cacultor3 {
public static void main(String[] args) {
try {
Scanner scan = new Scanner(System.in);
double number1 = 0,number2 = 0;
String op = null,result = null;
//输入的类型与想要的不符怎么办?
System.out.println("请输入数字A:");
if(scan.hasNextDouble()) {
number1 = scan.nextDouble();
System.out.println(number1);
} else {
throw new Exception("数字类型规范");
}
System.out.println("请输入符号:+ - * /");
if(scan.hasNext()) {
op = scan.next();
}
System.out.println("请输入数字B:");
if(scan.hasNextDouble()) {
System.out.println(number2);
number2 = scan.nextDouble();
} else {
throw new Exception("数字类型规范");
}
if(number2 == 0) {
result = "除数不能为0";
} else {
result = Opration.getResult(number1, number2, op) + "";
}
System.out.println("结果是 "+ result);
scan.close();
} catch(Exception e) {
System.out.println("您输入的参数不符合规范");
System.exit(-1);
}
}
}
1.9 紧耦合 VS 松耦合
问题:上面的代码是否可以做到灵活地可修改和拓展呢?如果加一个开根
运算怎么办?改Opration封装类代码吗?改坏了咋办!!!
思考: 如何增加或修改一个算法而不影响算法?
方案: 抽象实现属性封装算法声明,继承实现属性继承和算法分离,多态实现不同算法的切换
package com.designPattern.v1;
import lombok.Data;
@Data
public abstract class Operation {
private double numberA;
private double nubmerB;
public abstract double getResult();
}
class OperationAdd extends Operation {//加法
@Override
public double getResult() {
return getNumberA() + getNubmerB();
}
}
class OperationSub extends Opration {//减法
@Override
public double getResult() {
return getNumberA() - getNubmerB();
}
}
class OperationMul extends Opration {//乘法
@Override
public double getResult() {
return getNumberA() * getNubmerB();
}
}
class OperationDiv extends Opration {//除法
@Override
public double getResult() {
if(getNubmerB() == 0)
throw new RuntimeException("除数不能为0");
return getNumberA() / getNubmerB();
}
}
1.10简单工厂模式
问题:如何让计算器知道我希望用哪一个算法(即如何实例化对象)?
思考:到底要实例化谁?将来会不会增加实例化对象,比如增加开根运行等,这是很容易变化的地方,应该考虑用一个单独的类来做这个创造实例的过程,这就是工厂
package com.designPattern.v1;
public class OprationFactory {
public static Operation createOperation(String op) {
Operation2 result = null;
switch(op) {
case "+" : result = new OperationAdd();break;
case "-" : result = new OperationSub();break;
case "*" : result = new OperationMul();break;
case "/" : result = new OperationDiv();break;
default: System.out.println("操作符不合法!");break;
}
return result;
}
}
客户端代码:
Operation2 op = null;
op = OprationFactory.createOperation("+");
op.setNumberA(10);
op.setNubmerB(20);
double result = op.getResult();
编后语
编程是一门技术,更是一门艺术。不能只满足于写完代码,运行结果正确就完事。时常考虑让代码更加简练,更容易维护,容易扩展和复用,只有这样才能真正得到提高。