首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >快餐订餐模拟器

快餐订餐模拟器
EN

Code Review用户
提问于 2019-08-17 08:45:57
回答 2查看 4.5K关注 0票数 6

我最近一直在尝试学习OOP,并制作了一个简单的程序,通过使用9位键盘来添加、删除和支付从菜单上订购的项目来模拟某种驱动器体验。

据我所知,每件事都是按我的意思运作的。我觉得我的一些课程可能做得太多了,总体来说,这个程序可以简化。

我不确定的事情之一是Customer类,因为它只包含名称字符串。似乎客户应该能够做一些诸如支付等事情。

另一方面,Order类似乎做了太多的事情。

请告诉我你的想法,以及你会采取什么不同的做法。

这是密码,谢谢你抽出时间!

主要班:

代码语言:javascript
运行
复制
/*******************************************************************************
 * Title: Fast Food Simulator
 * Author: Some Dude
 * Date: 7/14/2019
 * Purpose: Learning basic OOP design
 *
 * Description:
 * ! A simple program that simulates placing an order at a drive-thru
 *   using a keypad for input.
 *
 * ! User can add/delete items from their order, and pay for the items
 ******************************************************************************/

package com.company;

import java.util.Scanner;

public class Main
{
    private static Scanner scanner = new Scanner(System.in);

    private static Menu mainMenu = new Menu();
    private static Customer newCustomer;
    private static Order customerOrder = new Order();
    private static Keypad driveThruKeypad = new Keypad();


    /* Main Function Here! */
    public static void main(String[] args)
    {
        CustomerMessages.displayGreeting();
        getCustomerName();
        CustomerMessages.displayKeypadInstructions();
        getOrder();
        customerOrder.payForOrder();
        CustomerMessages.goodbye();
    }


    /***************************************************************************
     *! While the order is active,
     *! Show menu
     *! Display order (if they have actually ordered something)
     *! Get keypad input from customer
     *! Allows user to add/delete items from their order
     **************************************************************************/
    private static void getOrder()
    {
        char itemSelection = '0';

        while (itemSelection != '#')
        {
            mainMenu.displayMenu();

            if (customerOrder.getItemCount() > 0)
                customerOrder.displayOrder(newCustomer.getCustomerName());

            itemSelection = driveThruKeypad.getKeypadEntry();

             if (driveThruKeypad.deleteBtnPressed(itemSelection))
                 deleteItem();
            else
                customerOrder.addItem(mainMenu.getMenuItemName(itemSelection),
                        mainMenu.getMenuItemPrice(itemSelection));
        }
    }


    /***************************************************************************
     *  Prompts user to select an item to delete, then deletes it
     *  only if the item has actually been ordered
     **************************************************************************/
    private static void deleteItem()
    {
        char itemSelection = 0;

        System.out.println("What Item would you like to delete?");

        itemSelection = driveThruKeypad.getKeypadEntry();

        customerOrder.removeItem(mainMenu.getMenuItemName(itemSelection),
                mainMenu.getMenuItemPrice(itemSelection));
    }

    /***************************************************************************
     * Prompts the customer to enter their name, then initializes the Customer
     * instance *newCustomer* using the name given by customer
     **************************************************************************/
    private static void getCustomerName()
    {
        System.out.println("Please enter your name");
        newCustomer = new Customer(scanner.nextLine());
    }

}

客户类别:

代码语言:javascript
运行
复制
/*******************************************************************************
 * Title: Fast Food Simulator
 * Author: Some Dude
 * Date: 7/14/2019
 * Purpose: Class for a customer, will hold name, and maybe a member id later
 ******************************************************************************/

package com.company;


public class Customer
{
    private String customerName;


    Customer(String name)
    {
        this.customerName = name;
    }


    public String getCustomerName()
    {
        return customerName;
    }

}

键盘级

代码语言:javascript
运行
复制
/*******************************************************************************
 * Title: Keypad
 * Author: Some Dude
 * Date: 7/14/2019
 *
 *
 * Description:
 * ! Interface for a 9 digit keypad
 ******************************************************************************/


package com.company;

import java.util.Scanner;

public class Keypad
{

    private Scanner keypadReader = new Scanner(System.in);

    /* Control buttons */
    private final char SUBMIT_BUTTON = '#';
    private final char DELETE_BUTTON = '-';

    /* User defined button ranges */
    private final char minNumberInput = '0';
    private final char maxNumberInput = '9';


