由于Java 课程设计已经完成前期的计算器GUI设计,以及功能实现,现在基于之前的基础,进行设计模式的应用,以完善软件设计。
如果还不了解之前GUI设计的童鞋,可以先查看【Java课程设计】【图形界面程序】【计算器】。
使用了以下设计模式:
工厂模式被用于创建不同类型的操作对象。Operation 接口充当了工厂模式中的产品,每个具体的操作类(例如 Addition、Subtraction 等)都实现了该接口。在 Calculation 类中,根据操作符的类型,使用工厂模式创建了相应的操作对象。
策略模式用于将不同的操作封装成独立的策略,并使它们可以相互替换。Operation 接口代表了策略的抽象,每个具体的操作类都实现了该接口并提供了自己的实现。在 Calculation 类中,根据用户选择的操作符,选择相应的操作策略,并将计算委托给所选策略。
通过实现 ActionListener 接口,可以为按钮添加监听器,以响应按钮的点击事件。在 Calculation 类中,通过为按钮添加监听器,实现了按钮的点击事件处理。
在 Division 类的 performOperation 方法中,通过抛出 ArithmeticException 异常来处理除以零的情况。在 Calculation 类中,在执行除法操作时,捕获 ArithmeticException 异常,并将错误消息显示在文本框中。
这些设计模式的使用让代码更具可扩展性、灵活性和可维护性。工厂模式和策略模式使得添加新的操作变得简单,可以轻松地扩展计算器的功能。监听器模式用于处理用户界面的交互,使得按钮点击事件得以处理。异常处理机制增强了代码的健壮性,能够适当地处理除以零的异常情况。
package cal1;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
interface Operation {
double performOperation(double number1, double number2) throws ArithmeticException;
}
class Addition implements Operation {
@Override
public double performOperation(double number1, double number2) {
return number1 + number2;
}
}
class Subtraction implements Operation {
@Override
public double performOperation(double number1, double number2) {
return number1 - number2;
}
}
class Multiplication implements Operation {
@Override
public double performOperation(double number1, double number2) {
return number1 * number2;
}
}
class Division implements Operation {
@Override
public double performOperation(double number1, double number2) throws ArithmeticException {
if (number2 != 0)
return number1 / number2;
else
throw new ArithmeticException("ERROR: Division by zero");
}
}
class Modulus implements Operation {
@Override
public double performOperation(double number1, double number2) {
return number1 % number2;
}
}
class SquareRoot implements Operation {
@Override
public double performOperation(double number1, double number2) {
return Math.sqrt(number1);
}
}
class Square implements Operation {
@Override
public double performOperation(double number1, double number2) {
return number2 * number2;
}
}
class Calculation {
double number1, number2; //记录运算的两个数字
Operation operation;
boolean unfinishedReading;
Frame frame = new Frame("高齐勉的计算器!");
TextField inputBox = new TextField(30);
Button[] button = new Button[20];
Calculation() {
//设置输入文本框位置
frame.setBounds(200, 200, 400, 320);
frame.add(inputBox, BorderLayout.NORTH);
//设置按钮布局
Panel panel = new Panel();
panel.setLayout(new GridLayout(5, 4, 3, 3));
//设置按钮,并将按钮加入panel
String[] s = {"sqrt", "<-", "AC", "%", "7", "8", "9", "+", "4", "5", "6", "-", "1", "2", "3", "*", "0", ".", "=", "/"};
for (int i = 0; i < s.length; i++) {
button[i] = new Button(s[i]);
button[i].addActionListener(new ActionListen());
panel.add(button[i]);
}
frame.add(panel, BorderLayout.CENTER);//将panel设置在中部区域
frame.setVisible(true);//设置窗口可见
frame.addWindowListener(new WindowAdapter() {//窗口监听器,注册监听,可以关闭窗口
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
public class ActionListen implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {//获取事件源的标签
String label = e.getActionCommand();
if (label.equals("=")) {
number2 = Double.parseDouble(inputBox.getText());
unfinishedReading = true;
try {
double result = operation.performOperation(number1, number2);
inputBox.setText(String.valueOf(result));
} catch (ArithmeticException ex) {
inputBox.setText("ERROR");
}
} else if (label.equals("+") || label.equals("*") || label.equals("/") || label.equals("%") || label.equals("sqrt")) {
number1 = Double.parseDouble(inputBox.getText());
switch (label) {
case "+":
operation = new Addition();
break;
case "-":
operation = new Subtraction();
break;
case "*":
operation = new Multiplication();
break;
case "/":
operation = new Division();
break;
case "%":
operation = new Modulus();
break;
case "sqrt":
operation = new SquareRoot();
break;
}
unfinishedReading = false;
} else if (label.equals("-")) {
if (!unfinishedReading) {
inputBox.setText("-");
unfinishedReading = true;
} else {
number1 = Double.parseDouble(inputBox.getText());
operation = new Subtraction();
unfinishedReading = false;
}
} else if (label.equals("<-")) {
String expression = inputBox.getText();
if (expression.length() != 0) {
expression = expression.substring(0, expression.length() - 1);
inputBox.setText(expression);
} else if (expression.length() == 0 && inputBox.getText().length() != 0)
// 对于计算结果后避免删除键不能清楚结果显示
inputBox.setText(expression);
} else if (label.equals("AC")) {
inputBox.setText("");
unfinishedReading = false;
} else {
String s = inputBox.getText();
if (!unfinishedReading)
inputBox.setText(label);
else
inputBox.setText(s + label);
unfinishedReading = true;
}
}
}
public static void main(String[] args) {
new Calculation();
}
}
【特别感谢】
下面的代码来自我的好基友(智子、),和前文一样,都是改进的产品,如果不懂内部逻辑,移步至简单计算器 Java图形化界面编程。
工厂模式用于封装对象的创建过程,使得代码更具灵活性和可维护性。在这个例子中,我们使用了工厂模式来创建不同的数学运算对象(Operation)。OperationFactory类充当工厂,根据给定的运算符创建相应的运算对象。通过将对象的创建委托给工厂,我们可以方便地添加新的运算类型,而无需修改主要的业务逻辑。
策略模式允许我们在运行时选择算法或行为,将其封装在独立的对象中。在这个例子中,每个数学运算(如加法、减法、乘法等)都被封装在实现了Operation接口的具体类中。通过使用策略模式,我们可以动态地切换不同的运算算法,而无需修改主要的计算器逻辑。在按钮的事件监听器中,根据用户选择的运算符,我们使用相应的运算策略对象执行计算操作。
在这个例子中,使用了监听器模式来处理按钮的点击事件。主要使用了以下几个监听器类:
NumListener(数字按钮监听器类):实现了ActionListener接口,用于处理数字按钮的点击事件。当用户点击数字按钮时,相应的数字会显示在文本框中。
OperatListener(操作符按钮监听器类):同样实现了ActionListener接口,用于处理操作符按钮的点击事件。当用户点击操作符按钮时,将当前的操作数(如果有的话)和操作符保存起来,以备后续计算使用。
EqualListener(等号按钮监听器类):同样实现了ActionListener接口,用于处理等号按钮的点击事件。当用户点击等号按钮时,根据之前保存的操作数和操作符,执行相应的数学运算,并将结果显示在文本框中。
这些监听器通过addActionListener方法将自身注册到对应的按钮上,以便在按钮被点击时接收到事件通知并执行相应的逻辑。
监听器模式允许我们将事件处理逻辑与事件源对象(例如按钮)分离,从而实现松耦合的设计。通过注册不同的监听器,我们可以为不同的按钮定义不同的行为,并且可以轻松地扩展和修改事件处理逻辑。
package calZhizi;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import static java.awt.Color.blue;
public class Calculation {
// 操作数
double x, y;
Operation operation;
boolean flag;
Frame frame = new Frame("智子的计算器!");
TextField tf = new TextField(30);
Button[] b = new Button[20];
public void init() {
// 北部区域放置文本框
frame.add(tf, BorderLayout.NORTH);
Panel panel = new Panel();
panel.setLayout(new GridLayout(4, 5, 2, 2));
// 设置按钮
String s = "+-*/%";
for (int i = 0; i < 10; i++) {// 运算数
b[i] = new Button(i + "");
b[i].setForeground(blue);
}
for (int i = 0; i < 5; i++) {// 运算符
b[i + 10] = new Button(s.charAt(i) + "");
b[i + 10].setForeground(blue);
}
String[] t = {"sqrt", "^2", "^3", "=", "."};
for (int i = 0; i < 5; i++) {
b[i + 15] = new Button(t[i]);
b[i + 15].setForeground(blue);
}
// 按钮注册监听
for (int i = 0; i < 10; i++) {// 操作数注册监听
b[i].addActionListener(new NumListener());
}
for (int i = 10; i < 18; i++) {// 操作符注册监听
if (i == 11) continue;
b[i].addActionListener(new OperatListener());
}
b[11].addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (!flag) {
tf.setText("-");
flag = true;
} else {
x = Double.parseDouble(tf.getText());
operation = OperationFactory.createOperation(e.getActionCommand());
flag = false;
}
}
});
// “=”注册监听
b[18].addActionListener(new EqualListener());
// “.”注册监听
b[19].addActionListener(new NumListener());
// 将按钮加入panel
for (int i = 0; i < 20; i++) {
panel.add(b[i]);
}
// 设置中部按钮
frame.add(panel);
// 窗口监听器 注册监听
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
// 设置窗口最优并可见
frame.pack();
frame.setVisible(true);
}
// 数字按钮监听器类
public class NumListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
String t = e.getActionCommand();
String s = tf.getText();
if (flag == false)
tf.setText(t);
else
tf.setText(s + t);
flag = true;
}
}
// 操作符按钮监听器类
public class OperatListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
x = Double.parseDouble(tf.getText());
operation = OperationFactory.createOperation(e.getActionCommand());
flag = false;
}
}
// 等号按钮监听器类
public class EqualListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
y = Double.parseDouble(tf.getText());
flag = true;
if (operation != null) {
double result = operation.calculate(x, y);
tf.setText(String.valueOf(result));
}
}
}
public static void main(String[] args) {
new Calculation().init();
}
}
interface Operation {
double calculate(double x, double y);
}
class Addition implements Operation {
@Override
public double calculate(double x, double y) {
return x + y;
}
}
class Subtraction implements Operation {
@Override
public double calculate(double x, double y) {
return x - y;
}
}
class Multiplication implements Operation {
@Override
public double calculate(double x, double y) {
return x * y;
}
}
class Division implements Operation {
@Override
public double calculate(double x, double y) {
if (y != 0)
return x / y;
else
return Double.POSITIVE_INFINITY;
}
}
class Modulo implements Operation {
@Override
public double calculate(double x, double y) {
return x % y;
}
}
class SquareRoot implements Operation {
@Override
public double calculate(double x, double y) {
return Math.sqrt(x);
}
}
class Square implements Operation {
@Override
public double calculate(double x, double y) {
return x * x;
}
}
class Cube implements Operation {
@Override
public double calculate(double x, double y) {
return x * x * x;
}
}
class OperationFactory {
public static Operation createOperation(String operator) {
switch (operator) {
case "+":
return new Addition();
case "-":
return new Subtraction();
case "*":
return new Multiplication();
case "/":
return new Division();
case "%":
return new Modulo();
case "sqrt":
return new SquareRoot();
case "^2":
return new Square();
case "^3":
return new Cube();
default:
throw new IllegalArgumentException("Invalid operator: " + operator);
}
}
}