디자인패턴
소프트웨어 공학의 소프트웨어 설계에서 공통으로 발생하는 문제에 대해 자주 쓰이는 설계방법을 정리한 패턴
디자인 패턴의 구성요소
- 패턴의 이름 - 디자인 패턴을 부를 때 사용하는 이름과 디자인 패턴의 유형
- 문제 및 배경 - 디자인 패턴이 사용되는 분야 또는 배경, 해결하는 문제를 의미
- 솔루션 - 디자인 패턴을 이루는 요소들, 관계, 협동 과정
- 사례 - 디자인 패턴의 간단한 적용 사례
- 결과 - 디자인 패턴을 사용하면 얻게 되는 이점이나 영향
- 샘플 코드 - 디자인 패턴이 적용된 원시 코드
디자인 패턴 유형
- 목적에 따라
- 생성 : 객체 인스턴스 생성에 관여, 클래스 정의와 객체 생성 방식을 구조화, 캡슐화를 수행하는 패턴
- 구조 : 더 큰 구조 형성 목적으로 클래스나 객체의 조합을 다루는 패턴
- 행위 : 클래스나 객체들이 상호 작용하는 방법과 역할 분담을 다루는 패턴
- 범위에 따라
- 클래스 : 클래스 간 관련성(상속 관계를 다루는 패턴), 컴파일 타임에 정적으로 결정
- 객체 : 객체 간 관련성을 다루는 패턴, 런타임에 동적으로 결정
디자인 패턴 종류
- 생성 - Builder, Prototype, Factory Method, Abstract Factory, Singleton
- 구조 - Bridge, Decorator, Facade, Flyweight, Proxy, Composite, Adapter
- 행위 - Mediator, Interpreter, Iterator, Template Method, Observer, State, Visitor, Command, Strategy, Memento, Chain of Responsibility
싱글톤(Singleton) 패턴
생성자가 여러 차례 호출되더라도 실제로 생성되는 객체는 하나이고 최초 생성 이후에 호출된 생성자는 최초의 생성자가 생성한 객체를 리턴한다
전역 변수를 사용하지 않고 객체를 하나만 생성하도록 하며, 생성된 객체를 어디에서든지 참조할 수 있도록 하는 디자인 패턴
한 클래스에 한 객체만 존재하도록 제한
같은 데이터를 메서드마다 정의해서 사용하지 않고 전역 변수로 빼서 사용하는 것과 비슷하다
같은걸 여러 번 정의해서 쓰면 비효율적이다
싱글톤 패턴도 객체를 여러 번 만들 필요가 없고 무거운 클래스일 때 적합하다
대표적으로 데이터 연결 모듈에 사용하는데 DB에 접속하는 작업 그 자체로 무거운 작업이기 때문
- 디스크 연결, 네트워크 통신, DBCP 커넥션풀, 스레드풀, 캐시, 로그 기록 객체 등에 이용
- 스프링 빈 도 싱글톤 패턴이다
따라서 애플리케이션에서 유일해야 하며 유일한 것이 좋은 것을 싱글톤 객체로 만들면 된다고 보면 된다.
코드 패턴은 한 가지만 있는 것은 아니다.
여러 가지 코드 기법들이 존재하여 이들 중 가장 최적화된 패턴을 상황에 맞게 사용하는 것이 핵심이다.
싱글톤 패턴을 구현하는 코드 기법 총 7가지
각기 코드 패턴마다 장단점이 존재한다.
각 순서마다 1번부터 조금씩 단점을 보완하는 식으로 흘러가는 것으로 보면 된다.
- Eager Initialization
- Static block initialization
- Lazy initialization
- Thread safe initialization
- Double-Checked Locking
- Bill Pugh Solution
- Enum 이용
다음은 수업 시간에 사용했었던 두 가지 방법이다.
Eager Initialization
한 번만 미리 만들어두는, 가장 직관적이면서도 심플한 기법 static final이라 멀티 스레드 환경에서도 안전함
그러나 static 멤버는 당장 객체를 사용하지 않더라도 메모리에 적재하기 때문에 만일 리소스가 큰 객체일 경우, 공간 자원 낭비가 발생함
예외 처리를 할 수 없음
만일 싱글톤을 적용한 객체가 그리 크지 않은 객체라면 이 기법으로 적용해도 무리는 없다.
package test01;
public class Test2 {
private static final Test2 instance = new Test2();
private Test2() {
}
public static Test2 getInstance() {
return instance;
}
}
Lazy initialization
객체 생성에 대한 관리를 내부적으로 처리메서드를 호출했을 때 인스턴스 변수의 null 유무에 따라 초기화하거나 있는 걸 반환하는 기법
위의 미사용 고정 메모리 차지의 한계점을 극복
그러나 스레드 세이프(Thread Safe) 하지 않는 치명적인 단점을 가지고 있음
package test01;
public class Test1 {
private static Test1 instance = null;
private Test1() {
}
public static Test1 getInstance() {
if (instance == null) {
instance = new Test1();
}
return instance;
}
}
참고
- 수제비 2023 정보처리기사 교재
- 위키백과
- https://inpa.tistory.com/entry/GOF-💠-싱글톤Singleton-패턴-꼼꼼하게-알아보자#eager_initialization
- https://gofnrk.tistory.com/63
- https://dev-coco.tistory.com/153