    /***************************************************************************
     *! Gets input from user until the button pressed was a valid button
     *  on the keypad (Valid buttons are defined up top)
     **************************************************************************/
    char getKeypadEntry()
    {
        char keypadEntry = '0';
        boolean inputIsValid = false;

        while (!inputIsValid)
        {
            System.out.println("Enter a keypad option: ");
            keypadEntry = keypadReader.next().charAt(0);
            inputIsValid = validateKeypadEntry(keypadEntry);
        }

        return keypadEntry;
    }


    /***************************************************************************
     *! Checks user input to make sure it's valid
     **************************************************************************/
    private boolean validateKeypadEntry(char keypadInput)
    {
        if ((keypadInput >= minNumberInput) && (keypadInput <= maxNumberInput))
            return true;
        else
            return (keypadInput == SUBMIT_BUTTON) || (keypadInput == DELETE_BUTTON);
    }


    /* Checks to see if the '#' button was pressed */
    public boolean orderCompleteBtnPressed(int input)
    {
        return input == SUBMIT_BUTTON;
    }


    /* Checks to see if the '-' button was pressed */
    public boolean deleteBtnPressed(int input)
    {
        return input == DELETE_BUTTON;
    }


}

订单类别:

代码语言:javascript
运行
复制
/*******************************************************************************
 * Title: Order
 * Author: Some Dude
 * Date: 7/14/2019
 * Purpose: Handles everything that has to do with the order
 *
 * Description: Handles everything that has to do with the order such as ->
 *! Adding/deleting order items
 *! Accepting payment for the order
 *! Keeping track of subtotal(no tax), and grandTotal(After tax)
 *! Keeping track of items in the order
 ******************************************************************************/

package com.company;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Scanner;

public class Order
{
    /* Scanner used for keypad input */
    private Scanner scanner = new Scanner(System.in);

    private final double STATE_TAX = 0.10;

    /* Order total before/after tax */
    private double subTotal;
    private double grandTotal;

    /* Counter for items ordered and list to hold item names*/
    private int itemCount;
    private ArrayList orderItems;


    public Order()
    {
        this.itemCount = 0;
        this.subTotal = 0.00;
        this.grandTotal = 0.00;
        this.orderItems = new ArrayList<>();
    }


    /***************************************************************************
     *! Add and item to the order, increment itemCount, increase price
     **************************************************************************/
    void addItem(String itemName, double itemPrice)
    {
        if ((!itemName.equals("")) && (itemPrice > 0.00))
        {
            this.orderItems.add(itemName);
            this.itemCount++;
            this.subTotal += itemPrice;
            System.out.println(itemName + " Added to your order");
            updateGrandTotal();
        }
    }


    /***************************************************************************
     *! If item has actually been ordered, delete it, else, show err message
     **************************************************************************/
    void removeItem(String itemName, double itemPrice)
    {
        if (this.orderItems.contains(itemName))
        {
            this.orderItems.remove(itemName);
            this.itemCount -= 1;
            this.subTotal -= itemPrice;
            System.out.println(itemName + " Deleted from your order");
            updateGrandTotal();
        }
        else
            System.out.println(itemName + " is not in your order");
    }



    double getGrandTotal()
    {
        return this.grandTotal;
    }

    public double getSubTotal()
    {
        return this.subTotal;
    }

    public int getItemCount()
    {
        return itemCount;
    }


    private void setSubTotal(double amount)
    {
        this.subTotal = amount;
    }


    /* Adds the tax rate to the order */
    private void updateGrandTotal()
    {
        this.grandTotal =
                this.subTotal + (this.subTotal * this.STATE_TAX);
    }


    /* Checks to see if item is in orderItems list */
    private boolean findOrderItem(String itemName)
    {
        return this.orderItems.contains(itemName);
    }


    /* Displays the order details to the user */
    public void displayOrder(String customerName)
    {
        System.out.println(
                "************************************************************");
        System.out.printf("%s's order details:\n", customerName);
        System.out.printf("Items ordered: %d\n", itemCount);
        System.out.println(Arrays.toString(this.orderItems.toArray()));
        System.out.printf("Price before tax: $%.2f\n", subTotal);
        System.out.printf("Grand total: $%.2f\n", grandTotal);
        System.out.println(
                "************************************************************");
    }


