본문 바로가기
java/java 리팩토링

06. 생성자를 팩토리 메서드로 바꾸기

by 문자메일 2023. 2. 10.

생성자로 인스턴스를 생성하고 싶지 않을 때

  • new 키워드로 객체를 생성하면 클래스의 이름이 노출됨 (되면 안되나?)
    • Employee employee = new Employee();
  • 생성되는 클래스의 이름을 숨기거나, 상황에 따라 인스턴스의 생성이 가능하도록 하고자 할 때
  • 컴파일 시간이 아닌 실행시간에 생성되는 인스턴스가 결정되어야 할 때

 

리팩토링과 디자인 패턴이 정답은 아니다.

이렇게 하면 좋고, 이렇게 하면 좀 더 객체지향적이고 이렇게 하면 좀 더 유지보수가 쉽다.

이 프로그램을 계속 써야 할 경우 어떻게 하면 좀 더 유연하게 만들어서 업그레이드 하는데 시간을 덜 들이는게 목적.

그러기 위하여 객체지향적으로 만들고 리팩토링을 해서 좀 더 코드를 유지보수를 쉽게 하는 것

 

고객 등급이 계속 늘어날 것으로 예상되면 switch case 분리하고 class 분리하는 것이 맞다.

생성할 때 유연성이 필요하면 factory method 쓰는 것이 맞다.

 

 

AS-IS

package factorymethod.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 factorymethod.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 factorymethod.after;

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;
	
	private Customer(int customerType, String customerName) {
		this.customerType = customerType;
		this.customerName = customerName;
	}
	
	public static Customer create (int customerType, String customerName) {
		return new Customer(customerType, 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 factorymethod.after;

public class Main {

	public static void main(String[] args) {
		
		Customer bronzeCustomer = Customer.create(Customer.BRONZE_CUSTOMER, "Tomas");
		Customer silverCustomer = Customer.create(Customer.SILVER_CUSTOMER, "Alice");
		Customer goldCustomer = Customer.create(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 2

package factorymethod.after2;

public class BronzeCustomer extends Customer {
	
	
	private BronzeCustomer(String customerName) {
		super(customerName);
		// TODO Auto-generated constructor stub
	}
	
	public static BronzeCustomer create(String customerName) {
		return new BronzeCustomer(customerName);
	}

	public String getCustomerGrade() {
		return "BRONZE";
	}
	
	public int calPrice(int price) {
		return price;
	}
	
	public int calBonusPoint(int price) {
		return bonusPoint += (price * 0.01);
	}

}

 

package factorymethod.after2;

public class GoldCustomer extends Customer {
	
	private GoldCustomer(String customerName) {
		super(customerName);
		// TODO Auto-generated constructor stub
	}
	
	public static GoldCustomer create(String customerName) {
		return new GoldCustomer(customerName);
	}

	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 factorymethod.after2;

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 factorymethod.after2;

public class Main {

	public static void main(String[] args) {
		
		Customer bronzeCustomer = BronzeCustomer.create("Tomas");
		Customer silverCustomer = SilverCustomer.create("Alice");
		Customer goldCustomer = GoldCustomer.create("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));
	
	}
	
}

댓글