개방 폐쇄 원칙은 기존의 코드를 변경하지 않으면서 기능을 추가할 수 있도록 설계가 되어야 한다는 뜻이다.
성적표나 출석부에 학생의 성적이나 출석 기록을 출력하는 기능을 사용하는 SomeClient 예는 다음과 같다.
// SomeClient
class SomeClient {
성적표 seongjeok;
출석부 chulseok;
main() {
seongjeok.출력()
chulseok.출력()
}
}
만약 도서관 명부와 같은 새로운 매체에 학생의 대여 기록을 출력하는 경우는 다음과 같이 할 수 있다.
// 대여명부 추가
class 대여명부 {
void 출력()
}
// SomeClient
class SomeClient {
성적표 seongjeok
출석부 chulseok
대여명부 daeyeo
main() {
seongjeok.출력()
chulseok.출력()
daeyo.출력()
}
}
그러나 이 방식은 OCP를 위반한다.
새로운 기능을 추가하려고 SomeClient 클래스를 수정해야 하기 때문이다.
OCP를 위반하지 않은 설계를 할 때 가장 중요한 것은 무엇이 변하는 것인지 아닌지를 구분해야 한다는 점이다.
위 경우에 변하는 것은 다음과 같은 학생의 대여 기록을 출력하는 매체다.
따라서 새로운 출력 매체를 표현하는 클래스를 추가하고 이러한 변경이 있더라도 기존의 클래스가 영향을 받지 않게 해야한다.
SomeClient 클래스가 개별적인 클래스를 처리하도록 하지않고 인터페이스에서 구체적인 출력 매체를 캡슐화 하도록 해야 한다.
다음과 같이 코드를 변경할 수 있다.
Printable을 구현하는 클래스가 늘어나도 코드의 변경은 없다.
// SomeClient
class SomeClient {
Printable print;
main() {
print = new 대여명부()
print.출력() // 대여 명부 출력
}
}
OCP를 보는 또 하나의 관점은 클래스를 변경하지 않고도(closed) 대상 클래스의 환경을 변경할 수 있는(open) 설계가 되어야 한다는 것이다.
이는 특히 단위 테스트를 수행할 때 중요하다.