Open-Closed Principle (OCP)
Objects or entities should be open for extension but closed for modification.
class ควรเปิดเพื่อขยาย แต่ปิดเพื่อแก้ไข
ซึ่งหมายความว่าเราควรจะสามารถเพิ่มฟังก์ชันการทำงานใหม่ให้กับคลาสได้โดยไม่ต้องแก้ไขโค้ดที่มีอยู่ สรุปสั้นๆ ง่าย ห้ามแก้ class เดิมเพื่อเพิ่มความสามารถให้กับ class
❌ Bad
// Non-compliant class violating the Open-Closed Principle
class AudioFileReader {
func readMp3 ( file : String ) -> String {
return " Reading MP3 file: \( file ) "
}
func readWav ( file : String ) -> String {
return " Reading WAV file: \( file ) "
}
}
// Client code violating the Open-Closed Principle
class AudioFileProcessor {
func processAudio ( fileReader : AudioFileReader, file : String ) {
// The client code needs to know about specific methods for each file format
if file. hasSuffix ( " .mp3 " ) {
let result = fileReader. readMp3 ( file : file )
print ( result )
} else if file. hasSuffix ( " .wav " ) {
let result = fileReader. readWav ( file : file )
print ( result )
}
// Adding support for a new file format would require modifying this code
}
}
// Example usage (client code violating OCP)
let audioReader = AudioFileReader ()
let processor = AudioFileProcessor ()
processor. processAudio ( fileReader : audioReader, file : " example.mp3 " )
processor. processAudio ( fileReader : audioReader, file : " example.wav " )
✅ Good
// Protocol defining the behavior of an audio file reader
protocol AudioFileReader {
func read ( file : String ) -> String
}
// Concrete implementation for reading MP3 files
class Mp3FileReader : AudioFileReader {
func read ( file : String ) -> String {
return " Reading MP3 file: \( file ) "
}
}
// Concrete implementation for reading WAV files
class WavFileReader : AudioFileReader {
func read ( file : String ) -> String {
return " Reading WAV file: \( file ) "
}
}
// Client code that uses the AudioFileReader without modification
class AudioFileProcessor {
func processAudio ( fileReader : AudioFileReader, file : String ) {
let result = fileReader. read ( file : file )
print ( result )
// Additional processing logic can be added here without modifying existing code
}
}
// Example usage
let mp3Reader = Mp3FileReader ()
let wavReader = WavFileReader ()
let processor = AudioFileProcessor ()
processor. processAudio ( fileReader : mp3Reader, file : " example.mp3 " )
processor. processAudio ( fileReader : wavReader, file : " example.wav " )