在 java swing 应用程序中分离 GUI 和逻辑代码

Separating GUI and Logic code in a java swing app

我试图将以下代码的逻辑和 UI 设计分离到它们自己的 class 中,但我无法弄清楚如何调用链接到 swing 组件的某些方法我的 GUI class 在 Controller class.

我的问题是,当我在控制器 class 中创建 GUI class 的实例时,G[=25= 中的 JRadioButtons class 变量]只在GUI中的createRBButtonsPanel()方法中初始化。当我尝试调用控制器的 actionPerformed 方法中的 cokeRb.getText() 方法时,这会给我一个 NullPointerException,因为我没有调用导致它们被初始化的事件链。

我试图避免将它们全部设置为静态,因为我确信这样做不是最佳做法。

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class GUI {
    private CoinAcceptor coinSlot = new CoinAcceptor();
    private VMController controller;
    
    GUI(VMController controller) {
        this.controller = controller;
    }

    private JRadioButton cokeRb, lemonadeRb, tangoRb, waterRb, pepsiRb, spriteRb;
    private JButton purchaseBtn , clearBtn, cancelBtn, loyaltyCardBTN;
    private JTextField moneyRemainingTf, balanceTf;
    

    private GridBagConstraints c = new GridBagConstraints();

//// Getters /////////////////////////////////
    public String getMoneyTFText() { return this.moneyRemainingTf.getText(); }
    public String getBalanceTF() { return balanceTf.getText(); }
    public String getCokeRbText() { return this.cokeRb.getText(); }
    public String getTangoRbText() { return this.tangoRb.getText(); }
    public String getLemonadeRbText() { return this.lemonadeRb.getText(); }
    public String getWaterRbText() { return this.waterRb.getText(); }
    public String getPepsiRbText() { return this.pepsiRb.getText(); }
    public String getSpriteRbText() { return this.spriteRb.getText(); }

//// Setters /////////////////////////////////
    public void setBalanceTF(String text) { balanceTf.setText(text); }
    public void setCokeRbText(String text) { this.cokeRb.setText(text); }
    public void setLemonadeRbText(String text) { this.lemonadeRb.setText(text); }
    public void setTangoRbText(String text) { this.tangoRb.setText(text); }
    public void setWaterRbText(String text) { this.waterRb.setText(text); }
    public void setPepsiRbText(String text) { this.pepsiRb.setText(text);}
    public void setSpriteRbText(String text) { this.spriteRb.setText(text); }
    
    
    
    public void deselectRadioButtons(String button) {
        switch (button) {
        case "COKE":
            this.cokeRb.setSelected(true);
            this.lemonadeRb.setSelected(false);
            this.tangoRb.setSelected(false);
            this.waterRb.setSelected(false);
            this.pepsiRb.setSelected(false);
            this.spriteRb.setSelected(false);
            break;
        case "LEMONADE":
            this.cokeRb.setSelected(false);
            this.lemonadeRb.setSelected(true);
            this.tangoRb.setSelected(false);
            this.waterRb.setSelected(false);
            this.pepsiRb.setSelected(false);
            this.spriteRb.setSelected(false);
            break;
        case "TANGO":
            this.lemonadeRb.setSelected(false);
            this.cokeRb.setSelected(false);
            this.tangoRb.setSelected(true);
            this.waterRb.setSelected(false);
            this.pepsiRb.setSelected(false);
            this.spriteRb.setSelected(false);
            break;
        case "WATER":
            this.lemonadeRb.setSelected(false);
            this.tangoRb.setSelected(false);
            this.cokeRb.setSelected(false);
            this.waterRb.setSelected(true);
            this.pepsiRb.setSelected(false);
            this.spriteRb.setSelected(false);
            break;
        case "PEPSI":
            this.lemonadeRb.setSelected(false);
            this.tangoRb.setSelected(false);
            this.waterRb.setSelected(false);
            this.cokeRb.setSelected(false);
            this.pepsiRb.setSelected(true);
            this.spriteRb.setSelected(false);
            break;
        case "SPRITE":
            this.lemonadeRb.setSelected(false);
            this.tangoRb.setSelected(false);
            this.waterRb.setSelected(false);
            this.pepsiRb.setSelected(false);
            this.cokeRb.setSelected(false);
            this.spriteRb.setSelected(true);
            break;
        default:
            this.lemonadeRb.setSelected(false);
            this.tangoRb.setSelected(false);
            this.waterRb.setSelected(false);
            this.pepsiRb.setSelected(false);
            this.cokeRb.setSelected(false);
            this.spriteRb.setSelected(false);
            break;
        }
    }

    public void clearAllFields() {
        deselectRadioButtons("");
        balanceTf.setText("");
        this.moneyRemainingTf.setText("");
    }

    public boolean isRBSelected() {
        JRadioButton[] radioButtons = new JRadioButton[] { cokeRb, lemonadeRb, tangoRb, waterRb, pepsiRb, spriteRb };
        for (JRadioButton button : radioButtons) {
            if (button.isSelected())
                return true;
        }
        return false;
    }

    private JPanel createRBButtonsPanel() {
        JPanel panel = new JPanel();
        panel.setLayout(new GridLayout(3, 6, 5, 5));
        panel.setBorder(BorderFactory.createTitledBorder("Select and item"));

        cokeRb = new JRadioButton("Coke : £1.50");
        cokeRb.addActionListener(controller);
        cokeRb.setActionCommand("COKE");

        lemonadeRb = new JRadioButton("Lemonade : £1.20");
        lemonadeRb.addActionListener(controller);
        lemonadeRb.setActionCommand("LEMONADE");

        tangoRb = new JRadioButton("Tango : £1.40");
        tangoRb.addActionListener(controller);
        tangoRb.setActionCommand("TANGO");

        waterRb = new JRadioButton("Water : £1");
        waterRb.addActionListener(controller);
        waterRb.setActionCommand("WATER");

        pepsiRb = new JRadioButton("Pepsi : £1.30");
        pepsiRb.addActionListener(controller);
        pepsiRb.setActionCommand("PEPSI");

        spriteRb = new JRadioButton("Sprite : £1.20");
        spriteRb.addActionListener(controller);
        spriteRb.setActionCommand("SPRITE");

        purchaseBtn = new JButton("PURCHASE");
        purchaseBtn.addActionListener(controller);

        clearBtn = new JButton("CLEAR");
        clearBtn.addActionListener(controller);

        cancelBtn = new JButton("CANCEL");
        cancelBtn.addActionListener(controller);

        panel.add(cokeRb);
        panel.add(lemonadeRb);
        panel.add(tangoRb);
        panel.add(waterRb);
        panel.add(pepsiRb);
        panel.add(spriteRb);
        panel.add(purchaseBtn);
        panel.add(clearBtn);
        panel.add(cancelBtn);

        c.gridx = 0;
        c.gridy = 0;
        c.insets = new Insets(10, 10, 10, 10);

        return panel;
    }

    private JPanel createInputPanel() {
        JPanel panel = new JPanel();
        panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
        balanceTf = new JTextField();
//      balanceTf.setForeground(Color.gray);
//      balanceTf.addFocusListener(new FocusListener() {
//
//          @Override
//          public void focusGained(FocusEvent e) {
//              if (balanceTf.getText().equals("2.50")) {
//                  balanceTf.setText("");
//                  balanceTf.setForeground(Color.black);
//              }
//          }
//
//          @Override
//          public void focusLost(FocusEvent e) {
//              if (balanceTf.getText().isEmpty()) {
//                  balanceTf.setText("2.50");
//                  balanceTf.setForeground(Color.gray);
//              }
//          }
//      });
        moneyRemainingTf = new JTextField();
        moneyRemainingTf.setEditable(false);
        loyaltyCardBTN = new JButton("Scan Loyalty Card");
        
        loyaltyCardBTN.addActionListener(controller);
        loyaltyCardBTN.setActionCommand("SCAN-CARD");

        panel.add(new JLabel("Cash"));
        panel.add(balanceTf);
        panel.add(new JLabel("Remaining Balance"));
        panel.add(moneyRemainingTf);
        panel.add(loyaltyCardBTN);

        c.gridx = 1;
        c.gridy = 0;

        return panel;
    }

    private JPanel coinKeypad() {
        JPanel panel = new JPanel();
        panel.setBorder(BorderFactory.createTitledBorder("Coins"));
        panel.setLayout(new GridLayout(3, 2, 5, 5));

        JButton button = new JButton("5p");
        button.addActionListener(e -> {
            
            coinSlot.depositCoin(0.05);
            balanceTf.setText(String.valueOf(coinSlot.getCoinsValue()));
        });
        panel.add(button);

        button = new JButton("10p");
        button.addActionListener(e -> {
            coinSlot.depositCoin(0.10);
            balanceTf.setText(String.valueOf(coinSlot.getCoinsValue()));
        });
        panel.add(button);

        button = new JButton("20p");
        button.addActionListener(e -> {
            coinSlot.depositCoin(0.20);
            balanceTf.setText(String.valueOf(coinSlot.getCoinsValue()));
        });
        panel.add(button);

        button = new JButton("50p");
        button.addActionListener(e -> {
            coinSlot.depositCoin(0.50);
            balanceTf.setText(String.valueOf(coinSlot.getCoinsValue()));
        });
        panel.add(button);

        button = new JButton("£1");
        button.addActionListener(e -> {
            coinSlot.depositCoin(1);
            balanceTf.setText(String.valueOf(coinSlot.getCoinsValue()));
        });
        panel.add(button);

        button = new JButton("£2");
        button.addActionListener(e -> {
            coinSlot.depositCoin(2);
            balanceTf.setText(String.valueOf(coinSlot.getCoinsValue()));
        });
        panel.add(button);

        c.gridx = 0;
        c.gridwidth = 2;
        c.fill = GridBagConstraints.HORIZONTAL;
        c.gridy = 1;
        return panel;
    }

    private JPanel createBody() {
        JPanel panel = new JPanel();
        panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
        panel.setLayout(new GridBagLayout());
        panel.add(createRBButtonsPanel(), c);
        panel.add(createInputPanel(), c);
        panel.add(coinKeypad(), c);
        return panel;
    }

    private JPanel createHeader() {
        JPanel panel = new JPanel();
        JLabel label = new JLabel("Vending Machine");
        label.setFont(new Font("Helvetica Neue", 3, 48));
        panel.add(label);
        return panel;
    }

    private void addComponentsToPane(Container pane) {
        JPanel header = createHeader();
        JPanel body = createBody();
        pane.add(header, BorderLayout.NORTH);
        pane.add(body, BorderLayout.CENTER);
    }

    private void setLookAndFeel() {
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException
                | UnsupportedLookAndFeelException e) {
            e.printStackTrace();
        }
    }

    public void createAndShowGUI() {
        JFrame frame = new JFrame("Vending Machine with a Four Dillabyte Crossfade");
        addComponentsToPane(frame.getContentPane());
        frame.setSize(800, 500);
        frame.setResizable(false);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        setLookAndFeel();
        frame.setVisible(true);
        frame.pack();
    }
    
}
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JOptionPane;

