Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 方法,该方法依赖于对策略模式的嵌套开关重构_Java_Design Patterns_Switch Statement_Strategy Pattern - Fatal编程技术网

Java 方法,该方法依赖于对策略模式的嵌套开关重构

Java 方法,该方法依赖于对策略模式的嵌套开关重构,java,design-patterns,switch-statement,strategy-pattern,Java,Design Patterns,Switch Statement,Strategy Pattern,对于遇到的特定问题,我在实施策略模式时遇到了问题 我基本上有一个方法来比较不同的值。除了这两个值之外,这个方法还依赖于两个额外的参数来确定我应该做的比较:一个运算符(等于,不等于,…)和一个类型(字符串,双精度) 它基本上是一个开关,依赖于另一个开关的结果 让我举例说明: 公共枚举类型{ 一串 布尔, 双重的 } 公共枚举运算符{ 等于(新类型[]{Type.STRING,Type.BOOLEAN}), NOT_EQUALS(新类型[]{Type.STRING,Type.BOOLEAN});

对于遇到的特定问题,我在实施策略模式时遇到了问题

我基本上有一个方法来比较不同的值。除了这两个值之外,这个方法还依赖于两个额外的参数来确定我应该做的比较:一个运算符(等于,不等于,…)和一个类型(字符串,双精度) 它基本上是一个开关,依赖于另一个开关的结果

让我举例说明:

公共枚举类型{
一串
布尔,
双重的
}
公共枚举运算符{
等于(新类型[]{Type.STRING,Type.BOOLEAN}),
NOT_EQUALS(新类型[]{Type.STRING,Type.BOOLEAN});
私有类型[]允许的类型;
运算符(类型[]允许的类型){
this.allowedTypes=allowedTypes;
}
公共列表getAllowedTypes(){
返回数组.asList(allowedTypes);
}
}
公共类求值器{
公共布尔求值(字符串值1、字符串值2、运算符、类型){
开关(操作员){
案例等于:
返回doEqualComparison(值1、值2、类型);
}
返回null;
}
私有布尔doEqualComparison(字符串值1、字符串值2、类型){
//此处的代码用于检查参数是否正确(非空等)
开关(类型){
大小写字符串:
返回值1.等于(值2);
双格:
返回Double.parseDouble(value1)=Double.parseDouble(value2);
}
返回null;
}
}
测试呢

公共类评估测试{
@试验
公共资产评估(){
Evaluator Evaluator=新的Evaluator();
//检查字符串
Assert.assertTrue(evaluator.evaluate(“100”,“100”,Operator.EQUALS,Type.STRING));
Assert.assertFalse(evaluator.evaluate(“100.00”、“100”、Operator.EQUALS、Type.STRING));
//双重检查
Assert.assertTrue(evaluator.evaluate(“100”,“100”,Operator.EQUALS,Type.DOUBLE));
Assert.assertTrue(evaluator.evaluate(“100.00”、“100”、Operator.EQUALS、Type.DOUBLE));
}
}
这很好,但是有两个(本质上是嵌套的)switch语句似乎不是一个非常干净和经得起未来考验的解决方案,如果我们添加了很多类型和运算符,事情会变得非常糟糕,非常快,所以我的第一次重构是将第一个switch(运算符)更改为一个策略

公共类EqualComparisonStrategy实现比较策略{
@凌驾
公共布尔比较(字符串值1、字符串值2、类型){
//这是我的问题
开关(条件类型){
大小写字符串:
返回值1.等于(条件值);
双格:
返回Double.parseDouble(value1)=Double.parseDouble(value2);
}
返回null;
}
@凌驾
公共布尔接受(运算符){
返回运算符==运算符.EQUAL;
}
}
虽然这个解决方案并不“太”糟糕,但我想我也想将第二个开关(我的评论是)外部化,问题是它的实现依赖于第一个(操作符)。 我想到了一些类似StringEqualComparisonStrategy的东西,要么是由工厂制定的,要么就是在accept方法中做更多的事情

//接受方法的片段(而不是工厂)
@凌驾
公共布尔接受(运算符,类型){
返回运算符==operator.EQUAL&&type==type.STRING;
}
但这会创建M*N策略,并很快失控(我有大约8个操作符,有3种类型,结果是24个策略) 鉴于我希望这是一个未来的证明,这不是最好的解决方案IMHO

我确信一定有一种模式可以解决这个问题,但我没有看到它。(我不是模式英雄)


有人能帮忙吗?

当我读到你的问题时,首先想到的是装饰图案。
您可以使用特定用例所需的功能来装饰一个非常基本的评估器。尽管如此,您仍然需要相当数量的装饰器,但如果您做得正确,您可能会得到一个非常灵活的解决方案。

如果您的
评估
方法总是将
字符串作为输入,那么为什么您需要对它们进行不同的比较?我的想法是,
“3.1415”。equals(“3.1415”)
应该与
((Double)3.1415)相同。equals((Double)3.1415)
正如我的示例代码所示,“40.0”在转换为双倍时不会等于“40”。考虑字符串是因为它存储在数据库中,虽然乍一看它似乎是装饰性的,但在我看来,我从来没有向方法中添加行为,而是选择基于上一个行为的行为,这对我来说不像装饰器(添加新行为而不修改现有行为)。事实上,我不是模式英雄,但这就是我所记得的。也许你可以用一个快速的例子来详细说明你的答案(即使伪代码也足够了)?