에릭 프리먼 님의 "헤드퍼스트 디자인 패턴" 책을 정리한 포스팅 입니다
1. 기존 문제: new 키워드
- new 키워드를 통해 직접 객체 생성 시 → 특정 구현체에 강하게 의존하게 됨
- ⚠️ OCP, DIP 위반 → 코드 변경에 취약, 테스트 어려움
2. 팩토리 메서드 패턴
- 객체를 생성을 서브클래스에서 위임하는 패턴
- 클라이언트 코드와 구현체 생성 코드를 분리시킴
추상 클래스화
- 서브클래스에 피자 생성을 위임함
- 어떤 종류의 피자를 만들지에 대한것은 어떤 서브클래스를 생성했느냐에 따라 결정됨
- 클라이언트는 어떤 구현이 생성되는지 몰라도 됨
예제) PizzaStore
더보기
추상클래스
public abstract class PizzaStore {
public Pizza orderPizza(String type) {
Pizza pizza = createPizza(type);
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
public abstract Pizza createPizza(String type);
}
서브클래스
public class NYPizzaStore extends PizzaStore {
public Pizza createPizza(String item) {
if (item.equals("cheese") return new NYStyleCheesePizza();
if (item.equals("veggie") return new NYStyleVeggiePizza();
if (item.equals("clam") return new NYStyleClamPizza();
if (item.equals("pepperoni") return new NYStylePepperoniPizza();
return null;
}
}
3. 추상 팩토리 패턴
- 연관된 여러 객체(제품군)을 생성해야 할 때 사용
- 제품군 생성을 위한 인터페이스 정의
- 구체 팩토리는 Composition 방식으로 필요한 구성 요소 생성 (내부 구성의 생성 책임을 외부 팩토리에 위임)
예제) Pizza
더보기
추상클래스
public abstract class Pizza {
String name;
Dough dough;
Sauce sauce;
Veggies[] veggies;
Cheese cheese;
Pepperoni pepperoni;
Clams clam;
void setName(String name) { this.name = name; }
String getName() { return name; }
void bake() { ... }
void cut() { ... }
void box() { ... }
abstract void prepare();
}
서브클래스
public class CheesePizza extends Pizza {
PizzaIngredientFactory pizzaIngredientFactory;
public CheesePizza(PizzaIngredientFactory pizzaIngredientFactory) {
this.pizzaIngredientFactory = pizzaIngredientFactory;
}
void prepare() {
dough = ingredientFactory.createDough();
sauce = ingredientFactory.createSauce();
cheese = ingredientFactory.createCheese();
}
}
Factory
- 호출자는 구체적인 구현을 알 필요 없음
- 확장에 열려있고 변경에 닫혀있게 할 수 있음
예제) PIzzaIngredientFactory
더보기
추상클래스
public interface PizzaIngredientFactory {
Dough createDough();
Sauce createSauce();
Cheese createCheese();
Veggies[] createVeggies();
Pepperoni createPepperoni();
Clams createClam();
}
- 제품군 구성에 대한 통일된 인터페이스 제공
서브클래스
public class NYPizzaIngredientFactory implements PizzaIngredientFactory {
public Dough createDough() { return new ThinCrustDough(); }
public Sauce createSauce() { return new MarinaraSauce(); }
public Cheese createCheese() { return new ReggianoCheese(); }
public Veggie[] createVeggies() { return new[] {new Galic(), new Onion(), new Mushroom(), new RedPepper() }; }
public Pepperoni createPepperoni() { return new SlicedPepperoni(); }
public Clams createClam() { return new FreshClams(); }
}
4. DIP (의존성 뒤집기 원칙)
- 고수준 모듈(정책 결정)은 저수준 모듈(구현 세부사항)에 의존해선 안되며, 둘다 추상화에 의존해야 함
문제점: DIP 전
- 고수준 클래스가 직접 구체 클래스를 생성
- 새로운 구현체가 생기면 고수준 클래스 수정 필수
- ⚠️ OCP 위반
예제) DependentPizzaStore
더보기
public class DependentPizzaStore {
public Pizza createPizza(String style, String type) {
Pizza pizza = null;
if (style.equals("NY")) {
if (item.equals("cheese") return new NYStyleCheesePizza();
if (item.equals("veggie") return new NYStyleVeggiePizza();
if (item.equals("clam") return new NYStyleClamPizza();
if (item.equals("pepperoni") return new NYStylePepperoniPizza();
} else if (style.equals("Chicago")) {
if (item.equals("cheese") return new ChicagoStyleCheesePizza();
if (item.equals("veggie") return new ChicagoStyleVeggiePizza();
if (item.equals("clam") return new ChicagoStyleClamPizza();
if (item.equals("pepperoni") return new ChicagoStylePepperoniPizza();
}
return pizza;
}
}
해결: DIP 적용
- 추상 팩토리 메서드 패턴을 사용하여 의존성을 역전시킴
예제) PizzaFactory
더보기
추상클래스
public interface PizzaFactory {
Pizza createPizza(String type);
}
서브클래스
public class NYPizzaFactory implements PizzaFactory {
@Override
public Pizza createPizza(String type) {
if (type.equals("cheese")) return new NYStyleCheesePizza();
if (type.equals("veggie")) return new NYStyleVeggiePizza();
if (type.equals("clam")) return new NYStyleClamPizza();
if (type.equals("pepperoni")) return new NYStylePepperoniPizza();
return null;
}
}
'Java > Design Pattern' 카테고리의 다른 글
[헤드퍼스트 디자인 패턴] 6. 커맨드 패턴 (0) | 2024.12.17 |
---|---|
[헤드퍼스트 디자인 패턴] 5. 싱글턴 패턴 (1) | 2024.12.16 |
[헤드퍼스트 디자인 패턴] 3. 데코레이터 패턴 (1) | 2024.12.16 |
[헤드퍼스트 디자인 패턴] 2. 옵저버 패턴 (0) | 2024.12.16 |
[헤드퍼스트 디자인 패턴] 0. 디자인 패턴이란 (1) | 2024.12.16 |