Notice
Recent Posts
Recent Comments
Link
후라이
객체지향에서의 다형성, 그리고 OCP 본문
다형성
객체지향언어의 가장 큰 특징은 다형성이라고 할 수 있습니다. 이를 예시를 들어 설명하자면,
운전자(클라이언트)가 자동차라고 하는 클래스를 운전하는 상황입니다.
하지만, 자동차는 K5, 아반떼, 테슬라 등 종류야 여러가지가 될 수 있겠죠? 여기서 이 각각의 자동차들은 공통적으로
엑셀 밟으면 가고, 브레이크 밟으면 멈추고 이런 표준화된 기능들을 가질 겁니다.
여기서 운전자는 테슬라의 전기 모터 구조나 원리에 대해서는 알 필요가 없습니다. 즉, "구현"은 알지 않아도 됩니다.
- 운전자: 자동차의 내부 구조나 구체적인 작동 방식(구현)을 몰라도 핸들, 브레이크 등 표준 인터페이스만으로 운전할 수 있다.
- 자동차: 다양한 종류(K5, 아반떼, 테슬라)가 있지만, 표준화된 기능(운전)이 구현되어 있다.
- 다형성: 운전자가 동일한 방식으로 다양한 자동차를 운전할 수 있게 하는 개념
이렇게 정리할 수 있겠습니다.
그래서, 코드적으로 말하면
- 운전자는 Car 인터페이스만 사용하고, 구체적인 자동차(K5, 아반떼, 테슬라)의 동작 방식을 알 필요가 없습니다.
- 운전자의 코드(Driver 클래스)는 수정할 필요 없이 새로운 자동차 클래스를 추가하면 확장 가능합니다.
- 예를 들어, Genesis라는 새로운 자동차를 추가해도 기존 코드는 건드리지 않습니다.
OCP :Open-close principle
1. 문제 상황
결제 시스템에서 다양한 결제 수단(카드, 현금, 모바일 결제 등)을 처리해야 합니다.
잘못된 설계 (OCP 위반)
public class PaymentProcessor {
public void processPayment(String method, int amount) {
if (method.equals("card")) {
System.out.println(amount + "원을 카드로 결제합니다.");
} else if (method.equals("cash")) {
System.out.println(amount + "원을 현금으로 결제합니다.");
} else if (method.equals("mobile")) {
System.out.println(amount + "원을 모바일로 결제합니다.");
} else {
throw new IllegalArgumentException("알 수 없는 결제 수단입니다.");
}
}
}
문제점:
- 새로운 결제 수단(예: 암호화폐 결제)을 추가하려면 기존 processPayment 메서드를 수정해야 합니다.
- 조건문이 많아지면서 가독성이 떨어지고 유지보수가 어렵습니다.
- 기존 코드에 대한 수정은 오류를 범하기 쉽습니다.
2. OCP를 만족하는 설계
Java의 인터페이스와 다형성을 활용하면 OCP를 만족하는 설계를 할 수 있습니다.
리팩토링된 설계
- 결제 수단 인터페이스 정의
공통된 인터페이스를 통해 다양한 결제 방식을 확장할 수 있습니다.
// 결제 수단 인터페이스
public interface PaymentMethod {
void pay(int amount);
}
- 구체적인 결제 방식 구현
각 결제 방식은 PaymentMethod 인터페이스를 구현합니다.
// 카드 결제
public class CardPayment implements PaymentMethod {
@Override
public void pay(int amount) {
System.out.println(amount + "원을 카드로 결제합니다.");
}
}
// 현금 결제
public class CashPayment implements PaymentMethod {
@Override
public void pay(int amount) {
System.out.println(amount + "원을 현금으로 결제합니다.");
}
}
// 모바일 결제
public class MobilePayment implements PaymentMethod {
@Override
public void pay(int amount) {
System.out.println(amount + "원을 모바일로 결제합니다.");
}
}
- 결제 처리 클래스
PaymentProcessor 클래스는 결제 수단의 구체적인 구현에 의존하지 않고, PaymentMethod 인터페이스만 사용합니다.
public class PaymentProcessor {
private PaymentMethod paymentMethod;
public PaymentProcessor(PaymentMethod paymentMethod) {
this.paymentMethod = paymentMethod;
}
public void processPayment(int amount) {
paymentMethod.pay(amount);
}
}
3. 사용 예시
이제 다양한 결제 수단을 처리할 수 있습니다.
public class Main {
public static void main(String[] args) {
PaymentMethod card = new CardPayment();
PaymentMethod cash = new CashPayment();
PaymentMethod mobile = new MobilePayment();
PaymentProcessor processor = new PaymentProcessor(card);
processor.processPayment(1000); // "1000원을 카드로 결제합니다."
processor = new PaymentProcessor(cash);
processor.processPayment(500); // "500원을 현금으로 결제합니다."
processor = new PaymentProcessor(mobile);
processor.processPayment(2000); // "2000원을 모바일로 결제합니다."
}
}
4. 새로운 기능 추가
암호화폐 결제를 추가해야 한다면, PaymentMethod를 구현하는 새로운 클래스를 추가하면 됩니다. 기존 코드를 변경할 필요가 없습니다.
// 암호화폐 결제
public class CryptoPayment implements PaymentMethod {
@Override
public void pay(int amount) {
System.out.println(amount + "원을 암호화폐로 결제합니다.");
}
}
// 사용 예시
public class Main {
public static void main(String[] args) {
PaymentMethod crypto = new CryptoPayment();
PaymentProcessor processor = new PaymentProcessor(crypto);
processor.processPayment(3000); // "3000원을 암호화폐로 결제합니다."
}
}
5. OCP 원칙 준수 결과
- 확장에는 열려 있음:
새로운 결제 방식을 추가하려면 PaymentMethod 인터페이스를 구현하는 클래스를 추가하기만 하면 됩니다. - 변경에는 닫혀 있음:
기존의 PaymentProcessor 클래스나 다른 결제 방식 클래스는 수정되지 않습니다.
6. 정리
- 확장을 위해 기존 코드를 변경하지 않고도 새로운 기능을 추가할 수 있습니다.
- 핵심: 인터페이스와 다형성을 사용해 역할과 구현을 분리
'Spring' 카테고리의 다른 글
[Spring MVC] MVC 프레임워크 <1> (1) | 2024.12.19 |
---|---|
[Spring MVC] 웹 시스템 | 서블릿 | HTML | HTTP API (0) | 2024.12.15 |
[Spring Boot] - 스프링 입문 (6) (1) | 2024.02.13 |
[Spring Boot] - H2 데이터베이스 연결 / Database not found (0) | 2024.02.12 |
[Spring Boot] - 스프링 입문 (5) (1) | 2024.01.21 |