개발자로 후회없는 삶 살기
디자인 패턴 PART.추상 팩토리 패턴 본문
서론
※ 이 포스트는 다음 강의의 학습이 목표임을 밝힙니다.
https://www.inflearn.com/course/%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4/dashboard
본론
- 추상 팩토리 패턴
서로 관련있는 여러 객체를 만들어주는 팩토리를 추상화된(인터페이스) 형태로 정의하는 패턴입니다. 아래 예제에서 관련있는 객체를 제품군으로 관련 지을 것입니다. 기본 제품 군은 (WhiteAnchor, WhiteWheel)처럼 기본으로 관련이 있고 Pro 제품 군은 (WhiteProAnchor, WhiteProWheel)로 관련이 있다고 봅니다.
구체적인 팩토리에서 구체적인 인스턴스를 만드는 것까지는 팩토리 메서드 패턴과 굉장히 비슷하지만 초점이 팩토리를 사용하는 클라이언트 입장에서 바라보면 추상 팩토리 패턴이라고 볼 수 있습니다.
목적 자체가 팩토리에서 인스턴스를 만들어서 쓰는 코드를 인터페이스 기반으로 코딩할 수 있게 도와주는 패턴이라서 모양은 팩토리 메서드 패턴과 굉장히 흡사하지만 팩토리를 사용하는 쪽 코드와 같이 봐야합니다.
-> 그림
내부 구조는 팩토리 메서드 패턴과 비슷하고 클라이언트가 추가 되었으며 구제적인 제품이 A, B로 서로 관련있는 제품끼리 추상화 되어있습니다.
- 기존 코드
public class WhiteshipFactory extends ShipFactory {
@Override
public Ship createShip() {
Ship ship = new Whiteship();
ship.setAnchor(new WhiteAnchor());
ship.setWheel(new WhiteWheel());
return ship;
}
}
기존 white ship, black ship을 만들 던 팩토리 메서드 패턴의 코드를 조금 더 확장합니다. 배를 만들 때 조종대와 휠을 만들 것입니다. 지금 여기서는 구체적인 부분을 생성자가 아닌 구체 Creator에서 하고 있는데 이렇게 하면 WhiteAdvancedAnchor, WhiteNewWheel 이렇게 바뀔 때마다 코드가 다 바뀌게 될 것입니다.(new)
이것을 바뀌지 않게 하고 관련 제품 군을 늘려가는 방법을 추상 팩토리 패턴을 적용해서 해결해봅니다. 현재 코드가 클라이언트 코드로 구체적인 클래스에 의존하고 있습니다. 이 부분을 개선할 것입니다.
public interface ShipPartsFactory {
Anchor createAnchor();
Wheel createWheel();
}
public interface Wheel {
}
public interface Anchor {
}
먼저 비슷한 제품 군을 만들 인터페이스를 만듭니다. 각각의 제품들은 휠이면 휠, 앵커면 앵커들의 특징이 다 따로 있을 것입니다. 그래서 각 제품 군들의 인터페이스를 만들어 줄 것입니다.
public interface ShipFactory {
Ship createShip();
제품을 만들 팩토리를 추상으로 만든 것은 팩토리 메서드 패턴과 동일합니다. 팩토리 메서드에서는 배를 만들 추상 creator를 만든 것이고 여기서는 배 내부의 제품을 만들 추상 creator를 만든 것입니다.
거기에 배의 각 제품도 Pro군, 일반 군으로 관련을 지을 것이라서 추상으로 만듭니다. 만들어진 결과를 보면 추상 팩토리가 생긴 것입니다. 이게 추상 팩토리고 추상 팩토리의 구체적인 팩토리를 만들어야 합니다.
public class WhiteshipPartsFactory implements ShipPartsFactory{
@Override
public Anchor createAnchor() {
return new WhiteAnchor();
}
@Override
public Wheel createWheel() {
return new WhiteWheel();
}
}
// 팩토리 메서드
public class BlackShipFactory implements ShipFactory{
@Override
public Ship createShip() {
return new BlackShip();
}
}
방금 만든 추상 팩토리인 ShipPartsFactory의 구체적인 팩토리를 구현합니다. 먼저 기본 제품군을 만드는 팩토리를 만듭니다. 모양을 보면 팩토리 메서드와 동일합니다. 제품을 만드냐 배를 만드냐의 차이입니다.
public class WhiteAnchor implements Anchor {
}
화이트 휠과 화이트 앵커도 각 제품군의 인터페이스를 구현해야 합니다. 그래야 그 제품의 특징을 가지고 있습니다. 이렇게 하면 모든 parts들을 만들 팩토리가 만들어졌습니다. 그럼 이제 이 팩토리를 클라이언트가 사용해서 기존 코드를 개선할 것입니다. 팩토리는 추상으로 사용하면 됩니다.
public class WhiteShipFactory implements ShipFactory {
private ShipPartsFactory shipPartsFactory;
public WhiteShipFactory(ShipPartsFactory shipPartsFactory) {
this.shipPartsFactory = shipPartsFactory;
}
@Override
public Ship createShip() {
Ship ship = new Whiteship();
ship.setAnchor(shipPartsFactory.createAnchor());
ship.setWheel(shipPartsFactory.createWheel());
return ship;
}
}
ShipPartsFactory를 주입받고 팩토리를 통해서 앵커를 가져오고 휠을 가져온다면 이 코드는 이제 전혀 바뀔 이유가 없습니다.
-> 프로 제품군 만들기
public class WhiteAnchorPro implements Anchor{
}
이전 같으면 new whiteAnchorPro를 만들어야 했는데 이제는 그렇게 하는게 아니라 WhiteAnchor를 만든 것처럼 Pro 제품군을 만들고
public class WhitePartsProFactory implements ShipPartsFactory{
@Override
public Anchor createAnchor() {
return new WhiteAnchorPro();
}
@Override
public Wheel createWheel() {
return new WhiteWheelPro();
}
}
프로 제품군을 제공할 팩토리를 만들면 됩니다. 이제 WhiteShipFactory를 만들어서 쓸 때 어떤 Parts 팩토리를 넣냐에 따라서 프로를 만들 수도 있고 일반 제품군을 만들 수도 있는 것입니다.
-> WhiteShipFactory 사용
public static void main(String[] args) {
ShipFactory shipFactory = new WhiteShipFactory(new WhitePartsProFactory());
Ship ship = shipFactory.createShip();
System.out.println(ship.getAnchor().getClass());
}
사용할 때 프로 팩토리를 가지고 만들면 프로 제품을 만들 수 있고 기본을 넣으면 기본 제품을 만들 수 있습니다.
실행해보면 프로 제품이 들어와 있습니다. 이렇게 밖에서 어떤 Part 팩토리를 넣어주느냐에 따라서 제품군을 다르게 할 수 있는 것이 개선된 것입니다. 팩토리 메서드 패턴과 유사하게 OCP를 지키면서 제품군을 확장할 수 있는 유용한 패턴입니다.
- 팩토리 메서드와 차이
디자인 패턴의 특징은 비슷하게 생긴게 많고 어떻게 보면 용어만 다르게 보일 수도 있는데 그렇게 보이는 이유는 관점이 다르기 때문입니다.
1. 팩토리 메서드 패턴
객체를 만드는 과정에 좀 더 집중하여 구체적인 ConcreteCreator를 만드는 과정을 추상 Creator로 숨기는 것입니다.
2. 추상 팩토리
팩토리를 사용하는 클라이언트 관점에서 봐서 팩토리를 통해서 추상화된 인터페이스만 클라이언트가 쓸 수 있게 끔 하기 때문에 클라이언트 입장에서 구체 클래스를 직접 쓸 필요가 없는 패턴입니다. 유사해 보이지만 만든 관점, 사용하는 목적이 조금 다른 패턴이라고 보면 될 것입니다.
'[백엔드] > [Java | 학습기록]' 카테고리의 다른 글
디자인 패턴 PART.프로토타입 패턴 (0) | 2023.08.17 |
---|---|
디자인 패턴 PART.빌더 패턴 (0) | 2023.08.17 |
디자인 패턴 PART.팩토리 메서드 패턴 (0) | 2023.08.13 |
디자인 패턴 PART.싱글톤 패턴 (0) | 2023.07.25 |
[문법] Stream (0) | 2023.06.18 |