특정 조건(상태)에 따라, 값을 다르게 응답해줘야 하는 메서드가 많은 경우 리팩토링 가능한 방법
if문으로 분기치는 것이 아닌 특정 조건(상태)에 따른 하위 클래스를 작성하고, 하위클래스에 메서드의 로직을 구현하여 if문 없는 로직으로 구현 가능함.
새로운 조건(상태, 아래 예시에서는 VIP Customer)가 추가되면 다른 java 파일에 상속받은 하위 클래스를 생성하고 로직 구현하면 되어서 확장성은 좋고 기존 코드에서의 변경에는 닫혀있는 방법임.
if - else if, switch 문으로 분류 코드를 사용할 때 발생 가능한 문제점
- 조건 추가 시 조건에 따른 if 문 지속 추가 필요
- 특정 조건일 때 로직 수정/추가 되는 경우 해당 타입 관련있는 여러 메서드 if문 분기 부분 에서 해당 내용 수정해야 함
리펙토링 순서
1. 상속으로 하위 클래스 생성하고 메서드 구현 위임
2. 불필요한 코드 삭제
AS-IS
package typecodewithsubclass.before;
public class Customer {
private int customerType;
private String customerName;
private String customerGrade;
private int bonusPoint;
public static final int BRONZE_CUSTOMER = 1;
public static final int SILVER_CUSTOMER = 2;
public static final int GOLD_CUSTOMER = 3;
public Customer(int customerType, String customerName) {
this.customerType = customerType;
this.customerName = customerName;
}
public String getCustomerGrade() {
switch(customerType) {
case BRONZE_CUSTOMER: return "BRONZE";
case SILVER_CUSTOMER: return "SILVER";
case GOLD_CUSTOMER: return "GOLD";
default : return null;
}
}
public int calPrice(int price) {
switch(customerType) {
case BRONZE_CUSTOMER:
return price;
case SILVER_CUSTOMER:
price = price - (int)(price * 0.05);
return price;
case GOLD_CUSTOMER:
price = price - (int)(price * 0.1);
return price;
default : return price;
}
}
public int calBonusPoint(int price) {
switch(customerType) {
case BRONZE_CUSTOMER:
return bonusPoint += (price * 0.01);
case SILVER_CUSTOMER:
return bonusPoint += (price * 0.05);
case GOLD_CUSTOMER:
return bonusPoint += (price * 0.1);
default : return price;
}
}
public String getCustomerName() {
return customerName;
}
public String toString() {
return customerName + "님의 멤버십 등급은 " + getCustomerGrade() + "입니다.";
}
}
package typecodewithsubclass.before;
public class Main {
public static void main(String[] args) {
Customer bronzeCustomer = new Customer(Customer.BRONZE_CUSTOMER, "Tomas");
Customer silverCustomer = new Customer(Customer.SILVER_CUSTOMER, "Alice");
Customer goldCustomer = new Customer(Customer.GOLD_CUSTOMER, "Edward");
int price = 10000;
System.out.println(bronzeCustomer);
System.out.println(bronzeCustomer.getCustomerName() + ": price : " + bronzeCustomer.calPrice(price)
+ " bonusPoint: " + bronzeCustomer.calBonusPoint(price));
System.out.println(silverCustomer);
System.out.println(silverCustomer.getCustomerName() + ": price : " + silverCustomer.calPrice(price)
+ " bonusPoint: " + silverCustomer.calBonusPoint(price));
System.out.println(goldCustomer);
System.out.println(goldCustomer.getCustomerName() + ": price : " + goldCustomer.calPrice(price)
+ " bonusPoint: " + goldCustomer.calBonusPoint(price));
}
}
TO-BE
package typecodewithsubclass.after;
public abstract class Customer {
protected String customerName;
protected String customerGrade;
protected int bonusPoint;
Customer(String customerName){
this.customerName = customerName;
}
public abstract String getCustomerGrade();
public abstract int calPrice(int price);
public abstract int calBonusPoint(int price);
public String getCustomerName() {
return customerName;
}
public String toString() {
return customerName + "님의 멤버십 등급은 " + getCustomerGrade() + "입니다.";
}
}
package typecodewithsubclass.after;
public class BronzeCustomer extends Customer {
BronzeCustomer(String customerName) {
super(customerName);
// TODO Auto-generated constructor stub
}
public String getCustomerGrade() {
return "BRONZE";
}
public int calPrice(int price) {
return price;
}
public int calBonusPoint(int price) {
return bonusPoint += (price * 0.01);
}
}
package typecodewithsubclass.after;
public class SilverCustomer extends Customer {
SilverCustomer(String customerName) {
super(customerName);
// TODO Auto-generated constructor stub
}
public String getCustomerGrade() {
return "SILVER";
}
public int calPrice(int price) {
return price = price - (int)(price * 0.05);
}
public int calBonusPoint(int price) {
return bonusPoint += (price * 0.05);
}
}
package typecodewithsubclass.after;
public class GoldCustomer extends Customer {
GoldCustomer(String customerName) {
super(customerName);
// TODO Auto-generated constructor stub
}
public String getCustomerGrade() {
return "GOLD";
}
public int calPrice(int price) {
return price - (int)(price * 0.1);
}
public int calBonusPoint(int price) {
return bonusPoint += (price * 0.1);
}
}
package typecodewithsubclass.after;
public class Main {
public static void main(String[] args) {
Customer bronzeCustomer = new BronzeCustomer("Tomas");
Customer silverCustomer = new SilverCustomer("Alice");
Customer goldCustomer = new GoldCustomer("Edward");
int price = 10000;
System.out.println(bronzeCustomer);
System.out.println(bronzeCustomer.getCustomerName() + ": price : " + bronzeCustomer.calPrice(price)
+ " bonusPoint: " + bronzeCustomer.calBonusPoint(price));
System.out.println(silverCustomer);
System.out.println(silverCustomer.getCustomerName() + ": price : " + silverCustomer.calPrice(price)
+ " bonusPoint: " + silverCustomer.calBonusPoint(price));
System.out.println(goldCustomer);
System.out.println(goldCustomer.getCustomerName() + ": price : " + goldCustomer.calPrice(price)
+ " bonusPoint: " + goldCustomer.calBonusPoint(price));
}
}
'java > java 리팩토링' 카테고리의 다른 글
07. 전략, 상태패턴 적용하기 (0) | 2023.02.11 |
---|---|
06. 생성자를 팩토리 메서드로 바꾸기 (0) | 2023.02.10 |
04. 분류 코드를 클래스로 만들기 (0) | 2023.02.08 |
03. null 객체 사용 (0) | 2023.02.07 |
02. 제어를 위한 플래그 삭제 (0) | 2023.02.07 |
댓글