본문 바로가기
Spring

[Spring] 생성(Creational) 패턴 - 추상 팩토리

by worldcenter 2024. 11. 13.

 

디자인 패턴(Design Pattern)은 소프트웨어를 설계할 때 자주 발생하는 문제들을 해결하기 위해 고안된 해결책 입니다. 여기서 '패턴' 이란 애플리케이션 개발에서 발생하는 문제는 유사한 경우가 많고 해결책도 동일하게 적용할 수 있다는 의미를 내포합니다. 그러나 디자인 패턴이 모든 문제의 정답은 아니며, 상황에 맞는 최적 패턴을 결정해서 사용하는 것이 바람직 합니다.

 

디자인 패턴의 종류

디자인 패턴을 구체화해서 정리한 대표적인 분류 방식으로는 'GoF 디자인 패턴' 이 있습니다. GoF의 디자인 패턴 분류는 다음과 같습니다.

생성(Creational) 패턴 구조(Structural) 패턴 행위(Behavioral) 패턴
추상 팩토리(Abstract Factory) 어댑터(Adapter) 책임 연쇄(Chain of Responsibility)
빌더(Builder) 브리지(Bridge) 커맨드(Command)
팩토리 메서드(Factory Method) 컴포지트(Composite) 인터프리터(Interpreter)
프로토타입(Prototype) 데코레이터(Decorator) 이터레이터(Iterator)
싱글톤(Singleton) 퍼사드(Facade) 미디에이터(Mediator)
  플라이웨이트(Flyweight) 메멘토(Memento)
  프록시(Proxy) 옵저버(Observer)
    스테이트(State)
    스트레티지(Strategy)
    템플릿 메서드(Template Method)
    비지터(Visitor)

 

 

생성 패턴

생성 패턴은 객체 생성에 사용되는 패턴으로, 객체를 수정해도 이를 사용하는 코드(호출부)가 영향을 받지 않도록 합니다.

 

추상 팩토리(Abstract Factory)

서로 연관된 객체들을 그룹화하여 일관된 방식으로 생성할 수 있도록 하는 생성 패턴 입니다.  연관성이 있는 객체 군이 여러개 있을 경우 이들을 묶어 추상화하고, 어떤 구체적인 상황이 주어지면 팩토리 객체에서 집합으로 묶은 객체 군을 구현화 하는 패턴 입니다.

 

즉, 추상 팩토리의 핵심은 제품 '군' 집합을 타입 별로 찍어낼수 있다는 점이 포인트 이다. 예를들어 모니터, 마우스, 키보드를 묶은 전자 제품군이 있는데 이들을 또 삼성 제품군이냐 애플 제품군이냐 로지텍 제품군이냐에 따라 집합이 브랜드 명으로 여러갈래로 나뉘게 될때, 복잡하게 묶이는 이러한 제품군들을 관리와 확장하기 용이하게 패턴화 한것이 추상 팩토리 입니다.

 

 

추상 팩토리 클래스

  • AbstractFactory : 최상위 공장 클래스. 여러개의 제품들을 생성하는 여러 메소드들을 추상화 한다.
  • ConcreteFactory : 서브 공장 클래스들은 타입에 맞는 제품 객체를 반환하도록 메소드들을 재정의 합니다.
  • AbstractProduct : 각 타입의 제품들을 추상화한 인터페이스
  • ConcreteProduct (ProductA ~ ProductB) : 각 타입의 제품 구현체들. 이들은 팩토리 객체로부터 생성된다. 
  • Client : Client는 추상화된 인터페이스만을 이용하여 제품을 받기 때문에, 구체적인 제품, 공장에 대해서는 모른다.

 

해당 클래스를 예시코드와 비교하면서 살펴보면 이해하기 쉽습니다.

 

1) AbstractProduct

public interface TV {
    void display();
}

public interface Refrigerator {
    void cool();
}

2) ConcreteProduct (ProductA ~ ProductB)

