Simple barista application to calculate the price of a drink based on different ingredients

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
1
down vote

favorite












The scenario is that a customer orders a coffee from a vending machine by selecting a choice from several categories,
such as size, flavor, and creamer type.



Given their choices, we then have to figure out the cost.



The twist is that the various creamer choices cost slightly more if you get an extra-large coffee.



For example, if you choose milk as your creamer,
it is normally 50 cents;
but, if you also choose XL as your size, the milk costs 60 cents.



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;






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;






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;







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();






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 servicenn");
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!");








I know there are 5 other ways (such as decorator pattern) to do this but for some reasons the solution has to have enum.



Let me know what you guys think about this solution. Any improvement on the pricing engine will be helpful.



There can be other categories as well that can change the price of the coffee.







share|improve this question

















  • 1




    ...for some reasons the solution has to have enum... could you elaborate on this, it seems like an artificial constraint, and the constraint may also affect answers
    – jrtapsell
    Feb 4 at 21:27
















up vote
1
down vote

favorite












The scenario is that a customer orders a coffee from a vending machine by selecting a choice from several categories,
such as size, flavor, and creamer type.



Given their choices, we then have to figure out the cost.



The twist is that the various creamer choices cost slightly more if you get an extra-large coffee.



For example, if you choose milk as your creamer,
it is normally 50 cents;
but, if you also choose XL as your size, the milk costs 60 cents.



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;






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;






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;







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();






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 servicenn");
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!");








I know there are 5 other ways (such as decorator pattern) to do this but for some reasons the solution has to have enum.



Let me know what you guys think about this solution. Any improvement on the pricing engine will be helpful.



There can be other categories as well that can change the price of the coffee.







share|improve this question

















  • 1




    ...for some reasons the solution has to have enum... could you elaborate on this, it seems like an artificial constraint, and the constraint may also affect answers
    – jrtapsell
    Feb 4 at 21:27












up vote
1
down vote

favorite









up vote
1
down vote

favorite











The scenario is that a customer orders a coffee from a vending machine by selecting a choice from several categories,
such as size, flavor, and creamer type.



Given their choices, we then have to figure out the cost.



The twist is that the various creamer choices cost slightly more if you get an extra-large coffee.



For example, if you choose milk as your creamer,
it is normally 50 cents;
but, if you also choose XL as your size, the milk costs 60 cents.



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;






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;






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;







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();






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 servicenn");
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!");








I know there are 5 other ways (such as decorator pattern) to do this but for some reasons the solution has to have enum.



Let me know what you guys think about this solution. Any improvement on the pricing engine will be helpful.



There can be other categories as well that can change the price of the coffee.







share|improve this question













The scenario is that a customer orders a coffee from a vending machine by selecting a choice from several categories,
such as size, flavor, and creamer type.



Given their choices, we then have to figure out the cost.



The twist is that the various creamer choices cost slightly more if you get an extra-large coffee.



For example, if you choose milk as your creamer,
it is normally 50 cents;
but, if you also choose XL as your size, the milk costs 60 cents.



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;






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;






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;







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();






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 servicenn");
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!");








I know there are 5 other ways (such as decorator pattern) to do this but for some reasons the solution has to have enum.



Let me know what you guys think about this solution. Any improvement on the pricing engine will be helpful.



There can be other categories as well that can change the price of the coffee.









share|improve this question












share|improve this question




share|improve this question








edited Feb 5 at 3:12









Jamal♦

30.1k11114225




30.1k11114225









asked Feb 4 at 20:55









Guest

565




565







  • 1




    ...for some reasons the solution has to have enum... could you elaborate on this, it seems like an artificial constraint, and the constraint may also affect answers
    – jrtapsell
    Feb 4 at 21:27












  • 1




    ...for some reasons the solution has to have enum... could you elaborate on this, it seems like an artificial constraint, and the constraint may also affect answers
    – jrtapsell
    Feb 4 at 21:27







1




1




...for some reasons the solution has to have enum... could you elaborate on this, it seems like an artificial constraint, and the constraint may also affect answers
– jrtapsell
Feb 4 at 21:27




...for some reasons the solution has to have enum... could you elaborate on this, it seems like an artificial constraint, and the constraint may also affect answers
– jrtapsell
Feb 4 at 21:27










2 Answers
2






active

oldest

votes

















up vote
4
down vote













General Implementation



I would lean towards having a Priceable interface, which the extra enums implement, and having the coffee storing a list of extras, which can be passed the size and return the amount to add to the price.



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);



Use of double for money



I would try to use int instead of double if possible, so that you do not have to deal with floating point issues.



Input validation



At the moment an exception is thrown if the user makes bad input, you probably want to handle this instead.



Using ordinals



Using the values() array you can avoid having to switch over the enum members to get them by index.






share|improve this answer





















  • loved your idea to move towards interface. Much cleaner approach. I made few changes to reflect those changes.
    – Guest
    Feb 4 at 23:31

