public class VMController implements ActionListener {
    private PaymentHandler handler = new PaymentHandler();
    private double balance;
    private String selectedRBText;
    private GUI gui = new GUI(this);
    
    VMController() {
        this.balance = 0;
    }

    private double balanceToDouble() {
        double balance = 0;
        try {
            return Double.valueOf(gui.getBalanceTF());
        } catch (NumberFormatException ex) {
            JOptionPane.showMessageDialog(null, "Invalid coin deposit.", "Enter numerical amount",
                    JOptionPane.ERROR_MESSAGE);
            return balance;
        }
    }

    private double productPriceToDouble() {
        double productPrice = 0;
        try {
            return Double.valueOf(selectedRBText);
        } catch (NullPointerException ex) {
            return productPrice;
        }
    }
    
    
    @Override
    public void actionPerformed(ActionEvent e) {

        String action = e.getActionCommand();
        switch (action) {
        case "COKE":
            gui.deselectRadioButtons("COKE");
            selectedRBText = gui.getCokeRbText().substring(gui.getCokeRbText().indexOf('£') + 1);
            break;
        case "LEMONADE":
            gui.deselectRadioButtons("LEMONADE");
            selectedRBText = gui.getLemonadeRbText().substring(gui.getLemonadeRbText().indexOf('£') + 1);
            break;
        case "TANGO":
            gui.deselectRadioButtons("TANGO");
            selectedRBText = gui.getTangoRbText().substring(gui.getTangoRbText().indexOf('£') + 1);
            break;
        case "WATER":
            gui.deselectRadioButtons("WATER");
            selectedRBText = gui.getWaterRbText().substring(gui.getWaterRbText().indexOf('£') + 1);
            break;
        case "PEPSI":
            gui.deselectRadioButtons("PEPSI");
            selectedRBText = gui.getPepsiRbText().substring(gui.getPepsiRbText().indexOf('£') + 1);
            break;
        case "SPRITE":
            gui.deselectRadioButtons("SPRITE");
            selectedRBText = gui.getSpriteRbText().substring(gui.getSpriteRbText().indexOf('£') + 1);
            break;
        case "PURCHASE":
            if (!gui.isRBSelected())
                JOptionPane.showMessageDialog(null, "Choose a product to purchase", "Select a product",
                        JOptionPane.ERROR_MESSAGE);
            else {
                if (handler.handlePayment(balanceToDouble(), productPriceToDouble()))
                    gui.setBalanceTF(String.valueOf(handler.getBalance()));
                else
                    JOptionPane.showMessageDialog(null, "Balance is insufficient for product purchase.",
                            "Insufficient Funds", JOptionPane.ERROR_MESSAGE);
            }
            break;
        case "CANCEL":
            if (handler.getBalance() > 0) {
                JOptionPane.showMessageDialog(null, "Order Cancelled.\nChange dispensed.\n£" + handler.getBalance());
            }
            JOptionPane.showMessageDialog(null, "Order Cancelled.");
            System.exit(0);

            break;
        case "CLEAR":
            gui.clearAllFields();
            break;
        case "SCAN-CARD":
            System.out.println("scan card");
            break;
        default:
            System.out.println("Action command not defined - \"" + action + "\"");
            break;
        }

    }
}


