摘要:但是有可能嵌套的語句只是轉移到了工廠類,這違背了我們的目的。這樣可以減少嵌套語句的數量,并將責任委托給單個值。一個評估規則和返回基于輸入的結果。首先,我們將定義一個接口其次,讓我們實現一個所述接受一個表達對象,并返回結果。
概述ifelse是任何編程語言的重要組成部分。但是我們編寫了大量嵌套的if語句,這使得我們的代碼更加復雜和難以維護。
接下來,讓我們探索如何簡化代碼的中的ifelse語句寫法。
案例研究我們經常遇到涉及很多條件的業務邏輯,并且每個邏輯都需要不同的處理方式。以Calculator類為例。我們將有一個方法,它接受兩個數字和一個運算符作為輸入,并根據操作返回結果:
public int calculate(int a, int b, String operator) {
int result = Integer.MIN_VALUE;
if ("add".equals(operator)) {
result = a + b;
} else if ("multiply".equals(operator)) {
result = a * b;
} else if ("divide".equals(operator)) {
result = a / b;
} else if ("subtract".equals(operator)) {
result = a - b;
}
return result;
}
我們也可以使用switch語句來實現它:
public int calculateUsingSwitch(int a, int b, String operator) {
switch (operator) {
case "add":
result = a + b;
break;
// other cases
}
return result;
}
在典型的開發中,if語句可能會變得更大,更復雜。此外,當存在復雜條件時,switch語句不適合。
擁有嵌套決策結構的另一個副作用是它們變得難以管理。例如,如果我們需要添加一個新的運算符,我們必須添加一個新的if語句并實現該操作。
重構工廠模式可以通過設計模式,來達到我們要的效果。
很多時候,我們遇到ifelse結構,最終在每個分支中執行類似的操作。這提供了提取工廠方法的機會,該工廠方法返回給定類型的對象并基于具體對象行為執行操作。
對于我們的示例,讓我們定義一個具有單個apply方法的Operation接口:
public interface Operation { int apply(int a, int b); }
該方法將兩個數字作為輸入并返回結果。讓我們定義一個用于執行添加的類:
public class Addition implements Operation {
@Override
public int apply(int a, int b) {
return a + b;
}
}
我們現在將實現一個工廠類,它根據給定的運算符返回Operation的實例:
public class OperatorFactory {
static Map operationMap = new HashMap<>();
static {
operationMap.put("add", new Addition());
operationMap.put("divide", new Division());
// more operators
}
public static Optional getOperation(String operator) {
return Optional.ofNullable(operationMap.get(operator));
}
}
現在,在Calculator類中,我們可以查詢工廠以獲取相關操作并應用源數:
public int calculateUsingFactory(int a, int b, String operator) {
Operation targetOperation = OperatorFactory
.getOperation(operator)
.orElseThrow(() -> new IllegalArgumentException("Invalid Operator"));
return targetOperation.apply(a, b);
}
在這個例子中,我們已經看到了如何將責任委托給工廠類提供的松散耦合對象。但是有可能嵌套的if語句只是轉移到了工廠類,這違背了我們的目的。
或者,我們可以在Map中維護一個對象存儲庫,可以查詢該存儲庫以進行快速查找。正如我們所見,OperatorFactory#operationMap服務于我們的目的。我們還可以在運行時初始化Map并將它們配置為查找。
使用枚舉除了使用Map之外,我們還可以使用Enum來標記特定的業務邏輯。之后,我們可以在嵌套的if語句或switch case 語句中使用它們。或者,我們也可以將它們用作對象的工廠并制定策略以執行相關的業務邏輯。
這樣可以減少嵌套if語句的數量,并將責任委托給單個Enum值。
讓我們看看我們如何實現它。首先,我們需要定義我們的枚舉:
public enum Operator { ADD, MULTIPLY, SUBTRACT, DIVIDE }
可以觀察到,這些值是不同運算符的標簽,將進一步用于計算。我們總是可以選擇在嵌套的if語句或switch case中使用這些值作為不同的條件,但讓我們設計一種將邏輯委托給Enum本身的替代方法。
我們將為每個Enum值定義方法并進行計算。例如:
ADD {
@Override
public int apply(int a, int b) {
return a + b;
}
},
// other operators
public abstract int apply(int a, int b);
然后在Calculator類中,我們可以定義一個執行操作的方法:
public int calculate(int a, int b, Operator operator) { return operator.apply(a, b); }
現在,我們可以通過使用Operator#valueOf()方法將String值轉換為Operator來調用該方法:
@Test
public void test() {
Calculator calculator = new Calculator();
int result = calculator.calculate(3, 4, Operator.valueOf("ADD"));
assertEquals(7, result);
}
命令模式
在前面的討論中,我們已經看到使用工廠類來返回給定運算符的正確業務對象的實例。稍后,業務對象用于在計算器中執行計算。
我們還可以設計一個Calculator#calculate方法來接受可以在輸入上執行的命令。這將是替換嵌套if語句的另一種方法。
我們首先定義我們的Command接口:
public interface Command { Integer execute(); }
接下來,讓我們實現一個AddCommand:
public class AddCommand implements Command {
// Instance variables
public AddCommand(int a, int b) {
this.a = a;
this.b = b;
}
@Override
public Integer execute() {
return a + b;
}
}
最后,讓我們在Calculator中引入一個接受并執行Command的新方法:
public int calculate(Command command) {
return command.execute();
}
接下來,我們可以通過實例化AddCommand調用計算并將其發送到Calculator#calculate方法:
@Test
public void test() {
Calculator calculator = new Calculator();
int result = calculator.calculate(new AddCommand(3, 7));
assertEquals(10, result);
}
規則引擎
當我們最終編寫大量嵌套if語句時,每個條件都描述了一個業務規則,必須對其進行評估才能處理正確的邏輯。規則引擎從主代碼中獲取了這種復雜性。一個RuleEngine評估規則和返回基于輸入的結果。
讓我們通過設計一個簡單的RuleEngine來演示一個例子,該RuleEngine通過一組規則處理Expression并返回所選規則的結果。首先,我們將定義一個Rule接口:
public interface Rule { boolean evaluate(Expression expression); Result getResult(); }
其次,讓我們實現一個RuleEngine:
public class RuleEngine {
private static List rules = new ArrayList<>();
static {
rules.add(new AddRule());
}
public Result process(Expression expression) {
Rule rule = rules
.stream()
.filter(r -> r.evaluate(expression))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("Expression does not matches any Rule"));
return rule.getResult();
}
}
所述RuleEngine接受一個表達對象,并返回結果。現在,讓我們將Expression類設計為一組包含兩個Integer對象的Operator,它將被應用:
public class Expression { private Integer x; private Integer y; private Operator operator; }
最后讓我們定義一個自定義的AddRule類,該類僅在指定ADD操作時進行求值:
public class AddRule implements Rule {
@Override
public boolean evaluate(Expression expression) {
boolean evalResult = false;
if (expression.getOperator() == Operator.ADD) {
this.result = expression.getX() + expression.getY();
evalResult = true;
}
return evalResult;
}
}
我們現在將使用Expression調用RuleEngine:
@Test
public void test() {
Expression expression = new Expression(5, 5, Operator.ADD);
RuleEngine engine = new RuleEngine();
Result result = engine.process(expression);
assertNotNull(result);
assertEquals(10, result.getValue());
}
結論
通過這些設計模式,可以作為我們的ifelse語句的替代方案,具體用哪一種可以根據你的實際業務場景來決定。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/7866.html
摘要:接收布爾型條件和兩個變量作為輸入。進行元素級運算,因此比更常用。比較懶惰,只計算滿足條件的相應輸出變量,而計算所有的輸出變量。如果那么計算和,并輸出在這個例子中,比花費更少的時間,因為他只計算輸出變量中的一個。 IfElse vs Switch IfElse接收布爾型條件和兩個變量作為輸入。 Switch接收一個張量(Tensor)以及兩個變量作為輸入。 Switch進行元素級運算,...
摘要:來源前條來源一書英文版已經出版,這本書的第二版想必很多人都讀過,號稱四大名著之一,不過第二版年出版,到現在已經將近年的時間,但隨著,,,甚至的發布,語言發生了深刻的變化。譯者在這里第一時間翻譯成中文版。供大家學習分享之用。 來源:sjsdfg/effective-java-3rd-chinese前 51 條來源:Effective Java, Third Edition 《Effec...
JS(JavaScript) 語句 一。概述; 1.語句概述; 在JavaScript中,語句使用分號進行分割,可編寫一條語句,也可編寫多條語句條件語句;在JavaScript中根據判斷是執行還是跳過語句循環語句;在JavaScript中判斷是否重復執行語句跳轉語句;在JavaScript中跳轉到語句2.語句塊;在JavaScript中使用一對花括號({})表示一個語句塊3.空語句;空語句允許包...
閱讀 3352·2021-11-25 09:43
閱讀 3143·2021-10-11 10:58
閱讀 2747·2021-09-27 13:59
閱讀 3080·2021-09-24 09:55
閱讀 2172·2019-08-30 15:52
閱讀 1833·2019-08-30 14:03
閱讀 2262·2019-08-30 11:11
閱讀 2027·2019-08-28 18:12