일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- 프로그래머스
- 동적계획법
- 사회초년생
- 청년내일채움공제
- 알고리즘
- 막대기자르기
- 튜터링
- 취업사실신고
- C++
- 정보
- 전화영어
- 정보처리기사개정
- 자취준비
- IT기초
- 네트워크
- 실업인정인터넷신청
- HeadFirstDesignPatterns
- 후니의쉽게쓴시스코라우팅
- 부분합알고리즘
- 자료구조
- 코딩테스트
- 실업급여
- 캡쳐링
- 생애첫계약
- 모여봐요동물의숲
- array
- 순열
- 회사폐업
- leetcode
- 후니의쉽게쓴시스코네트워킹
- Today
- Total
따봉도치야 고마워
Head First Design Patterns : (4)팩토리 패턴 본문
팩토리 패턴
- 팩토리 메소드 패턴에서는 객체를 생성하기 위한 인터페이스를 정의하는데, 어떤 클래스의 인스턴스를 만들지는 서브클래스에서 결정하게 함. 클래스의 인스턴스를 만드는 일을 서브 클래스에 맡김
- 모든 팩토리 패턴에서는 객체 생성을 캡슐화한다.
- 팩토리 메소드 패턴에서는 서브클래스에서 어떤 클래스를 만들지 결정하게 함으로 객체 생성을 캡슐화한다.
- Creator 클래스 : 생산자 클래스, 팩토리 메소드를 정의/구현한다. ex) PizzaStore(추상), NYPizzaStore(구상)
- Product 클래스 : 팩토리 메소드에서 생산하는 제품
- 추상 팩토리 패턴에서는 인터페이스를 이용해 서로 연관/의존하는 객체를 구상 클래스를 지정하지 않고도 생성할 수 있음
- 클라이언트에서 추상 인터페이스를 통해 일련의 제품을 공급받을 수 있고 (어떤 제품인지는 모름)
- 클라와 팩토리에서 생산되는 제품을 분리 가능
팩토리 메소드 패턴 vs 추상 팩토리 패턴
팩토리 메소드 패턴 | 추상 팩토리 패턴 | |
객체 생성 방법 | 상속 | 구성 |
사용 이유 | 클라이언트 코드와 인스턴스 생성 코드를 분리해야 할 때 | 서로 연관된 일련의 제품군을 만들어야 할 때 |
장단점 | (단) 제품군 수정할 경우 인터페이스의 수정이 필요함 | |
비고 | 추상 팩토리 패턴에서 팩토리 메소드를 사용하는 경우는 제품을 생산하기 위한 용도 | |
결국 둘 다 객체 생성을 캡슐화하고, 클라이언트와 구상 클래스가 분리된 유연한 디자인을 구현할 수 있게 해줌. |
문제 제기
- new 를 사용하는 것 자체가 구상클래스(구현)을 바탕으로 프로그래밍 하는 것 아닌가? 맞음
- 아래와 같은 코드가 있다면, 구상클래스가 추가/제거 될 때마다 수정이 필요해짐
Duck duck;
if ( type == picnic ) duck = new MallardDuck();
else if ( type == hunting ) duck = new DecoyDuck();
else if ( type == inBathTub) duck = new RubberDuck();
- new가 문제라기 보단 변화의 문제 -> 바뀔 수 있는 부분을 캡슐화해서 해결해보자
피자 가게 예제
- orderPizza() : 입력받은 타입에 맞는 피자를 생성하고, 요리하는 메소드 (바뀔 부분, 바뀌지 않는 부분)
- 타입에 맞는 피자를 생성해주는 PizzaFactory 팩토리 클래스를 만들어보자
public class SimplePizzaFactory{
public Pizza createPizza(String type){
Pizza pizza = null;
if(type.equals("cheese")){
pizza = new CheesePizza();
} else if(type.equals("pepperoni")){
pizza = new PepperoniPizza();
} else if(type.equals("clam")){
pizza = new ClamPizza();
}
return pizza;
}
}
- 이러면 결국 똑같은 문제를 다른 객체로 넘기기만 한 것 아닌가 ? ㄴㄴ 하나로 캡슐화해 다른 곳에서 재사용, 문제 코드 삭제 가능
- 팩토리를 정적메소드(static)로 선언하는 경우는? 팩토리 객체 인스턴스 생성하지 않아도됨. 하지만 서브클래스를 만들어 메소드 행동 변경이 불가능해짐.
간단한 팩토리는 팩토리 패턴이 아니다.
피자 프랜차이즈 사업
- 지역별로 생성되는 피자가 다르다면? 지역별 팩토리 생성
- But, 피자 제작 과정과 피자 가게 자체를 하나의 프레임워크로 묶을 필요가 생김
- 팩토리를 지우고, PizzaStore 추상클래스로 변경 + createPizza 추상 메소드 선언 (팩토리 메소드)
- 지역별 PizzaStore 서브 클래스 생성해 createPizza 구현
- 이렇게 되면 PizzaStore는 피자 제작 과정만 담당하고 어떤 피자인지에 대한 결정은 서브클래스에서 하게 됨.
팩토리 메소드는 객체 생성을 처리하고, 이를 이용하면 객체 생성 작업을 서브 클래스에 캡슐화 가능
abstract Product factoryMethod(String type);
- 추상 메소드로 선언해 서브 클래스에서 객체 생성을 책임지도록 함
- 특정 제품을 리턴하며, 보통 그 객체는 수퍼클래스에서 사용
- 클라이언트에서 실제로 생성된 객체가 무엇인지 알 수 없게 함
- 매개변수를 사용해 객체 종류 선택 가능
피자 원재료 품질 관리
- 각 지역별 재료군은 같지만 재료의 구체적인 내용이 달라 관리 필요
- 원재료 생산 팩토리를 위한 인터페이스 정의
public interface PizzaIngredientFactory{
public Dough createDough();
public Sauce createSauce();
public Cheese createCheese();
public Veggies[] createVeggies();
public Pepperoni createPepperoni();
public Clams createClam();
}
- 지역별로 팩토리 생성
- ReggianoCheese, RedPepperoni, ThickCrustDough 같이 재료 클래스 구현
- 새로 만든 원재료 공장을 PizzaStore에서 사용
- 각 지역별 PizzaStore에서 지역별 원재료 팩토리를 갖고, 인스턴스 생성 시 매개변수로 넘겨줌
- 각 Pizza 클래스들은 전달받은 원재료 팩토리 객체로 재료 세팅
추상 팩토리 패턴으로 연관된 제품군 생성
Q&A
Q) 구상 Creator가 하나인 경우에도 팩토리 패턴이 유용한지
A) 제품 생산과 사용을 분리하는 데 의미가 있음.
Q) 간단한 팩토리와의 차이
A) 간단한 팩토리는 팩토리가 PizzaStore 안에 포함되는 별개의 객체, 팩토리 패턴은 추상클래스를 확장해 사용
또한 어떤 구현을 사용할지를 서브클래스에서 결정하는 프레임워크를 만들 수 있음
Q) 팩토리 메소드는 꼭 추상클래스여야 하는지
A) ㄴㄴ 기본적인 구현을 작성해도 됨.
Q) 매개변수 팩토리 메소드 사용시 형식 안전성 문제는 어떻게?
A) 정적 상수/enum/형식을 나타내기 위한 객체 등 컴파일 시 오류를 잡아낼 수 있는 방법 사용
디자인 원칙
의존성 뒤집기 원칙(Dependency Inversion Principle)
- 추상화된 것에 의존하도록 만들어라. 구상 클래스에 의존하지 않도록 해야 한다.
- 고수준 구성요소가 저수준 구성요소에 의존하면 안됨. ex) PizzaStore(고) -> Pizza(저)
원칙을 지키는데 도움이 되는 가이드라인
- 어떤 변수에도 구상 클래스에 대한 레퍼런스를 저장하지 말자
- 구상 클래스에서 유도된 클래스를 만들지 말자
- 베이스 클래스에 이미 구현되어 있던 메소드를 오버라이드 하지 말자 -> 모든 서브 클래스가 사용 가능 한 것만 추상화
NOTE
- 데코레이터 패턴에선 토핑 객체를 생성해 직접 감싸주었다면 팩토리는 해당 토핑 객체 또한 팩토리 패턴을 사용해 별도로 세팅해주는 느낌?
- 특정 피자를 시키고 토핑을 커스터마이징 할 수 있다면 어떻게 해야할까?
- 공부할 수록 객체지향 원칙 중 추상화, 캡슐화에 대해 더 와닿는 느낌
'프로그래밍 > 공부' 카테고리의 다른 글
Head First Design Patterns : (6)커맨드 패턴 (0) | 2020.09.17 |
---|---|
Head First Design Patterns : (5)싱글턴 패턴 (0) | 2020.09.15 |
Head First Design Patterns : (3)데코레이터 패턴 (0) | 2020.09.11 |
Head First Design Patterns : (2)옵저버 패턴 (0) | 2020.09.10 |
Head First Design Patterns : (1)디자인 패턴 소개 (0) | 2020.09.09 |