我有一个if else语句,它可能会在不久的将来增长。
public void decide(String someCondition){
if(someCondition.equals("conditionOne")){
//
someMethod("someParameter");
}else if(someCondition.equals("conditionTwo")){
//
someMethod("anotherParameter");
}
.
.
else{
someMethod("elseParameter");
}
}
因为,这看起来已经很乱了,我想如果我能在这里应用任何设计模式会更好。我研究了战略模式,但我不确定这是否会降低其他条件。有什么建议吗?
Martin Fowler的一般建议是用多态替换条件。
就设计模式而言,这通常是策略模式用策略替换条件逻辑。
如果您有一个小的、有限的条件集,我建议使用enum来实现策略模式(在enum中提供一个抽象方法,并为每个常量覆盖它)。
public enum SomeCondition{
CONDITION_ONE{
public void someMethod(MyClass myClass){
//...
}
},
CONDITION_TWO{
public void someMethod(MyClass myClass){
}
}
public abstract void someMethod(MyClass myClass);
}
public class MyClass{
//...
public void decide(SomeCondition someCondition){
someCondition.someMethod(this);
}
}
如果它真的只是一个你想要选取的参数,那么你可以这样定义枚举:
public enum SomeCondition{
CONDITION_ONE("parameterOne"),
CONDITION_TWO("parameterTwo");
private final String parameter;
private SomeCondition(String parameter){
this.parameter = parameter;
}
public String getParameter(){
return parameter;
}
}
public class MyClass{
//...
public void decide(SomeCondition someCondition){
someMethod(someCondition.getParameter());
}
}
假设我们有这样的代码(与您的代码相同):
public void decide(String someCondition) {
if(someCondition.equals("conditionOne")) {
someMethod("someParameter");
}
else if(someCondition.equals("conditionTwo")) {
someMethod("anotherParameter");
}
else {
someMethod("elseParameter");
}
}
假设您不想重构应用程序的其他部分,也不想更改方法签名,那么有几种可能的重构方法:
警告-您应该使用上述模式的通用版本。< br >我展示了非通用的,因为这样更容易阅读。
策略工厂方法
我们可以使用策略和工厂方法模式。我们还利用了多态性。
private final StrategyConditionFactory strategyConditionFactory = new StrategyConditionFactory();
public void decide(String someCondition) {
Strategy strategy = strategyConditionFactory.getStrategy(someCondition)
.orElseThrow(() -> new IllegalArgumentException("Wrong condition"));
strategy.apply();
}
最好以工厂中包含其他条件的方式设计它,并且开发人员故意调用它。在这种情况下,当条件不满足时,我们会抛出异常。或者,我们可以完全按照它所讨论的方式编写它。如果你愿意而不是 .orElseThrow(() -
的工厂方法。
public class StrategyConditionFactory {
private Map<String, Strategy> conditions = new HashMap<>();
public StrategyConditionFactory() {
conditions.put("conditionOne", new ConditionOneStrategy());
conditions.put("conditionTwo", new ConditionTwoStrategy());
//It is better to call else condition on purpose than to have it in the conditional method
conditions.put("conditionElse", new ElseStrategy());
//...
}
public Optional<Strategy> getStrategy(String condition) {
return Optional.ofNullable(conditions.get(condition));
}
}
策略界面:
public interface Strategy {
void apply();
}
实现:
public class ConditionOneStrategy implements Strategy {
@Override
public void apply() {
//someMethod("someParameter");
}
}
public class ConditionTwoStrategy implements Strategy {
@Override
public void apply() {
//someMethod("anotherParameter")
}
}
public class ElseStrategy implements Strategy {
@Override
public void apply() {
//someMethod("elseParameter")
}
}
用法(简体):
public void strategyFactoryApp() {
//...
decide("conditionOne");
decide("conditionTwo");
decide("conditionElse");
//...
}
策略工厂方法-这种特殊情况(仅参数更改)
我们可以使用这样一个事实,即在这种情况下,我们总是调用相同的方法,仅参数更改
我们使用getParameter()方法将基本策略接口更改为抽象类,并对该抽象类进行新的实现。其他代码保持不变。
public abstract class Strategy {
public abstract String getParameter();
public void apply() {
someMethod(getParameter());
}
private void someMethod(String parameter) {
//someAction
}
}
实现:
public class CondtionOneStrategy extends Strategy {
@Override
public String getParameter() {
return "someParameter";
}
}
public class CondtionTwoStrategy extends Strategy {
@Override
public String getParameter() {
return "anotherParameter";
}
}
public class ElseStrategy extends Strategy {
@Override
public String getParameter() {
return "elseParameter";
}
}
enum enum有点像“工厂”< br >我们可以使用Enum来实现策略,我们可以使用Enum中的valueOf()来代替工厂方法。
public void decide(String someCondition) {
ConditionEnum conditionEnum = ConditionEnum.valueOf(someCondition);
conditionEnum.apply();
}
条件枚举:
public enum ConditionEnum {
CONDITION_ONE {
@Override
public void apply() {
//someMethod("someParameter");
}
},
CONDITION_TWO {
@Override
public void apply() {
//someMethod("anotherParameter");
}
},
CONDITION_ELSE {
@Override
public void apply() {
//someMethod("elseParameter");
}
};
//...more conditions
public abstract void apply();
}
用法(简体):
public void enumFactoryApp() {
//...
decide("CONDITION_ONE");
decide("CONDITION_TWO");
decide("CONDITION_ELSE");
//...
}
请注意,当枚举类型没有具有指定名称的常量时,您将得到
IllegalArgumentException
。
命令工厂
策略和命令之间的区别在于命令也保存状态,所以如果你有例如compute(int a,int b,String someCondition),并且你想用策略重构它,包括它的签名更改,你可以用命令将其减少为compute(int a,int b,ComputeStrategy computeStrategy),你可以把它减少到一个参数compute(ComputeCommand computeCommand)。在这种情况下,我们还利用了类似于策略模式情况的多态性。
CommandConditionFactory commandConditionFactory = new CommandConditionFactory();
public void decide(String someCondition) {
Command command = commandConditionFactory.getCommand(someCondition)
.orElseThrow(() -> new IllegalArgumentException("Wrong condition"));
command.apply();
}
最好以工厂中包含其他条件的方式设计它,并且开发人员故意调用它。在这种情况下,当条件不满足时,我们会抛出异常。或者,我们可以完全按照它所讨论的方式编写它。如果你愿意而不是
.orElseThrow(() -
CommandConditionFactory(工厂方法):
public class CommandConditionFactory {
private Map<String, Command> conditions = new HashMap<>();
public CommandConditionFactory() {
conditions.put("conditionOne", new ConditionOneCommand("someParameter"));
conditions.put("conditionTwo", new ConditionTwoCommand("anotherParameter"));
//It is better to call else condition on purpose than to have it in the conditional method
conditions.put("conditionElse", new ElseCommand("elseParameter"));
//...
}
public Optional<Command> getCommand(String condition) {
return Optional.ofNullable(conditions.get(condition));
}
}
命令界面:
public interface Command {
void apply();
}
实现(有一些冗余,但它是为了展示命令在更一般的情况下应该是如何看的,其中我们有三个不同的方法而不是某些方法()):
public class ConditionOneCommand implements Command {
private final String parameter;
public ConditionOneCommand(String parameter) {
this.parameter = parameter;
}
@Override
public void apply() {
//someMethod(parameter);
}
}
public class ConditionTwoCommand implements Command {
private final String parameter;
public ConditionTwoCommand(String parameter) {
this.parameter = parameter;
}
@Override
public void apply() {
//someMethod(parameter);
}
}
public class ElseCommand implements Command {
private final String parameter;
public ElseCommand(String parameter) {
this.parameter = parameter;
}
@Override
public void apply() {
//someMethod(parameter);
}
}
用法(简体):
public void commandFactoryApp() {
//...
decide("conditionOne");
decide("conditionTwo");
decide("conditionElse");
//...
}
命令工厂-这种特殊情况
这实际上不是一个真正的命令模式,只是一个派生模式。它利用了这样一个事实:在这种情况下,我们总是调用相同的方法someMethod(参数),而只有参数发生了变化
抽象类:
public abstract class Command {
abstract void apply();
protected void someMethod(String parameter) {
//someAction
}
}
实施(所有3个有条件的情况相同):
public class CommandImpl extends Command {
private final String parameter;
public CommandImpl (String parameter) {
this.parameter = parameter;
}
@Override
public void apply(){
someMethod(parameter);
}
}
工厂,请注意,只有一个命令实现,只有参数更改:
public class CommandConditionFactory {
Map<String, Command> conditions = new HashMap<>();
public CommandConditionFactory() {
conditions.put("conditionOne", new CommandImpl("someParameter"));
conditions.put("conditionTwo", new CommandImpl("anotherParameter"));
//It is better to call else condition on purpose than to have it in the conditional method
conditions.put("conditionElse", new CommandImpl("elseParameter"));
//...
}
public Optional<Command> getCommand(String condition) {
return Optional.ofNullable(conditions.get(condition));
}
}
嵌套的if < br >注意,即使你有嵌套的if,有时也可以重构它们并使用上面提到的技术之一。假设我们有以下代码:
public void decide2(String someCondition, String nestedCondition) {
if(someCondition.equals("conditionOne")) {
if(nestedCondition.equals("nestedConditionOne")){
someLogic1();
}
else if(nestedCondition.equals("nestedConditionTwo")){
someLogic2();
}
}
else if(someCondition.equals("conditionTwo")) {
if(nestedCondition.equals("nestedConditionThree")){
someLogic3();
}
else if(nestedCondition.equals("nestedConditionFour")){
someLogic4();
}
}
}
您可以使用数学逻辑规则重构它:
public void decide2(String someCondition, String nestedCondition) {
if(someCondition.equals("conditionOne")
&& nestedCondition.equals("nestedConditionOne")) {
someLogic1();
}
else if(someCondition.equals("conditionOne")
&& nestedCondition.equals("nestedConditionTwo")) {
someLogic2();
}
else if(someCondition.equals("conditionTwo")
&& nestedCondition.equals("nestedConditionThree")) {
someLogic3();
}
else if(someCondition.equals("conditionTwo")
&& nestedCondition.equals("nestedConditionFour")) {
someLogic4();
}
}
然后你可以使用策略、枚举或命令。你只有一对字符串
决策表
当您有无法重构的嵌套ifs时,您可以实现自己的决策表或使用一些现成的决策表解决方案。我不会在那里给出实现。
规则引擎
当您有嵌套的ifs无法如前所述重构时,您也可以实现自己的简单规则引擎。只有当您有许多嵌套的ifs时才应该使用它,否则它是形式对内容的胜利。
对于非常复杂的业务逻辑,有专业的规则引擎,如Drools。
我不会在那里给出实现。
还有一件事
在您给出的示例中,很有可能有人引入了这些 ifs,但它们完全是多余的。我们可以通过尝试重构决定方法签名来检查它,使其采用其他参数并重构调用我们方法的周围代码。通过这样做,我们摆脱了我们的工厂方法。有一些示例展示了当这些 if 是冗余时代码的外观。
战略< br >决策方法:
public void decide(Strategy strategy) {
strategy.apply();
}
用法(简体):
public void strategyApp() {
//...
decide(new ConditionOneStrategy());
decide(new ConditionTwoStrategy());
decide(new ElseStrategy());
//...
}
枚举
决定方法:
public void decide(ConditionEnum conditionEnum) {
conditionEnum.apply();
}
用法(简体):
public void enumApp() {
//...
decide(ConditionEnum.CONDITION_ONE);
decide(ConditionEnum.CONDITION_TWO);
decide(ConditionEnum.CONDITION_ELSE);
//...
}
命令
决定方法:
public void decide(Command command) {
command.apply();
}
用法(简体):
public void commandApp() {
//...
decide(new ConditionOneCommand("someParameter"));
decide(new ConditionTwoCommand("anotherParameter"));
decide(new ElseCommand("elseParameter"));
//...
}
实际上这是非常特殊的情况,在某些情况下,例如我们必须使用像String这样的简单类型,因为它来自外部系统或条件基于输入中的整数,因此我们无法轻松重构代码。
这是Refactoring to Patterns书中使用命令替换条件调度程序的经典版本。
基本上,您为旧的if/else组中的每个代码块创建一个< code>Command对象,然后创建这些命令的映射,其中键是您的条件字符串
interface Handler{
void handle( myObject o);
}
Map<String, Handler> commandMap = new HashMap<>();
//feel free to factor these out to their own class or
//if using Java 8 use the new Lambda syntax
commandMap.put("conditionOne", new Handler(){
void handle(MyObject o){
//get desired parameters from MyObject and do stuff
}
});
...
然后不是你的if/否则代码,而是:
commandMap.get(someCondition).handle(this);
现在,如果以后需要添加新命令,只需添加到散列中即可。
如果要处理默认情况,可以使用<code>Null Object</code>模式来处理条件不在Map中的情况。
Handler defaultHandler = ...
if(commandMap.containsKey(someCondition)){
commandMap.get(someCondition).handle(this);
}else{
defaultHandler.handle(this);
}
基于SO上的各种线程(例如。用设计模式替换多个If\Else或用模式替换if else语句)我知道我可以用< code >命令模式替换多个< code>if\else语句。 但对于我这个级别的人来说,答案远不是简单或详细的。我会有60个会阻塞。我做了一些研究,发现命令模式是最好的。搜索关于如何一步一步的教程似乎很难,因为我发现的都是复杂的事情。相信我,如果我没有在网上做大量的重新搜索和放弃,我不会
问题内容: 我需要使用REPLACE编写一条sql更新语句。字符串看起来像’SE * 88 * 000000001’。我需要替换两个星号“ *”之间的数字。除了要替换的数字始终在两个星号之间之外,这里没有其他模式。在这种情况下可以使用通配符吗? 感谢你的帮助。 谢谢! 问题答案: 或者,如果要替换的是一个特定的数字,那么它将更加简单:
我用R编写了以下代码,效果很好。但是,假设我必须对具有多个级别的因子变量应用类似的代码(
问题内容: 我想用Python编写一个函数,该函数根据输入索引的值返回不同的固定值。 在其他语言中,我将使用语句,但是Python似乎没有语句。在这种情况下,推荐的Python解决方案是什么? 问题答案: 你可以使用字典:
我们的老师让我们创建一个关于给定情况的java程序,即使用if/else的每小时工资率,这就是我得出的结果,我对此感到高兴(我只是一个初学者)。接下来的指令是用switch语句替换if/else。他还没有讨论switch语句。我试图搜索它们,但我无法理解。请帮忙。非常感谢。 这就是确切的指示:1。使用if/else构造编写一个程序,该程序将根据工作小时数计算人员工资。注意ff:工资率为每小时35菲
我想用Python编写一个函数,根据输入索引的值返回不同的固定值。 在其他语言中,我会使用或语句,但Python似乎没有语句。在这个场景中,推荐的Python解决方案是什么?