이번에는 Design Pattern 중 Factory Method Pattern에 대해 알아보자.
쇼핑몰
을 정해서 들어간다. 현재 예시에서는 Timon과 Coupang이다.카테고리
를 선택한다. 현재 예시에서는 식료품(Food), 건강(Health) 카테고리가 필요하다.물건을 찾고(find)
, 카트에 담고(cart)
, 주문하고(order)
, 마지막에 해당 주문을 확인(check)
하면 마무리된다.✅ 예시를 위해 필요한 클래스들을 확인한다.
✅ 쇼핑의 공통과정(find, cart, order, check)
는 인터페이스(interface)
에 작성한다.
// Shopping.java
public interface Shopping {
public void find(); // 물건을 검색한다.
public void cart(); // 카트에 담는다.
public void order(); // 카트에 담은 물건을 주문한다.
public void check(); // 주문이 제대로 되었는지 확인한다.
}
✅ 쇼핑몰
에서 find, cart, order, check
가 이루어지므로 쇼핑몰을 정의한다.
// ShoppingMall.java
public abstract class ShoppingMall {
public Shopping shopping(String category) {
Shopping shopping = selectCategory(category); // factory method 사용
shopping.find();
shopping.cart();
shopping.order();
shopping.check();
return shopping;
}
// factory method
abstract Shopping selectCategory(String category);
}
추상화(abstract)
되어 있다. 이들은 Timon과 Coupang에서 재정의(Override)
된다.✅ Timon 클래스를 작성한다.
// Timon.java
public class Timon extends ShoppingMall{
@Override
Shopping selectCategory(String category) {
System.out.println("-----------Timon-----------");
if (category.equals("Food")) {
return new TimonFoodCategory();
} else if (category.equals("Health")) {
return new TimonHealthCategory();
}
return null;
}
}
ShoppingMall
클래스를 상속(extends)
받는다.추상 메소드
를 재정의
하여 카테고리 객체를 생성한다.✅ TimonFoodCategory, TimonHealthCategory 클래스를 작성한다.
// TimonFoodCategory.java
public class TimonFoodCategory implements Shopping{
@Override
public void find() {
System.out.println("닭가슴살 브랜드를 검색합니다.");
}
@Override
public void cart() {
System.out.println("마음에 드는 닭가슴살을 카트에 담습니다.");
}
@Override
public void order() {
System.out.println("닭가슴살을 주문합니다.");
}
@Override
public void check() {
System.out.println("닭가슴살 주문이 올바르게 되었는지 확인합니다.");
}
}
// TimonHealthCategory.java
public class TimonHealthCategory implements Shopping{
@Override
public void find() {
System.out.println("구매하려는 비타민을 검색합니다.");
}
@Override
public void cart() {
System.out.println("마음에 드는 비타민을 카트에 담습니다.");
}
@Override
public void order() {
System.out.println("비타민을 주문합니다.");
}
@Override
public void check() {
System.out.println("비타민 주문이 올바르게 되었는지 확인합니다.");
}
}
Shopping
인터페이스
에 미리 작성되어 있는 find, cart, order, check
는 Food, Health 카테고리에서 조금 더 구체적으로 작성된다
.✅ Coupang 클래스를 작성한다.
// Coupang.java
public class Coupang extends ShoppingMall{
@Override
Shopping selectCategory(String category) {
System.out.println("-----------Coupang-----------");
if (category.equals("Food")) {
return new CoupangFoodCategory();
} else if (category.equals("Health")) {
return new CoupangHealthCategory();
}
return null;
}
}
✅ CoupangFoodCategory, CoupangHealthCategory 클래스를 작성한다.
// CoupangFoodCategory.java
public class CoupangFoodCategory implements Shopping{
@Override
public void find() {
System.out.println("구운 달걀을 검색합니다.");
}
@Override
public void cart() {
System.out.println("참나무로 구운(...) 달걀을 카트에 담습니다.");
}
@Override
public void order() {
System.out.println("달걀을 주문합니다.");
}
@Override
public void check() {
System.out.println("달걀 주문이 올바르게 되었는지 확인합니다.");
}
}
// CoupangHealthCategory.java
public class CoupangHealthCategory implements Shopping{
@Override
public void find() {
System.out.println("구매하려는 프로틴을 검색합니다.");
}
@Override
public void cart() {
System.out.println("마음에 드는 프로틴을 카트에 담습니다.");
}
@Override
public void order() {
System.out.println("프로틴을 주문합니다.");
}
@Override
public void check() {
System.out.println("프로틴 주문이 올바르게 되었는지 확인합니다.");
}
}
✅ Main 클래스에서 어떻게 동작하는지 확인한다.
// Main.java
public class Main {
public static void main(String[] args) {
// Timon 쇼핑
ShoppingMall timon = new Timon();
Shopping chickenBreast = timon.shopping("Food"); // 식료품 카테고리
Shopping vitamin = timon.shopping("Health"); // 건강 카테고리
// Coupang 쇼핑
ShoppingMall coupang = new Coupang();
Shopping roastedEgg = coupang.shopping("Food"); // 식료품 카테고리
Shopping protein = coupang.shopping("Health"); // 건강 카테고리
}
}
ShoppingMall
클래스를 상속
받았다.추상 메소드
와 find, cart, order, check
가 동작한다.✅ Main 클래스의 실행 결과를 확인한다.
유동적으로 반환
되어 실행되는 것을 볼 수 있다.결합도를 낮추면서
확장을 계속해
나갈 수 있다.재사용의 문제
가 있으므로 유념해서 사용해야 한다.