    /* While order is not paid for, get money from customer */
    public void payForOrder()
    {
        double cashRecieved = 0.00;

        while (grandTotal != 0.00)
        {
            /* Round grandTotal to 2nd decimal place */
            grandTotal = round2Decimals(grandTotal);

            System.out.printf("Your total is $%.2f\n", grandTotal);
            System.out.println("Enter your payment amount");

            cashRecieved = scanner.nextDouble();

            if (cashRecieved > 0)
                grandTotal -= cashRecieved;

            if (grandTotal < 0.00)
                calculateChange();
        }
    }


    /* Calculates the change due (Only used when grandTotal is < 0.00) */
    private void calculateChange()
    {
        double changeDue = 0.00;

        changeDue = (0.00 - grandTotal);
        grandTotal = 0.00;

        changeDue = round2Decimals(changeDue);

        System.out.println("Your change is " + changeDue);
    }


    /* Returns a double rounded to the 2nd value (2.222 = 2.22) */
    private double round2Decimals(double num)
    {
        return (double) Math.round(num * 100) / 100;
    }

}

客户消息类:

代码语言:javascript
运行
复制
/*******************************************************************************
 * Title: Customer Messages
 * Author: Some Dude
 * Date: 7/14/2019
 *
 * Purpose: Stores all of the general messages that the company would
 * want to show on the screen
 ******************************************************************************/

package com.company;

public class CustomerMessages
{

    public static void displayGreeting()
    {
        System.out.println("Welcome to some burger joint!");
    }

    public static void goodbye()
    {
        System.out.println("Thank you for eating at some burger joint!\n" +
                "Please come again!");
    }

    /* Shows the instructions for the keypad */
    public static void displayKeypadInstructions()
    {
        System.out.println("\n");
        System.out.println(
                "************************************************************");
        System.out.println("~Keypad Instructions~");
        System.out.println("To add an item to your order, please press the " +
                "keypad number that matches the item number on the screen");

        System.out.println("To delete an item from your order, press the '-' " +
                "key on the keypad");

        System.out.println("To submit your order, press the '#' key on the " +
                "keypad");
        System.out.println(
                "************************************************************");
    }

}

菜单类:

代码语言:javascript
运行
复制
/*******************************************************************************
 * Title: Menu
 * Author: Some Dude
 * Date: 7/14/2019
 *
 * Purpose: Interface for the main menu
 *
 * Description:
 * ! Shows the current menu
 * ! Keeps track of how many menu items are available
 * ! Keeps track of menu item prices and names
 ******************************************************************************/

package com.company;

public class Menu
{
    /* Menu Prices */
    private final double CHEESEBURGER_PRICE = 5.25;
    private final double FRENCH_FRIES_PRICE = 2.00;
    private final double DRINK_PRICE = 1.00;

    /* Menu Items */
    private final String CHEESEBURGER = "Cheeseburger";
    private final String FRIES = "Fries";
    private final String DRINK= "Drink";

    /* The amount of items currently on the menu */
    private final int totalMenuItems = 3;


    /* Displays menu options and prices */
    void displayMenu()
    {
        System.out.println("***************************");
        System.out.println("~Menu~");
        System.out.println("1) Cheeseburger $" + CHEESEBURGER_PRICE);
        System.out.println("2) Fries $" + FRENCH_FRIES_PRICE);
        System.out.println("3) Drink $" + DRINK_PRICE);
        System.out.println("***************************");
    }


    public double getCheeseburgerPrice()
    {
        return CHEESEBURGER_PRICE;
    }
    public double getFrenchFriesPrice()
    {
        return FRENCH_FRIES_PRICE;
    }
    public double getDrinkPrice()
    {
        return DRINK_PRICE;
    }
    public int getTotalMenuItems()
    {
        return totalMenuItems;
    }


    /***************************************************************************
     * Returns the name of the item that matches the item selection number,
     * Return blank string if menu item doesn't exist
     **************************************************************************/
    public String getMenuItemName(char itemSelection)
    {
        switch (itemSelection)
        {
            case '1':
                return CHEESEBURGER;
            case '2':
                return FRIES;
            case '3':
                return DRINK;
            default:
                return "";
        }
    }

    /***************************************************************************
     * Returns the price of the item that matches the itemSelection number
     * Return 0.00 if item doesn't exist
     **************************************************************************/
    double getMenuItemPrice(char itemSelection)
    {
        switch (itemSelection)
        {
            case '1':
                return CHEESEBURGER_PRICE;
            case '2':
                return FRENCH_FRIES_PRICE;
            case '3':
                return DRINK_PRICE;
            default:
                return 0.00;
        }
    }

}
EN

回答 2

Code Review用户

回答已采纳

