SOLID — От нуля до картошки 2

Mar 30 2023
О Принципе Открытости/Закрытости (OCP) В этой статье о «SOLID» рассказывается на примере. Если вы еще не читали часть 1 или не знаете, что такое принцип единой ответственности, прочтите часть 1. Сегодня я расскажу о принципе Open/Closed (OCP).

О принципе открытия/закрытия (OCP)

В этой статье о «SOLID» рассказывается на примере. Если вы еще не читали часть 1 или не знаете, что такое принцип единой ответственности , прочитайте часть 1 .

Сегодня я расскажу о принципе Open/Closed (OCP). В OCP класс должен быть открыт для расширения, но закрыт для модификации. Этот принцип побуждает нас писать код таким образом, чтобы его можно было легко расширять без изменения существующего кода.

В контексте класса Studentмы должны спроектировать класс таким образом, чтобы мы могли добавлять новые функции или поведения к объекту ученика без необходимости изменять существующий код класса. Например, мы можем использовать наследование для создания разных типов студентов (например, онлайн-студентов или иностранных студентов), которые наследуются от базового Studentкласса.

Вы не понимаете, как это будет в реальном времени? Не волнуйтесь, вы поймете после прочтения статьи.

Допустим, у нас есть Studentкласс с методом, который вычисляет средний балл (GPA) учащегося на основе его оценок:

class Student(val name: String, val grades: List<Double>) {
    fun calculateGPA(): Double {
        var sum = 0.0
        for (grade in grades) {
            sum += grade
        }
        return sum / grades.size
    }
}

class Student(val name: String, val grades: List<Pair<Double, Int>>) {
    fun calculateGPA(): Double {
        var sum = 0.0
        var creditSum = 0
        for ((grade, credits) in grades) {
            sum += grade * credits
            creditSum += credits
        }
        return sum / creditSum
    }
}

Итак, давайте найдем лучший способ с точки зрения OCP, поэтому я реорганизую класс выше, используя наследование, и создам новый подкласс, который добавляет новую функциональность:

open class Student(val name: String, val grades: List<Double>) {
    open fun calculateGPA(): Double {
        var sum = 0.0
        for (grade in grades) {
            sum += grade
        }
        return sum / grades.size
    }
}

class WeightedGPAStudent(name: String, grades: List<Pair<Double, Int>>) : Student(name, grades) {
    override fun calculateGPA(): Double {
        var sum = 0.0
        var creditSum = 0
        for ((grade, credits) in grades) {
            sum += grade * credits
            creditSum += credits
        }
        return sum / creditSum
    }
}

Этот подход соответствует принципу открытости/закрытости , поскольку позволяет расширять функциональность класса Studentбез изменения существующего кода. Базовый класс закрыт для модификации, но открыт для расширения посредством наследования.

Надеюсь, вы лучше поймете принцип Open/Closed , и эта статья будет вам полезна.