• 简单工厂模式实现简易计算器


    简单工厂模式实现简易计算器(基于Java语言)

    最近在学习设计模式,之前虽然也有学习过,但总是无法领悟其中奥妙,现在主要是利用学习的设计模式来实现一些东西加深了解。

    这里采用简单工厂模式实现了一个简易的计算器。


    简述

    这里简单讲一下我自己对于简单工厂模式的理解,简单工厂模式的核心在类的,创建一个所有产品类的父类或父接口,所有的产品类都需要继承或实现父类或父接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。

    关于简单工厂模式我这里就不详述了,给个链接,有兴趣的可以看一下:https://www.runoob.com/design-pattern/factory-pattern.html


    这里来看一下项目的UML图:

    这里Operation是所有运算类的父类,在Operation中封装了两个运算数,以及运算得到结果的虚方法,在子类中得到实现。

    OperationFactory是运算工厂类,当需要进行运算时,就得这里面去请求,根据输入来让Operation实例为相应的子类。

    Main类为界面类,这里将界面和运算逻辑进行解耦。

    项目结构:

    这里依次贴一下代码:

    Main:

    package FactoryMethodPattern;
    
    /*
    创建人:czc
    创建时间:2019/12/16
    创建用途:简单工厂模式实现计算器--主界面
     */
    
    import javax.swing.*;
    import javax.swing.border.BevelBorder;
    import java.awt.*;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    
    public class Main {
    
        private static Operation operation;
    
    
        private JFrame frame=new JFrame("简单工厂模式实现计算器");
        private JPanel panel_show=new JPanel();         //显示面板
        private JMenuBar menuBar=new JMenuBar();
        private JMenu menu1=new JMenu("帮助");
        private JLabel label_hint=new JLabel();    //提示信息标签
        private JLabel label_input=new JLabel();   //输入信息标签
        private JLabel label_result=new JLabel();  //输出结果标签
        private JPanel panel_button=new JPanel();  //按钮面板
    
        private final String[] str={"AC","←","²","÷","7","8","9","×","4","5","6","-","1","2","3","+","%","0",".","="};
        private JButton[] buttons=new JButton[str.length];
    
        private static double numberA=0;
        private static double numberB=0;
        private static double result=0;
        private boolean flag=true;                         //记录是否是第一次计算
        private boolean resultIsChange=false;              //判断结果框是否需要更改
        private boolean turn=true;                         //判断当前需要赋值给numberA还是numberB,true为A,false为B
    
    
        private static boolean hasOperation=true;          //判断之前是否已经存在操作符
        private static int index=0;                        //记录最后一个操作符位置
    
        //界面初始化
        private void initJFrame(){
            Container container=frame.getContentPane();
            frame.setSize(600,500);
    
            //设置窗口居中显示
            frame.setLocationRelativeTo(null);
    
            //设置菜单栏
            menu1.setFont(new Font("",Font.BOLD,20));
            menuBar.add(menu1);
            frame.setJMenuBar(menuBar);
    
            //设置提示信息标签
            label_hint.setText(" ");
            label_hint.setHorizontalAlignment(JLabel.RIGHT);
            label_hint.setFont(new Font("宋体",Font.BOLD,30));
            label_hint.setForeground(Color.RED);
    
            //设置输入标签
            label_input.setText(" ");
            label_input.setHorizontalAlignment(JLabel.RIGHT);
            label_input.setFont(new Font("宋体",Font.BOLD,30));
            label_input.setForeground(Color.BLACK);
    
            //设置结果标签
            label_result.setText("0");
            label_result.setHorizontalAlignment(JLabel.RIGHT);
            label_result.setFont(new Font("宋体",Font.BOLD,35));
            label_result.setForeground(Color.BLUE);
    
            panel_show.setLayout(new BorderLayout());
            panel_show.add(label_hint,BorderLayout.NORTH);
            panel_show.add(label_input,BorderLayout.CENTER);
            panel_show.add(label_result,BorderLayout.SOUTH);
    
            // 创建具有指定类型、高亮显示和阴影颜色的斜面边框。
            panel_show.setBorder(new BevelBorder(BevelBorder.RAISED, new Color(160, 170, 180), null, SystemColor.scrollbar, null));
    
            panel_button.setLayout(new GridLayout(5, 4, 8, 8));// 按键设置为网格布局5行5列间距为8
            // 创建具有指定类型、高亮显示和阴影颜色的斜面边框。凸出斜面类型。为滚动条提供的背景色。
            panel_button.setBorder(new BevelBorder(BevelBorder.RAISED, new Color(160, 170, 180), null, SystemColor.scrollbar, null));
    
            //添加按钮
            for(int i=0;i<str.length;i++){
                buttons[i]=new JButton(str[i]);
                buttons[i].setFont(new Font("宋体",Font.BOLD,30));
    
                buttons[i].addActionListener(new MyActionListener());  //为每个按钮添加事件监听器
    
    
                panel_button.add(buttons[i]);// 把每个按钮分别添加到面板上
    
            }
    
            //把面板添加进窗体框架里
            frame.add(panel_show,BorderLayout.NORTH);
            frame.add(panel_button,BorderLayout.CENTER);
            frame.setVisible(true);
            frame.setDefaultCloseOperation(frame.DISPOSE_ON_CLOSE);
        }
    
        public static void main(String[] args){
            new Main().initJFrame();
        }
    
    
    
        private class MyActionListener implements ActionListener{
    
            @Override
            public void actionPerformed(ActionEvent actionEvent) {
                String str=actionEvent.getActionCommand();        //得到触发事件相关的命令字符串
                switch (str){
                    case "AC":
                        //清屏操作
                        clear();
                        break;
    
                    case "←":
                        //回退操作修改输入标签
                        String s=label_input.getText();
                        if(s.length()>1){
                            label_input.setText(s.substring(0,s.length()-1));
                        }else{
                            numberA=0;
                            numberB=0;
                            label_input.setText(" ");
                            label_result.setText("0");
                        }
    
                        //回退操作修改操作符
                        System.out.println(s.length());
                        System.out.println(index);
    
                        if(s.length()==2){
                            label_result.setText("0");
                            break;
                        }
    
                        if(s.length()==(index+2)){
                            numberB=0;
                            label_result.setText(""+numberA);
                            break;
                        }
    
                        if(s.length()==(index+1)){
                            index=0;
                            operation=null;
                            break;
                        }
    
                        //回退操作修改numberA、B以及结果标签
                        if(index==0){
    
                            numberA=numberA/10;
                            label_result.setText(""+numberA);
                        }else{
                            numberB=numberB/10;
                            label_result.setText(""+numberB);
                        }
                        break;
    
    
                    case "²":
                        //平方操作
                        labelInputAppend(str);
                        double d=Double.parseDouble(label_result.getText());
                        label_result.setText(""+d*d);
                        if(turn){
                            numberA=Double.parseDouble(label_result.getText());
                        }else{
                            numberB=Double.parseDouble(label_result.getText());
                        }
                        break;
    
                    case "÷":
                        //除法操作
                        common(str);
                        operation=OperatorFactory.createOperate("÷");
                        resultIsChange=false;
                        break;
    
                    case "×":
                        common(str);
                        operation=OperatorFactory.createOperate("×");
                        resultIsChange=false;
                        break;
    
                    case "-":
                        common(str);
                        operation=OperatorFactory.createOperate("-");
                        resultIsChange=false;
                        break;
    
                    case "+":
                        common(str);
                        operation=OperatorFactory.createOperate("+");
                        resultIsChange=false;
                        break;
    
                    case "%":
                        common(str);
                        operation=OperatorFactory.createOperate("%");
                        resultIsChange=false;
                        break;
    
                    case ".":
                        labelInputAppend(str);
                        lableResultAppend(str);
                        break;
    
                    case "=":
                        //进行计算
                        turn=true;
    
                        //如果没有按下操作符就按下=
                        if(operation==null){
                            label_result.setText(""+numberA);
                            break;
                        }
    
                        //当进行除法和模操作时,判断numberB是否为0
                        Object obj=operation.getClass();
                        System.out.println(obj);
                        if(obj.equals(OperationDiv.class)||obj.equals(OperationMod.class)){
                            if(numberB==0.0){
                                label_hint.setText("除数不能为0!");
                                break;
                            }
                        }
    
                        operation.setNumberA(numberA);
                        operation.setNumberB(numberB);
                        try {
                            result=operation.getResult();
                        } catch (Exception e) {
                            label_hint.setText("抱歉,程序出现错误!");
                            result=0;
                            e.printStackTrace();
                        }
                        label_result.setText(""+result);
                        hasOperation=true;
                        flag=false;  //非第一次计算
                        break;
    
                    default:
                        //所有数字按键进行相同操作
                        labelInputAppend(str);
                        if(!resultIsChange){
                            label_result.setText(str);
                        }else{
                            lableResultAppend(str);
                        }
                        resultIsChange=true;
    
                        if(turn){
                            numberA=Double.parseDouble(label_result.getText());
                        }else{
                            numberB=Double.parseDouble(label_result.getText());
                        }
    
                        break;
                }
            }
        }
    
    
        //清屏
        private void clear(){
            label_hint.setText(" ");
            label_input.setText(" ");
            label_result.setText("0");
            numberA=0;
            numberB=0;
            result=0;
            turn=true;
            Main.this.flag=true;
            hasOperation=true;
            resultIsChange=false;
        }
    
    
        //在输入框中添加字符串
        private void labelInputAppend(String s){
            label_input.setText(label_input.getText()+s);
        }
        
        //在结果框之添加字符串
        private void lableResultAppend(String s){
            label_result.setText(label_result.getText()+s);
        }
    
    
        //包装相同操作
        private void common(String str){
            turn=false;
            if(flag){
                if(hasOperation){
                    labelInputAppend(str);
                    index=label_input.getText().length()-1;
                    hasOperation=false;
                }else{
                    label_input.setText(label_input.getText().substring(0,label_input.getText().length()-1)+str);
                }
            }else{
                numberA=Double.parseDouble(label_result.getText());
                if(hasOperation){
                    labelInputAppend(str);
                    index=label_input.getText().length()-1;
                    hasOperation=false;
                }else{
                    label_input.setText(label_input.getText().substring(0,label_input.getText().length()-1)+str);
                }
            }
        }
    }

     Operation:

    package FactoryMethodPattern;
    
    /*
    创建人:czc
    创建时间:2019/12/16
    创建用途:简单工厂模式实现计算器--运算父类
     */
    
    public abstract class Operation {
        private double numberA=0;
    
        private double numberB=0;
    
        public double getNumberA() {
            return numberA;
        }
    
        public void setNumberA(double numberA) {
            this.numberA = numberA;
        }
    
        public double getNumberB() {
            return numberB;
        }
    
        public void setNumberB(double numberB) {
            this.numberB = numberB;
        }
    
        public abstract double getResult() throws Exception;
    }

     

     OperationAdd:

    package FactoryMethodPattern;
    
    /*
    创建人:czc
    创建时间:2019/12/16
    创建用途:简单工厂模式实现计算器--运算符+
     */
    
    public class OperationAdd extends Operation{
    
        @Override
        public double getResult() {
            double result=0;
            result=getNumberA()+getNumberB();
            return result;
        }
    }

     OperationDiv:

    package FactoryMethodPattern;
    
    /*
    创建人:czc
    创建时间:2019/12/16
    创建用途:简单工厂模式实现计算器--运算符/
     */
    
    public class OperationDiv extends Operation{
        @Override
        public double getResult() throws Exception {
            if(getNumberB()==0){
                throw new Exception("除数不能为0!");
            }
            double result=0;
            result=getNumberA()/getNumberB();
            return result;
        }
    }

     OperationMod:

    package FactoryMethodPattern;
    /*
    创建人:czc
    创建时间:2019/12/16
    创建用途:简单工厂模式实现计算器--运算符%
    */

    public class OperationMod extends Operation {
        @Override
        public double getResult() throws Exception {
            double result=0;
            result=getNumberA()%getNumberB();
            return result;
        }
    }

     OperationMul:

    package FactoryMethodPattern;
    
    /*
    创建人:czc
    创建时间:2019/12/16
    创建用途:简单工厂模式实现计算器--运算符*
     */
    
    public class OperationMul extends Operation{
        @Override
        public double getResult() {
            double result=0;
            result=getNumberA()*getNumberB();
            return result;
        }
    }

    OperationSub:

    package FactoryMethodPattern;
    
    /*
    创建人:czc
    创建时间:2019/12/16
    创建用途:简单工厂模式实现计算器--运算符-
     */
    
    public class OperationSub extends Operation{
        @Override
        public double getResult() {
            double result=0;
            result=getNumberA()-getNumberB();
            return result;
        }
    }

    OperationFactory:

    package FactoryMethodPattern;
    
    /*
    创建人:czc
    创建时间:2019/12/16
    创建用途:简单工厂模式实现计算器--运算符工厂
     */
    
    abstract class OperatorFactory {
        static Operation createOperate(String operate){
            Operation oper=null;
            switch (operate){
                case "+":
                    oper=new OperationAdd();
                    break;
    
                case "-":
                    oper=new OperationSub();
                    break;
    
                case "×":
                    oper=new OperationMul();
                    break;
    
                case "÷":
                    oper=new OperationDiv();
                    break;
    
                case "%":
                    oper=new OperationMod();
                    break;
    
                default:
                    break;
    
            }
            return oper;
        }
    }

     运行截图:

    总的代码就在上面了,其实是主界面占的代码量比较多,简单工厂模式核心的代码就是下面这些父类子类和一个工厂类。

     这个程序并不够健壮,如有错误还请指出,感谢。


    总结

    总的来说通过继承和多态,降低了程序之间的耦合度,使程序更加灵活,容易修改扩展,并且易于复用。

    当然这里简单工厂模式的缺点也很明显,每增加一个运算,就要去增加子类,增加工厂类里的分支。

    简单工厂模式主要也应用于业务场景较少,更改较少的情况下。

    吾生也有涯,而知也无涯。

  • 相关阅读:
    linux下telnet安装与使用
    用日志记录Linux用户执行的每一条命令(history)
    监视网络接口TCP状态信息数据有多种工具或命令。下面举例一些:
    [C#]Winform后台提交数据且获取远程接口返回的XML数据,转换成DataSet
    C#生成Code128码
    BULK INSERT如何将大量数据高效地导入SQL Server
    SQLite中的时间日期函数
    C# winform小票打印
    c#读写txt文件
    C#-WinForm 串口通信
  • 原文地址:https://www.cnblogs.com/hzauxx/p/12513609.html
Copyright © 2020-2023  润新知