Factory Method
팩토리 메서드
- 객체 생성 처리를 서브 클래스로 분리해 처리하도록 캡슐화하는 패턴
- 객체 생성 코드를 별도의 클래스/메서드로 분리함으로써 객체 생성의 변화에 대비할 수 있다.
- 특정 기능의 구현은 개별 클래스를 통해 제공되는 것이 바람직하다.
- 기능의 변경이나 선택은 해당 객체를 생성하는 코드의 변경을 초래한다.
- 상황에 따라 적절한 객체를 생성하는 코드는 자주 중복될 수 있다.
- 객체 생성 방식의 변화는 해당되는 모든 코드 부분을 변경해야 하는 문제가 발생한다.
팩토리 메서드는 다음과 같은 상황에서 사용한다
- 어떤 클래스가 자신이 생성해야하는 객체의 클래스를 예츨할 수 없을때
- 생성하는 객체를 기술하는 책임을 자신의 서브클래스가 지정했으면 할 때
- 객체 생성의 책임을 몇 개의 보조 서브클래스 가운데 하나에게 위임하고, 어떤 서브클래스가 위임자인지에 대한
정보를 최소화하고 싶을 때

Product
- 팩토리 메서드로 생성될 객체의 공통 인터페이스
ConcreteProduct
- 구체적으로 객체가 생성되는 클래스
Creator
- 팩토리 메서드를 갖는 클래스
ConcreteCreator
- 팩토리 메서드를 구현하는 클래스로, ConcreateProduct 객체를 생성
팩토리 메서드의 개념과 적용 방법
- 객체 생성을 전담하는 별도의 Factory 클래스 이용
- Strategy 패턴과 Singleton 패턴을 이용
- 상속 이용 : 하위 클래스에서 적합한 클래스의 객체를 생성
- Strategy 패턴과 Singleton 패턴, 템플릿 메서드 패턴을 이용
예시
캔디 가게의 여러가지 캔디 관리하기
- 여러 개의 캔디를 보관한다.
- 캔디 통(CandyBarbin)에 있는 캔디가 특정 수 아래로 내려가 있는 경우는 재입고한다.
- 캔디 통에는 동일한 캔디만 보관한다.

CandyBarBin 클래스
|
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
|
public class CandyBarBin {
private List<CandyBar> candies = new ArrayList<>();
private static final int LowStockLevel = 3;
private String cbType;
public CandyBarBin(String cbType){
this.cbType = cbType;
}
public void restock(){
if(getAmountInStock() < LowStockLevel){
if(cbType.equals("Snickers"))
candies.add(new Snickers());
else if(cbType.equals("Kitkat"))
candies.add(new Kitkat());
else if(cbType.equals("ThreeMusketeers"))
candies.add(new ThreeMusketeers());
}
}
private int getAmountInStock() {
return candies.size();
}
}
|
cs |
- 캔디의 종류를 문자열로 받아온다.
- restock 메서드에서는 캔디가 특정 수 이하가 되면 받은 문자열과 일치하는 캔디의 객체를 생성한다.
- 만약 새로운 캔디 종류가 추가되거나 변경 사항이 생길 경우 restock 메서드는 영향을 받게 된다는 문제점이 생긴다.
- 즉, 위의 코드는 OCP 원칙을 만족하지 못하는 설계인 것이다.
해결 방안
CandyBar 클래스
|
1
2
3
4
5
6
|
public abstract class CandyBar {
// 팩토리 메서드: 하위클래스에서 구체적인 내용을 정의
public abstract CandyBar createCandyBar();
}
|
cs |
Candy 클래스들
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
public class ThreeMusketeers extends CandyBar {
@Override
public CandyBar createCandyBar() {
System.out.println("Creating ThreeMusketeers");
return new ThreeMusketeers();
}
}
public class Snickers extends CandyBar {
@Override
public CandyBar createCandyBar() {
System.out.println("Creating Snickers");
return new Snickers();
}
}
public class Kitkat extends CandyBar {
@Override
public CandyBar createCandyBar() {
System.out.println("Creating Kitkat");
return new Kitkat();
}
}
|
cs |
CandyBarBin 클래스
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
public class CandyBarBin {
private List<CandyBar> candies = new ArrayList<>();
private static final int LowStockLevel = 3;
private CandyBar candyBar;
// 보관통을 만들 때 어떤 캔디를 담을 보관통일지 정의
public CandyBarBin(CandyBar candyBar) {
this.candyBar = candyBar;
}
public void restock(){
if(getAmountInStock() < LowStockLevel){
// 정의된 캔디의 인스턴스를 받아와 리스트에 추가
candies.add(candyBar.createCandyBar());
}
}
private int getAmountInStock() {
return candies.size();
}
}
|
cs |
CandyStore 클래스
|
1
2
3
4
5
6
7
8
9
|
public class CandyStore {
private List<CandyBarBin> bins = new ArrayList<>();
public void add(CandyBarBin bin){
bins.add(bin);
}
}
|
cs |
Main 클래스
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
public class Main {
public static void main(String[] args) {
CandyStore mystore = new CandyStore();
CandyBarBin bin1 = new CandyBarBin(new Kitkat());
mystore.add(bin1);
bin1.restock();
CandyBarBin bin2 = new CandyBarBin(new Snickers());
mystore.add(bin2);
bin2.restock();
}
}
|
cs |
- 추상 클래스 CandyBar의 하위 클래스에서 어떤 객체를 생성할지 정의하게 한다.
- CandyBarBin 클래스의 restock 메서드에서는 특정 수 이하가 된 캔디들을 각 캔디 종류 클래스들에 정의되어 있는
createCandtBar 메서드를 이용해 객체를 생성한다.
- CandyBar 클래스를 팩토리 메서드로 만들어 캔디 종류의 변화에 기존 코드가 영향을 받지 않도록 설계하였다.
- 새로 추가하거나 변경하고 싶은 캔디가 있으면 CandyBarBin 클래스에 영향을 끼치지 않고 CandyBar 클래스를 상속
받는 클래스를 추가하거나 변경시켜주면 되는것이다.
- 위와 같이 상속을 이용하는 팩토리 메서드는 스트래티지 패턴, 싱글턴 패턴, 템플릿 메서드 패턴과 함께 사용된다.
- 공통기능을 제공하는 템플릿 메서드와 하위 기능의 객체를 생성해주는 팩토리 메서드는 같이 사용되는 경우가
많지만 해당 설계에서는 팩토리 메서드만이 사용됐다.
Gof Factory Method
상위 클래스에서 어떤 객체를 생성할 것인지 정하지 않고 하위 클래스에서 정의하는 것
참고
'설계 패턴' 카테고리의 다른 글
| 템플릿 메서드 패턴 (0) | 2020.11.12 |
|---|---|
| Decorator 패턴 (0) | 2020.11.09 |
| Strategy 패턴 (0) | 2020.10.06 |
| 빌더 패턴 (Builder Pattern) (0) | 2020.10.06 |
| SOLID 원칙 (0) | 2020.10.05 |
