추상 팩토리 패턴
서로 관련이 있는 객체들을 통째로 묶어서 팩토리 클래스로 만들고,
이들 팩토리를 조건에 따라 생성하도록 다시 팩토리를 만들어서 객체를 생성하는 패턴입니다.
쉽게말해 추상적인 공장에서는 추상적인 부품을 조합하여 추상적인 제품을 만든다고 생각하시면됩니다.
무슨말이야? 라고 하신다면 '추상화' 라는 말은 '구체적으로 어떻게 구현되어 있는지 생각하지 않고 인터페이스에만 주목하는 상태'를 뜻합니다.
추상화에 대표적인 예로 부품이 많은 자동차, 컴퓨터 등이 있으나 저는 이번에 컴퓨터로 예를 들어보겠습니다.
컴퓨터의 부품으로는 키보드, 마우스, 모니터, 스피커 등등 많습니다.
각 부품마다 제조사도 다르고 일부 지원하는 기능도 다양합니다. 우리가 원래 사용하던 부품이 아니고 다른 제조사의 부품을 갈아낀다고해서 컴퓨터가 작동이 안될까요? 당연히 아닙니다. 왜냐하면 각 부품마다 인터페이스화 되어있기때문입니다. 일종의 가이드라인 또는 설계도면인것인 셈이죠.
이를 코드로 작성한다면 키보드, 마우스, 모니터, 스피커는 interface 입니다. 그리고 제조사별로 구현체를 갈아끼울 수 있겠죠.
이런식으로 말입니다. 여기에서 Factory는 어떤 구현체를 적용할 지 조합하는 공장입니다.
지금부터 코드를 작성하며 같이 보겠습니다. 예시를 위해 키보드와 마우스에 대해서만 작성해보도록 하겠습니다.
추상팩토리패턴의 예
1. 키보드
public interface Keyboard {
void init();
}
public class LGKeyboard implements Keyboard{
@Override
public void init() {
System.out.println("LG Keyboard Call");
}
}
public class SAMSUNGKeyboard implements Keyboard{
@Override
public void init() {
System.out.println("SAMSUNG Keyboard Call");
}
}
2. 마우스
public interface Mouse {
void init();
void sound();
}
public class LGMouse implements Mouse{
@Override
public void init() {
System.out.println("LG Mouse Call");
}
@Override
public void sound() {
System.out.println("LG Sound");
}
}
public class SANSUNGMouse implements Mouse{
@Override
public void init() {
System.out.println("SAMSUNG Mouse Call");
}
@Override
public void sound() {
System.out.println("SAMSUNG Sound");
}
}
인터페이스에 대한 구현체는 모두 만들었습니다. 다음은 Factory를 만들어보겠습니다.
3. 팩토리
public class KeyboardFactory {
public Keyboard createKeyboard(String type) {
if ("LG".equals(type)) {
return new LGKeyboard();
}
if ("SAMSUNG".equals(type)) {
return new SAMSUNGKeyboard();
}
return new Keyboard() {
@Override
public void init() {
System.out.println("Default Keyboard Call");
}
};
}
}
public class MouseFactory {
public Mouse createMouse(String type) {
if ("LG".equals(type)) {
return new LGMouse();
}
if ("SAMSUNG".equals(type)) {
return new SANSUNGMouse();
}
return new Mouse() {
@Override
public void init() {
System.out.println("Default Mouse Call");
}
@Override
public void sound() {
System.out.println("Default Sound");
}
};
}
}
Factory 클래스에서 만약 type이 LG라면 LG에 맞는 구현체를 넣고, Samsung이라면 Samsung에 맞는 구현체를 넣어주는 부분입니다. 만약 둘다 아니라면 익명클래스를 이용해서 기본 부품을 넣어주었습니다.
이제 컴퓨터를 조립해볼까요?
4. 완성
public class Computer {
private Keyboard keyboard;
private Mouse mouse;
public Computer(String type) {
keyboard = createKeyboard(type);
mouse = createMouse(type);
}
public void call() {
keyboard.init();
mouse.init();
}
public void click() {
mouse.sound();
}
private Keyboard createKeyboard(String type) {
KeyboardFactory keyboardFactory = new KeyboardFactory();
return keyboardFactory.createKeyboard(type);
}
private Mouse createMouse(String type) {
MouseFactory mouseFactory = new MouseFactory();
return mouseFactory.createMouse(type);
}
}
Factory 클래스의 createKeyboard와 createMouse 메서드를 사용해서 구현체를 넣어주었습니다.
실제 컴퓨터를 사용해보겠습니다.
추상팩토리패턴의 결과
public class Main {
public static void main(String[] args) {
Computer computer = new Computer("LG");
computer.call();
computer.click();
// LG Keyboard Call
// LG Mouse Call
// LG Sound
Computer computer2 = new Computer("APPLE");
computer2.call();
computer2.click();
// Default Keyboard Call
// Default Mouse Call
// Default Sound
}
}
이 추상 팩토리 패턴의 장점은 공장에서 생성되는 제품들의 상호 호환을 보장할 수 있습니다.
그리고 구현체들은 한 곳에서 코드를 쉽게 유지보수할 수 있습니다.
단점으로는 패턴과 함께 새로운 인터페이스들과 클래스들이 많이 도입되기 때문에 코드가 필요 이상으로 복잡해질 수 있습니다.
'디자인패턴 > 생성' 카테고리의 다른 글
자바(JAVA) - 싱글톤 패턴(Singleton Pattern) (0) | 2024.02.23 |
---|---|
자바(JAVA) - 프로토타입 패턴(Prototype Pattern) (0) | 2024.02.01 |
자바(JAVA) - 팩토리 메소드 패턴(Factory Method Pattern) (0) | 2024.01.30 |
자바(JAVA) - 빌더 패턴(Builder Pattern) (0) | 2024.01.29 |