首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >基于不同成分饮料价格计算的简单咖啡师应用

基于不同成分饮料价格计算的简单咖啡师应用
EN

Code Review用户
提问于 2018-02-04 20:55:27
回答 2查看 972关注 0票数 3

这种情况是,客户从自动售货机上订购咖啡,方法是从几个类别中选择一个选择,例如大小、风味和奶油类型。

考虑到他们的选择,我们必须计算出成本。

更妙的是,如果你买了一杯超大杯咖啡,那么各种奶精的选择就会稍微贵一些。

例如,如果您选择牛奶作为您的乳膏,通常是50美分;但是,如果您也选择XL作为您的大小,牛奶价格60美分。

代码语言:javascript
复制
public enum Coffee {

    CAFFEE_AMERICANO("Coffee", .75),
    CAFFEE_LATTE("Caffee Latte" , .50),
    CAFFE_MOCHA("Caffee Mocha" , .65),
    CAPPUCCINO("Cappuccino" , .85),
    COFFEE("Caffee" , .95),
    DECAF_COFFEE("Decaf Coffee" , .45);

    private final String name;
    private final double unit_price;

    private Coffee(String name, double unit_cost)
    {
        this.name = name;
        this.unit_price = unit_cost;
    }

    public String getName() {
        return name;
    }

    public double getUnit_price() {
        return unit_price;
    }

}
代码语言:javascript
复制
public enum Creamer {

    NONE("None", 0.0),
    MILK("Milk", 0.50),
    HALF_N_HALF("Half and Half", 0.25),

    TALL_MILK("Milk", 0.60),
    TALL_HALF_N_HALF("Half and Half", 0.35),

    GRANDE_MILK("Grande Milk", 0.65),
    GRANDE_HALF_N_HALF("Grande Half and Half", 0.45),

    VENTI_MILK("Venti Milk", 0.70),
    VENTI_HALF_N_HALF("Venti Half and Half", 0.55),

    TRENTA_MILK("Trenta Milk", 0.75),
    TRENTA_HALF_N_HALF("Trenta Half and Half", 0.60);


    private String name;
    private double price;

    private Creamer(String name, double price)
    {
        this.name= name;
        this.price = price;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

}
代码语言:javascript
复制
public class PricingEngine {

    public static double priceBasedOnSize(Map<String, Enum> ingredients) {

        double totalCost = 0.0;
        Coffee coffee = (Coffee) ingredients.get("Coffee");
        totalCost += coffee.getUnit_price();

        Size size = (Size) ingredients.get("Size");

        Creamer creamer = (Creamer) ingredients.get("Creamer");

        // get price based on the creamer and cup size

        String priceBySize = size.name() + "_" + creamer.name();

        totalCost += Creamer.valueOf(priceBySize).getPrice();

        return totalCost;

    }

}
代码语言:javascript
复制
public enum Size {

    TALL("Tall"),
    GRANDE("Grande"),
    VENTI("Venti"),
    TRENTA("Trenta");

    private String name;

    private Size(String name)
    {
        this.name= name;
    }

    public String getName()
    {
        return this.name();
    }

}
代码语言:javascript
复制
public class BaristaMain {

