Factory Method와 Singleton 패턴

 

1. Factory Method

- 개념 : 객체 생성을 위한 인터페이스는 정의하지만, 인스턴스를 만들 클래스는 서브 클래스에서 정의한다.

- 예시 : 문서 편집기에 다양한 타입의 문서(Word, PDF, Text)를 생성하는 경우

 

(1) 인터페이스 정의

public interface Document {
    void open();
    void close();
}

 

(2) 서브 클래스 정의

public class WordDocument implements Document {
    public void open() {
        System.out.println("Word document opened.");
    }

    public void close() {
        System.out.println("Word document closed.");
    }
}

public class PDFDocument implements Document {
    public void open() {
        System.out.println("PDF document opened.");
    }

    public void close() {
        System.out.println("PDF document closed.");
    }
}

// Creator
public abstract class DocumentCreator {
    public abstract Document createDocument();
}

public class WordDocumentCreator extends DocumentCreator {
    public Document createDocument() {
        return new WordDocument();
    }
}

public class PDFDocumentCreator extends DocumentCreator {
    public Document createDocument() {
        return new PDFDocument();
    }
}

 

- 패턴 적용 전

문서 객체를 직접 생성하면, 문서 타입이 추가될 때마다 코드를 수정해야한다.

Document doc = new WordDocument();

 

- 패턴 적용 후

  문서 객체 생성 로직이 서브클래스에 위임되어, 새로운 문서 타입을 추가하더라도 기존 코드를 변경할 필요없이 

그냥 새로운  Document 구현체와 DocumentCreator 서브 클래스를 추가하기만하면 된다.

DocumentCreator creator = new WordDocumentCreator();
Document doc = creator.createDocument();

 

2. Singletone

 - 개념: 클래스의 인스턴스가 오직 단 하나의 유일하게 인스턴스로 생성되어야 할 때 사용한다.


 메모리 절약을 위해, 인스턴스가 필요할 때, 똑같은 인스턴스를 새로 만들지 않고 기존의 인스턴서를 가져와서 사용해도 무방한 경우 사용한다. 

 예를 들어, 우리가 전역 변수를 사용하는 이유는, 똑같은 데이터를 여러 코드 블록에서 사용하기 위함인데, 마찬가지로
이러한 개념을 클래스에 대입한 것이 Singleton 패턴이다.

 따라서 보통 싱글톤 패턴이 적용된 객체가 필요한 경우는 그 객체가 리소스를 많이 차지하는 역할을하며 무거운 클래스일 때 적합하다.

- 예시: 프린터 관리자 같은 시스템 내 리소스에 대한 전역 접근 지점을 제공하는 경우

public class PrinterManager {
    private static PrinterManager instance;

    private PrinterManager() {}

    public static PrinterManager getInstance() {
        if (instance == null) {
            instance = new PrinterManager();
        }
        return instance;
    }

    public void print() {
        System.out.println("문서를 출력합니다.");
    }
}

 

- 패턴 적용전
여러개의 프린터 관리자 인스턴스가 생성되어있을 경우, 프린터 자원에 대한 일관된 관리가 어렵다.

PrinterManager printerManager1 = new PrinterManager();
PrinterManager printerManager2 = new PrinterManager();

 

- 패턴 적용 후
전역 접근 지점을 통해 프린터 관리자의 단일 인스턴스를 얻으므로, 시스템 전체에서 하나의 프린터 관리자만 사용한다.

PrinterManager printerManager = PrinterManager.getInstance();

 

  이러한 Singleton 패턴은 Spring 프레임워크에서도 어플리케이션의 여러 컴포넌트들을 효율적으로 관리하기 위해
특히 @Controller, @Service, @Reposity 등과 같은 어노테이션이 붙은 클래스들은 Spring 컨테이너에 의해 Singleton으로 관리된다. 

- @Controller : @Controller가 붙은 클래스는 HTTP 요청을 처리하는 핸들러 메소드들이 존재하는데, 이러한 컨트롤러는 
어플리케이션 전역에서 일관된 접근 방식을 제공해야하므로 Singleton으로 관리된다.

-@Service : @Service가 붙은 클래스는 비즈니스 로직을 처리하며, 이로직은 어플리케이션의 여러 부분에서 일관되게
사용되어야 하므로 Singleton으로 관리된다.