팩토리 패턴
객체를 생성할 때 필요한 인터페이스를 만들어서 어떤 클래스의 인스턴스를 만들지는 서브클래스에서 결정합니다.
팩토리 메서드 패턴을 사용하면 클래스 인스턴스 만드는 일을 서브클래스에게 맡기게 됩니다.
즉, 객체를 만들기 위한 인터페이스를 제공하는 디자인 패턴입니다.
장점
- 구체적으로 생성할 클래스를 유연하게 정할 수 있다.
- 캡슐화와 추상화를 통해 구체적인 타입을 숨길 수 있다.
단점
- 새로운 객체를 추가하려면 팩토리 클래스를 만들어야 하기 때문에 확장성은 높지만 많은 변화가 필요하다.
- 클래스의 수와 코드의 양이 많아질 수 있다.
팩토리 메서드 패턴 사용 예제
Pasta인터페이스를 구현한3가지 파스타가 있고 PastaFactory라는 추상클래스를 만들고 그걸 구현한 3가지 파스타 팩도리가 있습니다.
파스타 팩토리를 통해 주문이 들어오면 그 주문에 맞는 파스타를 주문하는 방식입니다.만약 바질 파스타가 들어온다면 Pasts를 구현한 바질파스타 클래스를 만들고 PastaFactory를 구현한 바질파스타 클래스만 만들면 되기 때문에 확장에 용이합니다.
public interface Pasta {
void cook();
}
public class Carbonara implements Pasta {
@Override
public void cook() {
System.out.println("까르보나라 파스타 요리 시작.");
}
}
public class Oil implements Pasta {
@Override
public void cook() {
System.out.println("오일파스타 요리 시작.");
}
}
public class Tomato implements Pasta {
@Override
public void cook() {
System.out.println("토마토파스타 요리 시작.");
}
}
public abstract class PastaFactory {
public Pasta orderPasta(String type) {
return createPasta(type);
}
abstract Pasta createPasta(String type);
}
public class CarbonaraFactory extends PastaFactory {
@Override
Pasta createPasta(String type) {
switch (type) {
case "까르보나라":
return new Carbonara();
default:
throw new IllegalArgumentException("존재하지 않는 파스타입니다");
}
}
}
public class OilFactory extends PastaFactory {
@Override
Pasta createPasta(String type) {
switch (type) {
case "오일":
return new Oil();
default:
throw new IllegalArgumentException("존재하지 않는 파스타입니다");
}
}
}
public class TomatoFactory extends PastaFactory {
@Override
Pasta createPasta(String type) {
switch (type) {
case "토마토":
return new Tomato();
default:
throw new IllegalArgumentException("존재하지 않는 파스타입니다");
}
}
}
public class Test {
public static void main(String[] args) {
PastaFactory carbonaraFactory = new CarbonaraFactory();
PastaFactory oilFactory = new OilFactory();
PastaFactory tomatoFactory = new TomatoFactory();
carbonaraFactory.orderPasta("까르보나라").cook();
oilFactory.orderPasta("오일").cook();
tomatoFactory.orderPasta("토마토").cook();
}
}
팩토리 메서드 패턴은 한 종류의 객체만 만든다 PastaFactory를 구현한 까르보나라팩토리는 까르보나라만 만들고 있으며 토마토와 오일 또한 그렇다.
추상 팩토리 패턴
구상 클래스에 의존하지 않고도 서로 연관되거나 의존적인 객체로 이루어진 제품군을 생산하는 인터페이스를 제공합니다. 구상 클래스는 서브클래스에서 만듭니다.
즉, 연관된 객체들을 생성하는 인터페이스를 제공하고, 이를 구현한 서브클래스에서 생성합니다.
장점
- 관련된 객체를 함께 생성하므로 일관성이 유지된다.
- 객체 생성 코드가 분리되어 있어 가독성이 좋다.
단점
- 새로운 제품이 추가되면 모든 클래스를 수정해야 한다.
- 클래스가 늘어날수록 구조가 복잡해질 수 있다.
추상 팩토리 패턴 사용 예제
public abstract class ComponentFactory {
public abstract Bag changeBag(String size);
public abstract Handle changeHandle(String size);
public abstract Wheel changeWheel(String size);
}
public class BigSizeCarrier extends ComponentFactory {
@Override
public Bag changeBag(String size) {
return new RepairBigBag(size);
}
@Override
public Handle changeHandle(String size) {
return new RepairBigHandle(size);
}
@Override
public Wheel changeWheel(String size) {
return new RepairBigWheel(size);
}
}
public abstract class Handle {
public String size;
public Handle(String size) {
this.size = size;
}
public abstract void description();
}
public abstract class Bag {
public String size;
public Bag(String size) {
this.size = size;
}
public abstract void description();
}
public abstract class Wheel {
public String size;
public Wheel(String size) {
this.size = size;
}
public abstract void description();
}
public class RepairBigHandle extends Handle {
public RepairBigHandle(String size) {
super(size);
}
@Override
public void description() {
System.out.println("고장난 " + this.size + "손잡이를 새 손잡이로 교환합니다");
}
}
public class RepairBigWheel extends Wheel{
public RepairBigWheel(String size) {
super(size);
}
@Override
public void description() {
System.out.println("고장난 " + this.size + "바퀴를 새 바퀴로 교환합니다");
}
}
public class RepairSmallWheel extends Wheel {
public RepairSmallWheel(String size) {
super(size);
}
@Override
public void description() {
System.out.println("고장난 " + this.size + "바퀴를 새 바퀴로 교환합니다");
}
}
public class Test {
public static void main(String[] args) {
ComponentFactory bigFactory = new BigSizeFactory();
Bag bigBag = bigFactory.changeBag("대형");
Handle bigHandle = bigFactory.changeHandle("대형");
Wheel bigWheel = bigFactory.changeWheel("대형");
bigBag.description();
bigHandle.description();
bigWheel.description();
}
}
추상 팩토리 패턴은 하나의 객체에서 여러 종류의 객체를 골라 하나의 객체를 생성할 수 있다.
예제로 보면 BigSizeCarrier가 고장났을 경우 그에 맞는 사이즈의 부품을 골라 변경한 것과 같습니다.
사용 상황 및 공통점과 차이점
사용 상황
- 팩토리 패턴 : 단일 제품의 객체 생성하는 경우
- 추상 팩토리 패턴 : 여러 제품을 생성하거나, 제품간 연관성을 유지해야 하는 경우
공통점
- 둘 다 객체 생성을 팩토리에 맡긴다.
- 인터페이스나 추상 클래스를 사용해 객체간 결합도가 낮다.
차이점
- 팩토리 패턴은 각 단계를 수행하는 서브 클래스를 만들어 객체를 생성하는데 사용할 수 있다.
- 추상 팩토리 패턴은 필요한 재료가 여러 종류일 때 필요한 재료들을 생성하는 여러 팩토리를 제공하여 객체 생성하는데 사용할 수 있다.
'개발 도서' 카테고리의 다른 글
디자인 패턴 - 커맨드 패턴 (0) | 2023.12.09 |
---|---|
디자인 패턴 - 싱글톤 패턴 (0) | 2023.12.04 |
디자인 패턴 - 데코레이터 패턴 (0) | 2023.11.28 |
디자인 패턴 - 옵저버 패턴 (1) | 2023.11.23 |
헤드 퍼스트 디자인 패턴 - 1장 전략패턴 (1) | 2023.11.20 |