SOLID — จากศูนย์ถึงมันฝรั่ง 2

Mar 30 2023
เกี่ยวกับ Open/Closed Principle (OCP) บทความนี้จะอธิบายเกี่ยวกับ 'SOLID' ในแง่ของตัวอย่าง หากคุณยังไม่ได้อ่านส่วนที่ 1 หรือหากคุณไม่ทราบว่าหลักการความรับผิดชอบเดียวคืออะไร โปรดอ่านส่วนที่ 1 วันนี้ผมจะอธิบายเกี่ยวกับ Open/Closed Principle (OCP)

เกี่ยวกับหลักการเปิด/ปิด (OCP)

บทความนี้อธิบายเกี่ยวกับ'SOLID'ในแง่ของตัวอย่าง หากคุณยังไม่ได้อ่านส่วนที่ 1 หรือหากคุณไม่ทราบว่าหลักการความรับผิดชอบคนเดียวคืออะไรโปรดอ่านส่วนที่ 1

วันนี้ผมจะอธิบายเกี่ยวกับOpen/Closed Principle (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ดังนั้น ฉันจึงทำการ refactor เหนือคลาสโดยใช้การสืบทอดและสร้างคลาสย่อยใหม่ที่เพิ่มฟังก์ชันใหม่:

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คลาสได้โดยไม่ต้องแก้ไขโค้ดที่มีอยู่ คลาสพื้นฐานถูกปิดสำหรับการแก้ไข แต่เปิดให้ขยายผ่านการสืบทอด

หวังว่าคงจะเข้าใจมากขึ้นเกี่ยวกับหลักการเปิด/ปิด และบทความนี้จะเป็นประโยชน์สำหรับคุณ