Рубрики
Без рубрики

Принцип открытия/закрытия в Java

Исследуйте принцип открытия/закрытия (OCP) как один из ОСНОВНЫХ принципов объектно-ориентированного программирования в Java.

Автор оригинала: baeldung.

1. Обзор

В этом уроке мы обсудим принцип открытия/закрытия (OCP) как один из ОСНОВНЫХ принципов объектно-ориентированного программирования.

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

2. Принцип открытия/закрытия

Как следует из названия, этот принцип гласит, что объекты программного обеспечения должны быть открыты для расширения, но закрыты для модификации. В результате, когда бизнес-требования изменяются, сущность может быть расширена, но не изменена.

Для иллюстрации ниже мы сосредоточимся на том, как интерфейсы являются одним из способов следовать OCP.

2.1. Несоответствие требованиям

Давайте рассмотрим, что мы создаем приложение-калькулятор, которое может иметь несколько операций, таких как сложение и вычитание.

Прежде всего, мы определим интерфейс верхнего уровня- CalculatorOperation :

public interface CalculatorOperation {}

Давайте определим Дополнение класс, который бы добавил два числа и реализовал C работа калькулятора :

public class Addition implements CalculatorOperation {
    private double left;
    private double right;
    private double result = 0.0;

    public Addition(double left, double right) {
        this.left = left;
        this.right = right;
    }

    // getters and setters

}

На данный момент у нас есть только один класс Сложение, поэтому нам нужно определить другой класс с именем Вычитание :

public class Subtraction implements CalculatorOperation {
    private double left;
    private double right;
    private double result = 0.0;

    public Subtraction(double left, double right) {
        this.left = left;
        this.right = right;
    }

    // getters and setters
}

Теперь давайте определим наш основной класс, который будет выполнять наши операции с калькулятором:

public class Calculator {

    public void calculate(CalculatorOperation operation) {
        if (operation == null) {
            throw new InvalidParameterException("Can not perform operation");
        }

        if (operation instanceof Addition) {
            Addition addition = (Addition) operation;
            addition.setResult(addition.getLeft() + addition.getRight());
        } else if (operation instanceof Subtraction) {
            Subtraction subtraction = (Subtraction) operation;
            subtraction.setResult(subtraction.getLeft() - subtraction.getRight());
        }
    }
}

Хотя это может показаться прекрасным, это не очень хороший пример OCP. Когда появляется новое требование добавления функций умножения или деления, у нас нет другого способа, кроме как изменить метод calculate класса Calculator .

Следовательно, мы можем сказать, что этот код не соответствует OCP.

2.2. Соответствие требованиям OCP

Как мы уже видели, наше приложение для калькулятора еще не совместимо с OCP. Код в методе calculate будет меняться с каждым входящим новым запросом на поддержку операций. Итак, нам нужно извлечь этот код и поместить его в слой абстракции.

Одним из решений является делегирование каждой операции в соответствующий класс:

public interface CalculatorOperation {
    void perform();
}

В результате Дополнение класс может реализовать логику сложения двух чисел:

public class Addition implements CalculatorOperation {
    private double left;
    private double right;
    private double result;

    // constructor, getters and setters

    @Override
    public void perform() {
        result = left + right;
    }
}

Аналогично, обновленный класс Subtraction будет иметь аналогичную логику. И аналогично Сложению и вычитанию , в качестве нового запроса на изменение мы могли бы реализовать логику деления :

public class Division implements CalculatorOperation {
    private double left;
    private double right;
    private double result;

    // constructor, getters and setters
    @Override
    public void perform() {
        if (right != 0) {
            result = left / right;
        }
    }
}

И, наконец, наши Калькулятор классу не нужно реализовывать новую логику, поскольку мы вводим новые операторы:

public class Calculator {

    public void calculate(CalculatorOperation operation) {
        if (operation == null) {
            throw new InvalidParameterException("Cannot perform operation");
        }
        operation.perform();
    }
}

Таким образом, класс закрыт для модификации, но открыт для расширения.

3. Заключение

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

Как всегда, код доступен на GitHub .