2022-12-01 @이영훈
OCP(Open Closed Principle) 개방 폐쇄 원칙
The open–closed principle (OCP) states "software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification
that is, such an entity can allow its behaviour to be extended without modifying its source code - wiki
개방 폐쇄 원칙은 소프트웨어 개체가 확장에는 열려있고, 수정에는 닫혀있어야 한다는 원칙입니다.
개체는 소스코드 수정없이 기능(행동)을 확장할 수 있어야 합니다.
백화점 맴버십 예제
백화점에 맴버십이 있습니다. 맴버십에는 유저 정보와 맴버십 만료일이 기입되어 있습니다.
이를 코드로 구현해보면 다음과 같습니다
class BasicMembership {
private String userName;
private LocalDateTime expiredAt;
public BasicMembership(String userName, LocalDateTime expiredAt) {
this.userName = userName;
this.expiredAt = expiredAt;
}
public String getUserName() {
return userName;
}
public LocalDateTime getExpiredAt() {
return expiredAt;
}
}
Java
복사
프리미엄 맴버십이 추가되었습니다. 프리미엄 맴버십은 모든 상품에 5% 할인 기능이 추가되었습니다.
이를 기존 Membership 클래스를 건드리지 않고 수정하려면 (즉, OCP를 지키면서) 다음과 같이 할 수 있습니다.
OCP 원칙을 지키면서 프리미엄 맴버십 추가하기
다음 구조처럼 맴버십 인터페이스를 만들고 맴버십의 공통 기능을 맴버십 인터페이스에 명세합니다.
그리고 새로운 맴버십이 만들어질 때마다 Membership 인터페이스를 상속받아 공통 기능을 구현하고, 새로운 맴버십을 위한 확장된 기능을 추가합니다.
이 내용을 코드로 구현해보면 다음과 같습니다.
맴버십 인터페이스를 만듭니다
(공통 기능 명세) 모든 맴버십은 유저 이름과 만료 기간을 가져올 수 있어야 합니다.
interface Membership {
public String getUserName();
public LocalDateTime getExpiredAt();
}
Java
복사
프리미엄 맴버십만의 기능인 할인율을 추가하고, 할인이 적용된 가격을 반환하는 함수를 추가합니다.
class PremiumMembership implements Membership {
private String userName;
private LocalDateTime expiredAt;
private int discountPercent;
public PremiumMembership(String userName, LocalDateTime expiredAt) {
this.userName = userName;
this.expiredAt = expiredAt;
this.discountPercent = 5;
}
@Override
public String getUserName() {
return userName;
}
@Override
public LocalDateTime getExpiredAt() {
return expiredAt;
}
// 할인이 적용된 가격 반환 함수
public int getDiscountAppliedPrice(int productPrice) {
return (int) (productPrice * (100 - discountPercent) * 0.01);
}
}
Java
복사
Basic 맴버십도 인터페이를 상속받아 구현합니다.
class BasicMembership implements Membership {
private String userName;
private LocalDateTime expiredAt;
public BasicMembership(String userName, LocalDateTime expiredAt) {
this.userName = userName;
this.expiredAt = expiredAt;
}
@Override
public String getUserName() {
return userName;
}
@Override
public LocalDateTime getExpiredAt() {
return expiredAt;
}
}
Java
복사
이렇게 OCP를 지키면 기존의 코드를 수정하지 않고도 새로운 기능을 추가할 수 있습니다.