简介

我将您的代码复制到我的 Eclipse IDE。缺少 class,所以我看不到您的 GUI 是什么样子。

所以我创建了这个 GUI。

我离开了会员卡按钮。

说明

Oracle 有一个有用的教程,Creating a GUI With Swing。跳过使用 NetBeans 学习 Swing IDE 部分。

我在创建 Swing 应用程序时使用 model-view-controller (MVC) 模式。顾名思义,您首先创建模型,然后是视图,然后是控制器。

应用程序模型由一个或多个普通Java getter/setter classes.

该视图由一个 JFrame、一个或多个 JPanels 和 Swing 组件组成。

每个 ActionActionListener class 组成控制器。通常没有一个控制器可以“一统天下”。

型号

我创建的第一个模型 class 是 Item class。 Item class 包含名称和价格。价格以便士指定。使用 int 字段保存价格使计算更容易。我在显示价格时将便士换算成英镑。

我创建的第二个模型 class 是 VendingMachineModel class。 VendingMachineModel class 包含 java.util.List 项、java.util.List 硬币、int 余额字段和 int 更改字段。

查看

您的观点易于理解且结构合理,因此我在这里没有太多评论。我使用 ButtonGroupJRadioButtons 限制为一个选择。

不要将所有 Swing 组件设为 class 字段。这会让您的代码的读者感到困惑。 Class 字段只能用于不止一种方法需要的字段。