发布于 2019-08-17 17:14:33

  • 从总体上看,您的代码看起来非常干净,我认为您的类之间的逻辑分离非常清楚。
  • 不要用双倍的钱,因为有精确的问题。考虑使用BigDecimal。这样,您还可以避免使用像round2Decimals这样的草率功能。
  • 在Keypad类上,应该注入扫描器依赖项。
代码语言:javascript
运行
复制
public class Keypad
{

    private Scanner keypadReader;
    public Order(Scanner keypadReader)
    {
        this.itemCount = 0;
        this.subTotal = 0.00;
        this.grandTotal = 0.00;
        this.orderItems = new ArrayList<>();
        this.keypadReader = keypadReader;
    }

    // ...
}
  • 为什么在注释前加上!符号?这没有任何用处,应该删除。
  • 使用预增量:this.itemCount -= 1; \to --this.itemCount;
  • 您的菜单类可能无法处理,比方说,5或6个以上的配料。您可能希望创建一个以名称和价格作为属性的Dish类。
  • CustomerMessages类应该是static
  • 考虑使用JavaDoc:
代码语言:javascript
运行
复制
/**
 * @author Some Dude
 * @since 7/14/2019
 *
 * Interface for the main menu:
 * - Shows the current menu
 * - Keeps track of how many menu items are available
 * - Keeps track of menu item prices and names
 */
  • 避免长/**********..。备注。只要/*/** (对于JavaDoc)就够了。
  • 看看Liskov替代原则。这里相当大的例子不是使用ArrayLists作为属性,而是简单地使用Lists:
代码语言:javascript
运行
复制
 private List orderItems; // No longer ArrayList!!!!


    public Order()
    {
        this.itemCount = 0;
        this.subTotal = 0.00;
        this.grandTotal = 0.00;
        this.orderItems = new ArrayList<>();
    }
  • 不要对单行注释使用多行注释:/* Menu Items */ \to // Menu items
  • 检查类中的静态函数(即void displayMenu()应该是静态的,CHEESEBURGER_PRICE和其他神奇的数字/字符串也应该是静态的)。
票数 2
EN

Code Review用户

发布于 2019-08-18 17:21:12

你好,我提议的更改涉及类Menu,因为每次您修改菜单(添加或删除菜单项)时,都必须定义一个新方法来获取新菜单项的名称和价格,或者您必须删除使用已删除项的方法。为了避免这个问题,我建议您的解决方案是在类的代码之上创建一个名为MenuItem的新类:

代码语言:javascript
运行
复制
class MenuItem {
    private String name;
    private Double price;

    public MenuItem(String name, Double price) {
        this.name = name;
        this.price = price;
    }

    public String getName() {
        return name;
    }


    public Double getPrice() {
        return price;
    }

    @Override
    public String toString() {
        return String.format("%s $%.2f", name, price);
    }
}

您可以检查我是否重写了toString方法:该方法将返回一个字符串,其价格限制在前两位数,如奶酪汉堡,$5,25。现在,Menu类将包含一个ArrayList of MenuItem对象,它位于类的代码之上:

代码语言:javascript
运行
复制
public class Menu {

    private List items;

    public Menu() {
        this.items = new ArrayList();
        this.items.add(new MenuItem("Cheeseburger", 5.25));
        this.items.add(new MenuItem("Fries", 2.00));
        this.items.add(new MenuItem("Drink", 1.00));
    }

    public void displayMenu()
    {
        System.out.println("***************************");
        System.out.println("~Menu~");
        int i = 1;
        for (MenuItem item : items) {
            System.out.println(String.format("%d) %s", i++, item));
        }
        System.out.println("***************************");
    }

    public MenuItem getMenuItem(int itemSelection) {
        return items.get(itemSelection);
    }
}

您可以看到,现在可以从菜单中添加或删除元素。我将参数itemSelection的类型从char修改为int,否则菜单将被限制为从1项到9项。

代码语言:javascript
运行
复制
public class Main {

public static void main(String[] args) {
    Menu menu = new Menu();
    menu.displayMenu();
    int itemSelection = 1;
    MenuItem item = menu.getMenuItem(--itemSelection); //menu displayed and arraylist differs for one position 
    System.out.println(item); //it will print Cheeseburger $5,25
    System.out.println(item.getName()); //it will print Cheeseburger
    System.out.println(item.getPrice()); //it will print 5.25
}

如果菜单从1开始,则必须记住减少从客户中选择的菜单项,以匹配类菜单中的arrayList。

票数 0
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/226306

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档