这种情况是,客户从自动售货机上订购咖啡,方法是从几个类别中选择一个选择,例如大小、风味和奶油类型。
考虑到他们的选择,我们必须计算出成本。
更妙的是,如果你买了一杯超大杯咖啡,那么各种奶精的选择就会稍微贵一些。
例如,如果您选择牛奶作为您的乳膏,通常是50美分;但是,如果您也选择XL作为您的大小,牛奶价格60美分。
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 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。
告诉我你们对这个解决方案的看法。对定价引擎的任何改进都是有帮助的。
还有其他种类也可以改变咖啡的价格。
发布于 2018-02-04 21:46:41
我倾向于拥有一个昂贵的界面,这是额外的枚举实现的,并让咖啡存储一个额外的列表,可以传递的大小和返回的金额,以增加的价格。
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()数组,您可以避免切换枚举成员来按索引获取它们。
发布于 2018-02-04 22:19:58
谢谢你分享你的代码。
我喜欢enum方法,但它可以改进。
我对你的做法的问题是,你处理饮料的大小就像一种配料。
另一方面,你将奶油的"XL“价格和奶油本身分开,因为它可能是奶油的一种属性。
因此,我会为咖啡类型和面霜创建一个公共界面,这样我就可以将它们保存在同一个列表中:
interface Ingredient{
/** @return the ingredient price depending on the drinks size */
double getPrice(Size size);
} creamer enum实现了这个接口:
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咖啡类型还将实现此接口,因为实现者忽略大小参数没有问题。此外,这也使人们很容易为咖啡引入尺寸决定的价格,但这是一个副作用,不是故意的:
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:
// ...
Collection<Ingredient> myCoffee = new HasSet<>();
myCoffee.add(askForCoffeeType());
int size = askForSize();
myCoffee.add(askForCreamer());
double coffeePrice = new PricingEngine()
.priceBasedOnSize(myCoffee, size);
reportToCustomer(coffeePrice);
// ...。
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();
}
}效益:
https://codereview.stackexchange.com/questions/186756
复制相似问题