在 class 中从最重要的方法到最不重要的方法对您的方法进行排序。这使代码更易于人们阅读和理解。

控制器

除了购买按钮,我对所有 JButtons 使用了 lambda 表达式。在我看来,ActionPerformed 方法对于 lambda 表达式来说太大了,所以我创建了一个 PurchaseListener class.

代码

这是完整的可运行代码。我在 classes 内部制作了额外的 classes 这样我就可以 post 代码作为一个块。

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.ButtonModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

public class VendingMachineExample implements Runnable {
    
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new VendingMachineExample());
    }
    
    private ButtonGroup buttonGroup;
    
    private JFrame frame;
    
    private JTextField balanceField, changeField;
    
    private final VendingMachineModel model;
    
    public VendingMachineExample() {
        this.model = new VendingMachineModel();
    }

    @Override
    public void run() {
        frame = new JFrame("Vending Machine with a Four Dillabyte Crossfade");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        frame.add(createHeaderPanel(), BorderLayout.NORTH);
        frame.add(createBodyPanel(), BorderLayout.CENTER);
        
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }
    
    private JPanel createHeaderPanel() {
        JPanel panel = new JPanel();
        panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
        
        JLabel label = new JLabel("Vending Machine");
        label.setFont(new Font("Helvetica Neue", 3, 48));
        panel.add(label);
        
        return panel;
    }
    
    private JPanel createBodyPanel() {
        JPanel panel = new JPanel();
        panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
        panel.setLayout(new FlowLayout());
        
        panel.add(createVendingPanel());
        panel.add(createDisplayPanel());
        panel.add(createCoinKeypad());
        
        return panel;
    }

    
    private JPanel createVendingPanel() {
        JPanel panel = new JPanel();
        panel.setLayout(new GridLayout(0, 3, 5, 5));
        panel.setBorder(BorderFactory.createTitledBorder("Select an item"));
        
        buttonGroup = new ButtonGroup();
        for (Item item : model.getItems()) {
            double price = 0.01 * item.getPrice();
            String text = item.getName() + ": £" + String.format("%.2f", price);
            JRadioButton button = new JRadioButton(text);
            text = item.getName() + ";;;" + item.getPrice();
            button.setActionCommand(text);
            buttonGroup.add(button);
            panel.add(button);
        }
        
        JButton button = new JButton("Purchase");
        button.addActionListener(new PurchaseListener(this, model));
        panel.add(button);
        
        button = new JButton("Clear");
        button.addActionListener(event -> {
            buttonGroup.clearSelection();
        });
        panel.add(button);
        
        button = new JButton("Cancel");
        button.addActionListener(event -> {
            buttonGroup.clearSelection();
            int amount = model.getBalance();
            model.setBalance(0);
            model.setChange(amount);
            updateDisplayPanel();
        });
        panel.add(button);
        
        return panel;
    }
    
    private JPanel createDisplayPanel() {
        JPanel panel = new JPanel();
        panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
        
        panel.add(new JLabel("Cash"));
        balanceField = new JTextField(10);
        balanceField.setEditable(false);
        balanceField.setHorizontalAlignment(JTextField.CENTER);
        panel.add(balanceField);
       
        panel.add(new JLabel("Change"));
        changeField = new JTextField(10);
        changeField.setEditable(false);
        changeField.setHorizontalAlignment(JTextField.CENTER);
        panel.add(changeField);
        
        updateDisplayPanel();
        return panel;
    }
    
    public void updateDisplayPanel() {
        double amount = 0.01 * model.getBalance();
        String text = "£" + String.format("%.2f", amount);
        balanceField.setText(text);
        
        amount = 0.01 * model.getChange();
        text = "£" + String.format("%.2f", amount);
        changeField.setText(text);
    }
    
    private JPanel createCoinKeypad() {
        JPanel panel = new JPanel();
        panel.setBorder(BorderFactory.createTitledBorder("Coins"));
        panel.setLayout(new GridLayout(0, 2, 5, 5));
        
        for (Item item : model.getCoins()) {
            JButton button = new JButton(item.getName());
            button.setActionCommand(Integer.toString(item.getPrice()));
            button.addActionListener(event -> {
                model.setChange(0);
                model.addCoin(item.getPrice());
                updateDisplayPanel();
            });
            panel.add(button);
        }
        
        return panel;
    }
    
    public ButtonGroup getButtonGroup() {
        return buttonGroup;
    }

    public JFrame getFrame() {
        return frame;
    }

    public class PurchaseListener implements ActionListener {
        
        private final VendingMachineExample view;
        
        private final VendingMachineModel model;

        public PurchaseListener(VendingMachineExample view, VendingMachineModel model) {
            this.view = view;
            this.model = model;
        }

        @Override
        public void actionPerformed(ActionEvent event) {
            ButtonModel buttonModel = view.getButtonGroup().getSelection();
            if (buttonModel == null) {
                JOptionPane.showMessageDialog(view.getFrame(), 
                        "Please select an item", "Select an item",
                        JOptionPane.ERROR_MESSAGE);
            } else {
                String text = buttonModel.getActionCommand();
                String[] parts = text.split(";;;");
                String name = parts[0];
                int amount = Integer.valueOf(parts[1]);
                int balance = model.getBalance();
                
                if (balance >= amount) {
                    displayPurchaseMessage(name, amount, balance);
                } else {
                    displayDifferenceMessage(amount, balance);
                }
            }
        }

        private void displayPurchaseMessage(String name, int amount, int balance) {
            String text;
            text = "You purchased a " + name;
            JOptionPane.showMessageDialog(view.getFrame(), text, "Item purchased",
                    JOptionPane.INFORMATION_MESSAGE);
            model.purchaseProduct(amount);
            int change = balance - amount;
            model.setBalance(0);;
            model.setChange(change);
            view.updateDisplayPanel();
            view.getButtonGroup().clearSelection();
        }

        private void displayDifferenceMessage(int amount, int balance) {
            String text;
            int difference = amount - balance;
            double price = 0.01 * difference;
            text = "Please deposit an additional £" + 
                    String.format("%.2f", price);
            JOptionPane.showMessageDialog(view.getFrame(), text, "Add Coins",
                    JOptionPane.ERROR_MESSAGE);
        }
        
    }
    
    public class VendingMachineModel {
        
        private int balance, change;
        
        private final List<Item> coins, items;
        
        public VendingMachineModel() {
            this.balance = 0;
            this.change = 0;
            
            this.coins = new ArrayList<>();
            this.coins.add(new Item("5p", 5));
            this.coins.add(new Item("10p", 10));
            this.coins.add(new Item("20p", 20));
            this.coins.add(new Item("50p", 50));
            this.coins.add(new Item("£1", 100));
            this.coins.add(new Item("£2", 200));
            
            this.items = new ArrayList<>();
            this.items.add(new Item("Coke", 150));
            this.items.add(new Item("Lemonade", 120));
            this.items.add(new Item("Tango", 140));
            this.items.add(new Item("Water", 100));
            this.items.add(new Item("Pepsi", 130));
            this.items.add(new Item("Sprite", 120));
        }

        public List<Item> getCoins() {
            return coins;
        }

        public List<Item> getItems() {
            return items;
        }
        
        public void addCoin(int amount) {
            this.balance += amount;
        }
        
        public void purchaseProduct(int amount) {
            this.balance -= amount;
        }

        public void setBalance(int balance) {
            this.balance = balance;
        }
        
        public int getBalance() {
            return balance;
        }

        public void setChange(int change) {
            this.change = change;
        }
        
        public int getChange() {
            return change;
        }

    }
    
    public class Item {
        
        private final int price;
        
        private final String name;

        public Item(String name, int price) {
            this.name = name;
            this.price = price;
        }

        public int getPrice() {
            return price;
        }

        public String getName() {
            return name;
        }

    }

}