public class LGTV implements TV {
    @Override
    public void display() {
        System.out.println("LG TV Display");
    }
}
public class SamsungTV implements TV {
    @Override
    public void display() {
        System.out.println("Samsung TV Display");
    }
}
public class LGRefrigerator implements Refrigerator {
    @Override
    public void cool() {
        System.out.println("LG Refrigerator Cooling");
    }
}
public class SamsungRefrigerator implements Refrigerator {
    @Override
    public void cool() {
        System.out.println("Samsung Refrigerator Cooling");
    }
}

3) AbstractFactory

public interface ApplicationFactory {

    TV createTV();

    Refrigerator createRefrigerator();
}

 

4) ConcreteFactory

public class LGFactory implements ApplicationFactory {
    @Override
    public TV createTV() {
        return new LGTV();
    }

    @Override
    public Refrigerator createRefrigerator() {
        return new LGRefrigerator();
    }
}
public class SamsungFactory implements ApplicationFactory {
    @Override
    public TV createTV() {
        return new SamsungTV();
    }

    @Override
    public Refrigerator createRefrigerator() {
        return new SamsungRefrigerator();
    }
}

5) Client

public class Main {
    public static void main(String[] args) {
        ApplianceFactory factory = new LGFactory(); // SamsungFactory로 바꾸면 삼성 제품 생성
        TV tv = factory.createTV();
        Refrigerator refrigerator = factory.createRefrigerator();
        
        tv.display();
        refrigerator.cool();
    }
}

 

해당 소스코드를 클래스로 다시 정의하면 위와 같습니다.

 

 

SpringFramework에서의 추상 팩토리 패턴

Spring에서는 추상 팩토리 패턴이 BeanFactory와 ApplicationContext를 통해 구현되어 있으며, 이들은 스프링의 주요 IoC 컨테이너로서 빈(bean) 객체를 일관된 방식으로 생성하고 관리하는 역할을 합니다.

추상 팩토리는 의존성 주입을 통해 애플리케이션이 구체적인 객체의 생성 과정에 의존하지 않도록 하고, 설정과 구성만으로 객체 생성을 유연하게 변경할 수 있습니다.

 

1) Bean 구성 파일 설정

@Configuration
public class AppConfig {

    @Bean
    public MyRepository myRepository() {
        return new MyRepository();
    }
}

 

2) ApplicationContext를 통해 Bean 가져오기(추상 팩토리 활용)

@Component
public class MemoService {
private final MemoRepository memoRepository;
public MemoService(ApplicationContext context) {
    // 1.'Bean' 이름으로 가져오기
    MemoRepository memoRepository = (MemoRepository) context.getBean("memoRepository");
    // 2.'Bean' 클래스 형식으로 가져오기
    // MemoRepository memoRepository = context.getBean(MemoRepository.class);
    this.memoRepository = memoRepository;
}
...
}

 

ApplicationContext가 필요한 객체를 생성 및 주입하여, Main 클래스는 객체 생성 방식에 의존하지 않고 필요한 빈을 가져와 사용할 수 있습니다.

 

 

 

해당 게시글은 아래 블로그를 참고하여 작성한 글입니다.

https://inpa.tistory.com/entry/GOF-%F0%9F%92%A0-%EC%B6%94%EC%83%81-%ED%8C%A9%ED%86%A0%EB%A6%ACAbstract-Factory-%ED%8C%A8%ED%84%B4-%EC%A0%9C%EB%8C%80%EB%A1%9C-%EB%B0%B0%EC%9B%8C%EB%B3%B4%EC%9E%90

 

💠 추상 팩토리(Abstract Factory) 패턴 - 완벽 마스터하기

Abstract Factory Pattern 추상 팩토리 패턴은 연관성이 있는 객체 군이 여러개 있을 경우 이들을 묶어 추상화하고, 어떤 구체적인 상황이 주어지면 팩토리 객체에서 집합으로 묶은 객체 군을 구현화

inpa.tistory.com

 

'Spring' 카테고리의 다른 글

[Spring] JPA(Java Persistent API)  (0) 2024.11.17
[Spring] IoC(제어의 역전), DI(의존성 주입) 이해하기  (0) 2024.11.17
[Spring] SpringSecurity - JWT  (0) 2024.11.11
[Spring] JWT(Json Web Token)  (0) 2024.11.11
[Spring] Servlet Filter 란?  (1) 2024.11.10