    public static void main(String[] args) {

        Scanner in = new Scanner(System.in);
        boolean appRunning = true;
        Map<String, Enum> map = new HashMap<String, Enum>();
        System.out.println("Welcome to automatic coffee dispensing service\n\n");
        while (appRunning) {

            System.out.print("1. Caffe Americano");
            System.out.print(" 2. Caffe Latte");
            System.out.print(" 3. Caffe Mocha");
            System.out.print(" 4. Cappuccino");
            System.out.print(" 5. Coffee");
            System.out.println(" 6. Decaf Coffee");
            System.out.println("Please enter your choice: ");
            int chioiceOfCoffee = in.nextInt();

            if (chioiceOfCoffee == 1) {
                map.put("Coffee", Coffee.CAFFEE_AMERICANO);

            } else if (chioiceOfCoffee == 2) {
                map.put("Coffee", Coffee.CAFFEE_LATTE);

            } else if (chioiceOfCoffee == 3) {
                map.put("Coffee", Coffee.CAFFE_MOCHA);

            } else if (chioiceOfCoffee == 4) {
                map.put("Coffee", Coffee.CAPPUCCINO);

            } else if (chioiceOfCoffee == 5) {
                map.put("Coffee", Coffee.COFFEE);

            } else if (chioiceOfCoffee == 6) {
                map.put("Coffee", Coffee.DECAF_COFFEE);

            } else {
                System.out.println("Your entry: " + chioiceOfCoffee + " is not valide. Please enter a valid choice.");
            }

            System.out.print("1. Tall(Slept 8-10 Hours)");
            System.out.print(" 2. Grande(Slept 5-7 Hours)");
            System.out.print(" 3. Venti(Slept 0-4 Hours");
            System.out.println(" 4. Trenta(WTF is sleep?)");
            System.out.println("Please enter your cup size: ");
            int cupSize = in.nextInt();

            if (cupSize == 1) {
                map.put("Size", Size.TALL);

            } else if (cupSize == 2) {
                map.put("Size", Size.GRANDE);

            } else if (cupSize == 3) {
                map.put("Size", Size.VENTI);

            } else if (cupSize == 4) {
                map.put("Size", Size.TRENTA);

            } else {
                System.out.println(
                    "Your entry for cup size : " + cupSize + " is not valide. Please enter a valid choice.");
            }

            System.out.print("1. NONE");
            System.out.print(" 2. MILK");
            System.out.println(" 3. HALF_N_HALF");
            System.out.println("Please enter your choice of creamer: ");
            int creamer = in.nextInt();

            if (creamer == 1) {
                map.put("Creamer", Creamer.NONE);

            } else if (creamer == 2) {
                map.put("Creamer", Creamer.MILK);

            } else if (creamer == 3) {
                map.put("Creamer", Creamer.HALF_N_HALF);

            } else {
                System.out.println(
                    "Your entry for cup size : " + cupSize + " is not valide. Please enter a valid choice.");
            }

            System.out.println();

            System.out.println("Dispensing.............");

            System.out.println("Total Cost: " + PricingEngine.priceBasedOnSize(map));
            System.out.println("Enjoy your coffee!");

        }

    }

}

我知道还有5种其他方法(例如装饰模式)可以做到这一点,但出于某些原因,解决方案必须有enum。

告诉我你们对这个解决方案的看法。对定价引擎的任何改进都是有帮助的。

还有其他种类也可以改变咖啡的价格。

EN

回答 2

Code Review用户

发布于 2018-02-04 21:46:41

通用实现

我倾向于拥有一个昂贵的界面,这是额外的枚举实现的,并让咖啡存储一个额外的列表,可以传递的大小和返回的金额,以增加的价格。

代码语言:javascript
复制
enum Creamer implements Priceable {
    NONE {
        @Override
        public double getPrice(Size size) {
            return 0;
        }
    }, MILK {
        @Override
        public double getPrice(Size size) {
            switch (size) {
                case TALL:
                    return 0.6;
                case GRANDE:
                    return 0.65;
                case VENTI:
                    return 0.70;
                case TRENTA:
                    return 0.75;
                default:
                    throw new AssertionError("Unknown size");
            }
        }
    }, HALF_N_HALF {
        @Override
        public double getPrice(Size size) {
            switch (size) {
                case TALL:
                    return 0.35;
                case GRANDE:
                    return 0.45;
                case VENTI:
                    return 0.50;
                case TRENTA:
                    return 0.6;
                default:
                    throw new AssertionError("Unknown size");
            }
        }
    };
}

interface Priceable {
    public double getPrice(Size size);
}

使用双重货币--

如果可能的话,我会尝试使用int而不是double,这样您就不必处理浮点问题了。

输入验证

目前,如果用户输入错误,则会引发异常,您可能需要处理此异常。

使用序数的

使用values()数组,您可以避免切换枚举成员来按索引获取它们。

票数 6
EN

Code Review用户

发布于 2018-02-04 22:19:58

谢谢你分享你的代码。

我喜欢enum方法,但它可以改进。

我对你的做法的问题是,你处理饮料的大小就像一种配料。

另一方面,你将奶油的"XL“价格和奶油本身分开,因为它可能是奶油的一种属性。

因此,我会为咖啡类型和面霜创建一个公共界面,这样我就可以将它们保存在同一个列表中:

代码语言:javascript
复制
interface Ingredient{
  /** @return the ingredient price depending on the drinks size */
  double getPrice(Size size);
} 

creamer enum实现了这个接口:

代码语言:javascript
复制
enum Creamer implements Ingredient {
    NONE("None"){
       @override
       public double getPrice(Size size){
           return 0.0; // same value for all
       }
    },
    MILK("Milk", 0.50, 0.65, 0.70, 0.75),
    HALF_N_HALF("Half and Half", 0.25, 0.45, 0.55, 0.60);

    private final double[] prices;
    private final String name;
    Creamer(String name, double ... prices){
      this.name = name;
      this.prices = prices;
    }
    @override
    public double getPrice(Size size){
       return prices[size.ordinal()]; // enum Size should have a dedicated getIndex() method to be independent from order in the enum.
    }
    public String getName() {
        return name;
    }
}

my咖啡类型还将实现此接口,因为实现者忽略大小参数没有问题。此外,这也使人们很容易为咖啡引入尺寸决定的价格,但这是一个副作用,不是故意的:

代码语言:javascript
复制
enum Coffe implements Ingredient {

    CAFFEE_AMERICANO("Coffee", .75),
    CAFFEE_LATTE("Caffee Latte" , .50),
    CAFFE_MOCHA("Caffee Mocha" , .65),
    CAPPUCCINO("Cappuccino" , .85),
    COFFEE("Caffee" , .95),
    DECAF_COFFEE("Decaf Coffee" , .45);

    private final String name;
    private final double unitPrice;

    private Coffee(String name, double unitCost)
    {
        this.name = name;
        this.unitPrice = unitCost;
    }

    public String getName() {
        return name;
    }

    @override
    public double gePrice(Size size) {
        return unitPrice;
    }
}

有了这个之后,我可以在Collection<Ingredient> (而不是Map)中收集咖啡和奶油,并将这个列表连同选定的大小一起传递给PricingEngine

代码语言:javascript
复制
// ...
Collection<Ingredient> myCoffee = new HasSet<>();
myCoffee.add(askForCoffeeType());
int size = askForSize();
myCoffee.add(askForCreamer());

double coffeePrice = new PricingEngine()
                      .priceBasedOnSize(myCoffee, size);
reportToCustomer(coffeePrice);
// ...

代码语言:javascript
复制
public class PricingEngine {

    public static double priceBasedOnSize(Collection<Ingredient> ingredients, int size) {
        double totalCost = 0.0;
        for(Ingredient ingredient : ingredients)
            totalCost += ingredient.getPrice(size);
        return totalCost;
        // alternative with Java8
        return ingredients.stram().
                          .mapToDouble(ingredient.getPrice(size))
                          .sum();
    }

}

效益:

  • 咖啡和奶油没有区别。
  • 更短
  • 支持更多的成分类型(例如可选的“口味”)而不改变。但再次:这是一个副作用,不是故意的。
票数 3
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

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

复制
相关文章

相似问题

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