up vote
2
down vote













Thanks for sharing your code.



I like the enum approach but it could be improved.



My problem with your approach is that you handle the drink size like an ingredient.



On the other hand you separate the "XL" price of the creamer from the creamer itself where it might be a property of the creamer.



So I'd create a common interface for the coffee types and the creamers, so that I can hold them in the same List:



interface Ingredient
/** @return the ingredient price depending on the drinks size +/
double getPrice(Size size);



The creamer enum implements this interface:



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;




The my coffee type type will also implement this interface since it no problem for the implementer to ignore the size parameter. Also it makes it easy to introduce size depended prices for the coffees too, but this is a side effect, not intended:



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;




Having this I can collect coffee and creamer in a Collection<Ingredient> (rather than in a Map) and pass this list along with the selected size to the PricingEngine:



public class PricingEngine 

public static double priceBasedOnSize(Collection<Ingredient> ingredients, Size 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();





Benefit:



  • no differentiation between coffee and creamer.

  • shorter

  • supports more ingredient types (e.g. optional "flavors") without change. But again: this is a side effect, not intended.





share|improve this answer





















    Your Answer




    StackExchange.ifUsing("editor", function ()
    return StackExchange.using("mathjaxEditing", function ()
    StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
    StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
    );
    );
    , "mathjax-editing");

    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "196"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    convertImagesToLinks: false,
    noModals: false,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );








     

    draft saved


    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f186756%2fsimple-barista-application-to-calculate-the-price-of-a-drink-based-on-different%23new-answer', 'question_page');

    );

    Post as a guest






























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    4
    down vote













    General Implementation



    I would lean towards having a Priceable interface, which the extra enums implement, and having the coffee storing a list of extras, which can be passed the size and return the amount to add to the price.



    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);



    Use of double for money



    I would try to use int instead of double if possible, so that you do not have to deal with floating point issues.



    Input validation



    At the moment an exception is thrown if the user makes bad input, you probably want to handle this instead.



    Using ordinals



    Using the values() array you can avoid having to switch over the enum members to get them by index.






    share|improve this answer





















    • loved your idea to move towards interface. Much cleaner approach. I made few changes to reflect those changes.
      – Guest
      Feb 4 at 23:31














    up vote
    4
    down vote













    General Implementation



    I would lean towards having a Priceable interface, which the extra enums implement, and having the coffee storing a list of extras, which can be passed the size and return the amount to add to the price.



    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);



    Use of double for money



    I would try to use int instead of double if possible, so that you do not have to deal with floating point issues.



    Input validation



    At the moment an exception is thrown if the user makes bad input, you probably want to handle this instead.



    Using ordinals



    Using the values() array you can avoid having to switch over the enum members to get them by index.






    share|improve this answer





















    • loved your idea to move towards interface. Much cleaner approach. I made few changes to reflect those changes.
      – Guest
      Feb 4 at 23:31












    up vote
    4
    down vote










    up vote
    4
    down vote









    General Implementation



    I would lean towards having a Priceable interface, which the extra enums implement, and having the coffee storing a list of extras, which can be passed the size and return the amount to add to the price.



    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);



    Use of double for money



    I would try to use int instead of double if possible, so that you do not have to deal with floating point issues.



    Input validation



    At the moment an exception is thrown if the user makes bad input, you probably want to handle this instead.



    Using ordinals



    Using the values() array you can avoid having to switch over the enum members to get them by index.






    share|improve this answer













    General Implementation



    I would lean towards having a Priceable interface, which the extra enums implement, and having the coffee storing a list of extras, which can be passed the size and return the amount to add to the price.



    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);



    Use of double for money



    I would try to use int instead of double if possible, so that you do not have to deal with floating point issues.



    Input validation



    At the moment an exception is thrown if the user makes bad input, you probably want to handle this instead.



    Using ordinals



    Using the values() array you can avoid having to switch over the enum members to get them by index.







    share|improve this answer













    share|improve this answer



    share|improve this answer











    answered Feb 4 at 21:46









    jrtapsell

    435112




    435112











    • loved your idea to move towards interface. Much cleaner approach. I made few changes to reflect those changes.
      – Guest
      Feb 4 at 23:31
















    • loved your idea to move towards interface. Much cleaner approach. I made few changes to reflect those changes.
      – Guest
      Feb 4 at 23:31















    loved your idea to move towards interface. Much cleaner approach. I made few changes to reflect those changes.
    – Guest
    Feb 4 at 23:31




    loved your idea to move towards interface. Much cleaner approach. I made few changes to reflect those changes.
    – Guest
    Feb 4 at 23:31












    up vote
    2
    down vote













    Thanks for sharing your code.



    I like the enum approach but it could be improved.



    My problem with your approach is that you handle the drink size like an ingredient.



    On the other hand you separate the "XL" price of the creamer from the creamer itself where it might be a property of the creamer.



    So I'd create a common interface for the coffee types and the creamers, so that I can hold them in the same List:



    interface Ingredient
    /** @return the ingredient price depending on the drinks size +/
    double getPrice(Size size);



    The creamer enum implements this interface:



    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;




    The my coffee type type will also implement this interface since it no problem for the implementer to ignore the size parameter. Also it makes it easy to introduce size depended prices for the coffees too, but this is a side effect, not intended:



    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;




    Having this I can collect coffee and creamer in a Collection<Ingredient> (rather than in a Map) and pass this list along with the selected size to the PricingEngine:



    public class PricingEngine 

    public static double priceBasedOnSize(Collection<Ingredient> ingredients, Size 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();





    Benefit:



    • no differentiation between coffee and creamer.

    • shorter

    • supports more ingredient types (e.g. optional "flavors") without change. But again: this is a side effect, not intended.





    share|improve this answer

























      up vote
      2
      down vote













      Thanks for sharing your code.



      I like the enum approach but it could be improved.



      My problem with your approach is that you handle the drink size like an ingredient.



      On the other hand you separate the "XL" price of the creamer from the creamer itself where it might be a property of the creamer.



      So I'd create a common interface for the coffee types and the creamers, so that I can hold them in the same List:



      interface Ingredient
      /** @return the ingredient price depending on the drinks size +/
      double getPrice(Size size);



      The creamer enum implements this interface:



      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;




      The my coffee type type will also implement this interface since it no problem for the implementer to ignore the size parameter. Also it makes it easy to introduce size depended prices for the coffees too, but this is a side effect, not intended:



      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;




      Having this I can collect coffee and creamer in a Collection<Ingredient> (rather than in a Map) and pass this list along with the selected size to the PricingEngine:



      public class PricingEngine 

      public static double priceBasedOnSize(Collection<Ingredient> ingredients, Size 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();





      Benefit:



      • no differentiation between coffee and creamer.

      • shorter

      • supports more ingredient types (e.g. optional "flavors") without change. But again: this is a side effect, not intended.





      share|improve this answer























        up vote
        2
        down vote










        up vote
        2
        down vote









        Thanks for sharing your code.



        I like the enum approach but it could be improved.



        My problem with your approach is that you handle the drink size like an ingredient.



        On the other hand you separate the "XL" price of the creamer from the creamer itself where it might be a property of the creamer.



        So I'd create a common interface for the coffee types and the creamers, so that I can hold them in the same List:



        interface Ingredient
        /** @return the ingredient price depending on the drinks size +/
        double getPrice(Size size);



        The creamer enum implements this interface:



        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;




        The my coffee type type will also implement this interface since it no problem for the implementer to ignore the size parameter. Also it makes it easy to introduce size depended prices for the coffees too, but this is a side effect, not intended:



        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;




        Having this I can collect coffee and creamer in a Collection<Ingredient> (rather than in a Map) and pass this list along with the selected size to the PricingEngine:



        public class PricingEngine 

        public static double priceBasedOnSize(Collection<Ingredient> ingredients, Size 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();





        Benefit:



        • no differentiation between coffee and creamer.

        • shorter

        • supports more ingredient types (e.g. optional "flavors") without change. But again: this is a side effect, not intended.





        share|improve this answer













        Thanks for sharing your code.



        I like the enum approach but it could be improved.



        My problem with your approach is that you handle the drink size like an ingredient.



        On the other hand you separate the "XL" price of the creamer from the creamer itself where it might be a property of the creamer.



        So I'd create a common interface for the coffee types and the creamers, so that I can hold them in the same List:



        interface Ingredient
        /** @return the ingredient price depending on the drinks size +/
        double getPrice(Size size);



        The creamer enum implements this interface:



        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;




        The my coffee type type will also implement this interface since it no problem for the implementer to ignore the size parameter. Also it makes it easy to introduce size depended prices for the coffees too, but this is a side effect, not intended:



        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;




        Having this I can collect coffee and creamer in a Collection<Ingredient> (rather than in a Map) and pass this list along with the selected size to the PricingEngine:



        public class PricingEngine 

        public static double priceBasedOnSize(Collection<Ingredient> ingredients, Size 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();





        Benefit:



        • no differentiation between coffee and creamer.

        • shorter

        • supports more ingredient types (e.g. optional "flavors") without change. But again: this is a side effect, not intended.






        share|improve this answer













        share|improve this answer



        share|improve this answer











        answered Feb 4 at 22:19









        Timothy Truckle

        4,673316




        4,673316






















             

            draft saved


            draft discarded


























             


            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f186756%2fsimple-barista-application-to-calculate-the-price-of-a-drink-based-on-different%23new-answer', 'question_page');

            );

            Post as a guest













































































            Popular posts from this blog

            Chat program with C++ and SFML

            Function to Return a JSON Like Objects Using VBA Collections and Arrays

            Will my employers contract hold up in court?