Как правильно реализовать принцип «Открыто-закрыто»?

#java #open-closed-principle

Вопрос:

У меня есть класс, и внутри него у меня есть метод, который отвечает за шаблон процесса, основанный на определенном условии

 public doProcessing(@RequestParam("tempId") int TempId){
if(tempId == 1){
//some logic
}
elseIf(tempId == 2){
// another type of logic
}
elseIf(tempId == 3){
// some more complex type of logic
}
}
 

Каждую неделю на картинке появлялся новый шаблон, и я должен добавить его, если-иначе

Нет, мой вопрос заключается в том, что в соответствии с принципом SOLID класс принципа открытия и закрытия открыт для расширения и закрыт для модификации.

Итак, мне разрешено добавлять новую логику, основанную на новых условиях «если бы еще»?

Вот мой полный внешний вид кода

 public interface TemplateClassification {
    QuesObj processTemplate();
}


public class Template1 implements  TemplateClassification{
    
    @Override
    public QuesObj processTemplate() {
        return new QuesObj("Hi I am header 1","Hi I am footer 1");
    }
}


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

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){
        QuesObj ques = templateInfo.getTemplateClassification().processTemplate();
        return ques;
    }
}

@RestController
class Pg {

    @Autowired
    TemplateInfo templateInfo;

    @Autowired
    TemplateProduct templateProduct;

    public doProcessing(@RequestParam("tempId") int TempId){
        QuesObj ques = null;
        if(tempId == 1){
          Template1 temp = new Template1(); 
          ques = templateProduct.calculateTemplate(templateInfo);
        }
        elseIf(tempId == 2){
          Template2 temp = new Template2(); 
          ques = templateProduct.calculateTemplate(templateInfo);
        }
        elseIf(tempId == 3){
        // coming soon
        }
    }
}

 

Должен ли я использовать Class.forName , а затем создать новый экземпляр для него, будет ли это хорошей практикой?

 Class c = Class.forName("ocp." state);

TemplateClassification ref = (TemplateClassification)c.newInstance();
 

Ответ №1:

Это отличный пример, демонстрирующий принцип «открыто-закрыто» в действии. Постоянное добавление новых утверждений IF, я думаю, нарушает закрытую часть этого принципа. В основном потому, что вы изменяете код, относящийся к этому классу.

Один из способов заставить его лучше соблюдать принцип открытия-закрытия-это использовать шаблон обратного вызова. Например, класс может взять целое число и обратный вызов и добавить его в свой список процессоров. Ниже приведен пример кода.

 public void addProcessor(Integer tempId, Consumer<Integer> processor)
    procesorMap.put(tempId, processor);
}

public void doProcessing(@RequestParam("tempId") int TempId){
    if(processorMap.contains(TempId) {
        processorMap.get(TempId).accept(TempId);
    }
}
 

Таким образом, в этом случае код для этого класса остается закрытым для изменения, но вы можете расширить то, что он делает (в этом случае добавьте больше кода процессора для разных идентификаторов).

Комментарии:

1. Я не понял кодовую часть @Jose Martinez

2. @Начинающий проверьте сейчас. Не хватало public void только этих методов. Таким образом, по сути, код какой-то другой фрагмент кода может вызвать addProcessor метод для добавления новых процессоров TempId.

3. Но если я присмотрюсь, я верю addProcessor , что глубоко внутри работает то же if-else самое, что и при сохранении соответствующего процесса с идентификатором шаблона на КАРТЕ

4. Привет, я обновил свой полный код @Jose Martinez

5. Принцип «открыто-закрыто» применяется именно к этому классу. Вам, как разработчику приложения, все еще нужен способ предоставить этому классу идентификатор TempId и метод обратного вызова…. через метод addProcessor. Это может быть сделано другим фрагментом кода, чья работа заключается в регистрации процессоров. Все утверждения «ЕСЛИ» исчезли. Тесты для каждой части кода становятся проще. Вы можете добавлять новые процессоры, не беспокоясь о нарушении функциональности класса. Каждая часть становится гипер сфокусированной на том, что ей нужно делать… и вам нужно только кормить ее новыми процессорами.