我正在制作 Subway 餐廳的復制品,您將在其中按特定順序收到訂單,并檢查該順序是否有效以及選單中是否有食材。
正確的順序是:1 塊面包、0 到 1 塊肉、1 塊奶酪、1 到 3 份額外食物、1 到 3 種醬汁。
這意味著一個訂單可以包含至少 4 種成分(面包、奶酪、1 種額外成分、1 種醬汁)和最多 9 種成分(面包、肉類、奶酪、3 種額外成分、3 種醬汁)。
我的問題是,是否有比我的更優化/更智能的方法來驗證每種成分?
代碼:
// Example order
HashMap<String, HashSet<String>> menu = new HashMap<>();
public static void main(String[] args) {
// Example order
List<String> ingredients = Arrays.asList("Wheat", "Veal",
"Yellow", "Cucumbers", "Onions");
if (!isValid(ingredients)) {
// throw exc;
}
boolean isValid(List<String> ingredients) {
if (ingredients.size() < 4 || ingredients.size() > 9) {
return false;
}
int i = 0;
// Bread
if (!Restaurant.menu.get("Bread")
.contains(ingredients.get(i ))) {
System.out.println("Bread");
return false;
}
// Meat
if (!(Restaurant.menu.get("Meat")
.contains(ingredients.get(i)))
&& !Restaurant.menu.get("Cheese")
.contains(ingredients.get(i))) {
System.out.println("Meat");
return false;
}
if (Restaurant.menu.get("Meat")
.contains(ingredients.get(i))) { // Meat case
if ((!Restaurant.menu.get("Cheese")
.contains(ingredients.get( i)))) {
System.out.println("Cheese");
return false;
}
}
for (int j = i; j < ingredients.size(); j ) {
if ((!Restaurant.menu.get("Extras")
.contains(ingredients.get(j)))) { // Extras
if (j == i) {
return false;
} else {
if ((!Restaurant.menu.get("Sauces")
.contains(ingredients.get(j)))) { // Sauces
return false;
}
}
}
}
return true;
}
注 1:我知道“如果它有效,請不要碰它”的規則,但我覺得這段代碼正在進入意大利面條代碼的領域,其中有一堆 ifs 基本上檢查了很多情況下類似的事情,只是想要一個第二種意見,如果我現在想不出更優化的方式。
注意 2:我為選單選擇了 HashSet 而不是 ArrayList,因為它的搜索速度更快。
uj5u.com熱心網友回復:
我在您提出的解決方案中看到的問題是它試圖一次解決所有問題,而不是單獨解決它們。在我看來,這使您的代碼難以閱讀和理解。雖然它可能有效,但您添加的業務規則越多,這就越難。
所以你對此能做些什么?分離關注點。
第一個問題是對一種成分進行分類:是面包、奶酪、肉、額外的還是醬汁?例如,您可以使用回傳類別Menu
的方法getCategory()
(而不僅僅是使用HashSet
for 選單)創建一個類,并且回傳值可以是一個 Enum。
第二個問題是秩序。您可以使用自定義檢查串列的順序Comparator
。有關詳細資訊,請參閱此問題。
第三個關注點是某一類別的成分數量。鑒于您可以找出一種成分的類別,您可以計算您有多少并檢查它是否正確。
關于如何實作這一點還有很多話要說,我只是想為您指出一個可能的方向。
uj5u.com熱心網友回復:
首先,您的一般方法沒有什么問題。
話雖如此,還是有一些錯誤。
- 您通過未宣告為靜態的 Restaurant 將您的 hashMap 參考為靜態值。
- 您是
isValid()
從靜態背景關系(Main)中呼叫的,但該方法未宣告為靜態的。
這就是我可能接近它的方式。這也不是說它是最好的方法或風格。
我選擇使用一個
enum
來保存每個選單項的詳細資訊,以及一個處理訂單的類。Enum 很容易滿足這種型別的要求。我建議您閱讀它們(它們過于復雜,無法在此處詳細解釋)。但正因為如此,static
他們最適合持有不太可能改變的價值觀。每個專案都有兩個引數,都在
enum's
建構式中處理。所以每個專案都有一個單獨的專案范圍(成分)
還有
enum
一個 validate 方法來檢查提供的專案數量是否符合要求。
實際順序在MyOrder
課堂上。
- 它包含一個地圖來保存每種成分的數量。
- add 方法將當前數量添加到給定成分的地圖中。
- 以及列印訂單資訊的顯示方法。
enum Menu {MEAT(0,1), BREAD(1,1), CHEESE(1,1), EXTRAS(1,3), SAUCES(1,3);
private int min;
private int max;
private Menu(int min, int max) {
this.min = min;
this.max = max;
}
public int getMax() {
return max;
}
public int getMin() {
return min;
}
public boolean validate(int count) {
return count >= min && count <= max;
}
}
class MyOrder {
private EnumMap<Menu, Integer> counts = new EnumMap<>(Menu.class);
public void display() {
for (Menu item : Menu.values()) {
int count = counts.get(item);
System.out.printf("%-7s: %d (%d,%d) %s%n",item.name(), count, item.getMin(), item.getMax(),
item.validate(count) ? "" : "Item count out of range.");
}
}
public boolean add(Menu item, int quantity) {
return item.validate(counts.merge(item, quantity, Integer::sum));
}
}
public class Restaurant {
public static void main(String[] args) {
boolean isValid;
MyOrder order = new MyOrder();
isValid = order.add(Menu.BREAD,2);
isValid &= order.add(Menu.MEAT,1);
isValid &= order.add(Menu.CHEESE,2);
isValid &= order.add(Menu.EXTRAS,3);
isValid &= order.add(Menu.SAUCES,2);
if (isValid) {
System.out.println("Your order is accepted.");
} else {
System.out.println("Order is not in compliance");
order.display();
}
}
}
印刷
Order is not in compliance
MEAT : 1 (0,1)
BREAD : 1 (1,1)
CHEESE : 2 (1,1) Item count out of range.
EXTRAS : 3 (1,3)
SAUCES : 2 (1,3)
還要記住 any 的結果if statement
是boolean
. 因此,inequality
可以將其分配給布林值,然后再進行測驗(如果這樣做有意義的話)。另請注意,我直到最后才檢查合法訂單。有些人可能更愿意在訂單出現錯誤時立即發出信號。這是一種設計選擇。
欲了解更多資訊檢查。
列舉
EnumMap
Map.merge
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/493743.html