假设我有以下代码:
int age=(from user input);
int weight=(from user input);
if(age>60){
if(weight>100){
function1();
}else if(weight<40){
function2();
}else{
function3();
}
}else if(age<20){
if(weight>100){
function4();
}else if(weight<40){
function5();
}else{
function6();
}
}else{
if(weight>100){
function7();
}else if(weight<40){
function8();
}else{
function9();
}
}
问题在于代码模式:
if(weight>100){
//do something different
}else if(weight<40){
//do something different
}else{
//do something different
}
重复,因为有不同的年龄范围。并且我不能将内部if-else包含在单个函数中,因为要做的事情是不同的,即使条件是相同的。有没有办法修改这段代码,以便代码模式:
if(age>60){
//do something different
}else if(age<20){
//do something different
}else{
//do something different
}
和
if(weight>100){
//do something different
}else if(weight<40){
//do something different
}else{
//do something different
}
只会出现一次?
答案 0 :(得分:1)
没有看到你的所有函数1-9做什么(这可能是Stack Overflow的代码太多了),很难给出明确的答案。如果function1
,function2
和function3
在age > 60
和function1
,function4
和function7
时都做了一些常见的事情在weight > 100
时,所有人都会做一些常见的事情,然后你可以将这些功能分开,然后将公共部分重新组合成新的方法。
如果你真的有9个不同的功能没有任何共同点,那么就没有真正好的解决方案。您可以尝试设置将所有9种组合映射到函数的地图:
Map<String, Runnable> functions = new HashMap<>();
functions.put("senior_heavy") = this::function1;
functions.put("senior_medium") = this::function2;
functions.put("senior_light") = this::function3;
functions.put("middleaged_heavy") = this::function4;
...
functions.put("child_light") = this::function9;
[你必须考虑更好的名字,因为一个20岁的孩子并不完全中年。]
然后:
String ageString;
// set this to "senior", "middleaged", or "child"
String weightString;
// set this to "heavy", "medium", or "light"
functions.get(ageString + "_" + weightString).run();
Runnable
是不带参数且不返回结果的方法的接口。 (对于带参数和/或返回结果的函数,还有其他功能接口类型可供使用。或者您可以在smac89的答案中定义自己的类型,这样可以为功能接口类型提供更具描述性的名称。 )this::function1
是对属于当前对象function1
的{{1}}的引用;如果this
为function1
,则需要说static
。
这将消除重复的ThisClass::function1
模式,但这不是一个漂亮的解决方案。如果我正在审查您的代码,我不会抱怨您的原始代码,因为替代方案也不是很好。 (if
的二维数组是另一种选择。)
答案 1 :(得分:1)
不是特别优雅。简而言之,构成一个执行内部条件检查的方法,并允许在不同情况下传递“动作”
// Change to use other proper functional interface. Using Runnable
// just to align with your sample code.
doOnWeight(int weight,
Runnable overWeightAction,
Runnable normalWeightAction,
Runnable underWeightAction) {
if(weight>100){
overWeightAction.apply();
}else if(weight<40){
underWeightAction.apply();
}else{
normalWeightAction.apply();
}
}
//.......
// your original code, I assume your functions are instance methods
if(age>60){
doOnWeight(weight, this::function1, this::function3, this::function2)
}else if(age<20){
doOnWeight(weight, this::function4, this::function6, this::function5)
}else{
doOnWeight(weight, this::function7, this::function9, this::function8)
}
答案 2 :(得分:1)
public class User {
int age;
int weight;
}
@FunctionalInterface
public interface WeightFunction {
void perform(User user);
}
@FunctionalInterface
public interface AgeFunction {
WeightFunction getWeightFunction(User user);
}
public class Age60Function implements AgeFunction {
@Override
public WeightFunction getWeightFunction(User user) {
String desc = "Age 60 ";
if (user.weight > 100) {
return weightUser -> System.out.println(desc + "Age > 100");
} else if (user.weight < 40) {
return weightUser -> System.out.println(desc + "Age < 40");
}
return weightUser -> System.out.println(desc + "100 > Age > 40");
}
}
然后你可以创建外部if和创建相关的AgeFunction并执行该功能。
另一个建议如果重量类别不等于所有年龄限制,因为此示例重量类别100 +,40-和100>年龄> 40,您可以按照以下实施。
public interface AdvanceAgeFunction {
WeightFunction get100PlusWeightFunction(User user);
WeightFunction get40MinusWeightFunction(User user);
WeightFunction getWeightFunction(User user);
}
答案 3 :(得分:0)
我能想到的最好的就是:
interface WeightFunc {
void function();
}
public static final List<WeightFunc> weightFuncs = Arrays.asList(weightFunc1, weightFunc2,...);
现在在你的方法中
List<WeightFunc> choices = null;
if(age>60){
choices = Arrays.asList(weightFuncs.get(0), weightFuncs.get(1), ...);
// 1, 2, 3
}else if(age<20){
choices = Arrays.asList(weightFuncs.get(3), weightFuncs.get(4), ...);
// 4, 5, 6
}else{
choices = Arrays.asList(weightFuncs.get(6), weightFuncs.get(7), ...);
// 7, 8, 9
}
WeightFunc choice = null;
if(weight>100){
choice = choices.get(0);
//do something different
}else if(weight<40){
choice = choices.get(1);
//do something different
}else{
choice = choices.get(2);
//do something different
}
现在打电话给:
choice.function();
IMO,我更喜欢你的初始方法
答案 4 :(得分:0)
我没有完全明白你的问题,但从我看到的情况来看,似乎你不会丢失冗余代码,所以这就是我的建议。
创建临时变量假设
int ageGroup;
和计算权重计算的函数,其中ageGroup作为参数传递
void CheckWeight(int ageGroup)
{
}
您可以通过创建另一个功能来进一步减少冗余代码,以管理在切换条件下在功能1-9中完成的工作。
您的最终代码块将如下所示:
if(age>60){
CheckWeight(1);
}else if(age<20){
CheckWeight(2)
}else{
CheckWeight(3)
}
void CheckWeight(int ageGroup)
{
if(weight>100){
Compute(ageGroup,1);
}else if(weight<40){
Compute(ageGroup,2);
}else{
Compute(ageGroup,3);
}
}
void Compute(int ageGroup,int weightGroup)
{
switch(ageGroup)
{
case 1:
switch(weightGroup)
{
case 1:
//func1;
break;
case 2:
//func 2;
break;
.
.
}
break;
case 2:
.
.
.
}
}
这是我能想到的最好的,可能还有其他实现。