首页 > 解决方案 > 开闭固原则条件失败

问题描述

根据 SOLID 原则,开闭原则说类对扩展是开放的,对修改是封闭的。

所以我可以根据新的 if-else 条件添加新的逻辑吗?

如果我不使用条件,那么我将如何根据哪个条件确定必须应用哪个操作

public interface TemplateClassification {
    QuesObj processTemplate(RawPart rawPart);
}
public class Template1 implements  TemplateClassification{
    
    @Override
    public QuesObj processTemplate(RawPart rawPart) {
        return new QuesObj("Hi header 1"+rawPart.getHead(),"Hi I am footer 1"+rawPart.getFoot());
    }
}


public class Template2 implements  TemplateClassification{
    @Override
    public QuesObj processTemplate(RawPart rawPart) {
        return new QuesObj("Hi header 2"+rawPart.getHead(),"Hi I am footer "+rawPart.getFoot());
    }
}

public class TemplateInfo {

    private TemplateClassification templateClassification;

    public TemplateClassification getTemplateClassification() {
        return templateClassification;
    }

    public void setTemplateClassification(TemplateClassification templateClassification) {
        this.templateClassification = templateClassification;
    }
}
public class TemplateProduct {
    public QuesObj calculateTemplate(TemplateInfo templateInfo,RawPart rawPart){
        QuesObj ques = templateInfo.getTemplateClassification().processTemplate(rawPart);
        return ques;
    }
}
@RestController
class Pg {

    @Autowired
    TemplateInfo templateInfo;

    @Autowired
    TemplateProduct templateProduct;

    public doProcessing(RawPart rawPart){
        QuesObj ques = null;
        if(rawPart.getId() == 1){
          Template1 temp = new Template1(); 
          ques = templateProduct.calculateTemplate(templateInfo,rawPart);
        }
        elseIf(rawPart.getId() == 2){
          Template2 temp = new Template2(); 
          ques = templateProduct.calculateTemplate(templateInfo,rawPart);
        }
        elseIf(tempId == 3){
        // coming soon
        }
    }
}

如何消除 if else 条件,使其遵循开闭原则

标签: javasolid-principles

解决方案


要在 SOLID 中实现“O”,您可以遵循以下内容,其中也包括“S”。

我们将使用多态性和继承。

步骤1 :

创建一个位于负责创建 QuesObj 的类前面的接口。我们将需要这个,因为当 id 为 1,2 或 3 时,代码可以接收创建者(子类)。

重要的是要注意 QuesObj 已被识别,因为它会在您的原始 if 语句中返回,这就是我们被允许继续使用这种方法的原因。

public interface QuesObjCreator {
    QuesObj calculate(RawPart rawPart);
}

第2步:

创建以不同方式创建 QuesObj 的单个类 该类的唯一作用是创建对象。

public class QuesObjCreatorFor1 implements QuesObjCreator {

private TemplateInfo templateInfo;
private TemplateProduct templateProduct;


@Override
public QuesObj calculate(RawPart rawPart) {
    Template1 temp = new Template1();
    return templateProduct.calculateTemplate(templateInfo,rawPart);
}

}

public class QuesObjCreatorFor2 implements QuesObjCreator {

private TemplateInfo templateInfo;
private TemplateProduct templateProduct;


@Override
public QuesObj calculate(RawPart rawPart) {
    Template2 temp = new Template2();
    return templateProduct.calculateTemplate(templateInfo,rawPart);
}

}

第 3 步:

创建工厂以返回 QuesObjCreator。工厂将返回您的主要代码/服务。

public class QuesObjectCreatorFactory {

private static final Map<Integer,QuesObjCreator> quesObjCreatorMap = new HashMap<>();

public QuesObjectCreatorFactory() {
    quesObjCreatorMap.put(1,new QuesObjCreatorFor1());
    quesObjCreatorMap.put(2,new QuesObjCreatorFor2());

}

public static QuesObjCreator getQuesObjCreator(final int number) {
    final QuesObjCreator quesObjCreator = quesObjCreatorMap.get(number);
    if(quesObjCreator == null) {
        throw new IllegalArgumentException("QuesObj for "+number+" does not exist");
    }

    return quesObjCreator;
}

}

第4步:

使用 Factory 创建 QuesObj

public class Pg {

public void doProcessing(RawPart rawPart){
    final QuesObjCreator quesObjCreator = QuesObjectCreatorFactory.getQuesObjCreator(rawPart.getId());
    QuesObj ques = quesObjCreator.calculate(rawPart);
}

}

我们共同实现了所有类的单一职责并解耦。

它易于维护,因为现在您可以添加更多选项来创建 QuesObj,并且不会更改任何代码,从而实现开放可扩展/封闭以进行修改。

这一切都归结为拥有创作者的工厂和地图。必须使用所有创建者实例填充地图。使用 Spring 这很容易,因为 Spring 可以扫描您的项目,查找特定类型的 bean,给您一个 List,然后您可以将其转换为 map。


推荐阅读