'패턴'에 해당하는 글 3건

흔히 디자인 패턴을 적용해서 개발하면서 가장 많이 쓰고 있는 패턴이 있다면 싱글턴 패턴일 것이다. (물론 개인적인 기준일 수 있지만)

그만큼 자주 사용하지만 정확히 싱글턴 패턴이란 무엇인지, 왜 사용하는지 설명하려면 어려울 수 있다.

그래서 이번에는 싱글턴 패턴에 대해서 알아보자.

 

싱글턴 패턴이란?

· 오직 한 개의 클래스 인스턴스만을 갖도록 보장하고, 이에 대한 전역적인 접근점을 제공하는 패턴.

※ 단일체 패턴이라고도 불림.

 

· 클래스 자신이 자기의 유일한 인스턴스로 접근하는 방법을 자체적으로 관리하는 것. 이 클래스는 또 다른 인스턴스가 생성되지 않도록 할 수 있고, 클래스 자신이 그 인스턴스에 대한 접근 방법을 제공할 수 있음.

 

언제 싱글턴 패턴을 사용해야 할까?

· 클래스의 인스턴스가 오직 하나여야 함을 보장하고, 잘 정의된 접근점(Access Point)으로 모든 사용자가 접근할 수 있도록 해야 할 때.

· 유일한 인스턴스가 서브클래싱으로 확장되어야 하며, 사용자는 코드의 수정없이 확장된 서브 클래스의 인스턴스를 사용할 수 있어야 할 때.

 

구조

· Singleton : Instance() 연산을 정의하여, 유일한 인스턴스로 접근할 수 있도록 함. Instance() 연산은 유일한 인스턴스를 생성하는 책임을 맡음.

 

싱글턴 패턴의 장점

· Singleton 클래스 자체가 인스턴스를 캡슐화하기 때문에, 이 클래스에서 사용자가 언제, 어떻게 이 인스턴스에 접근할 수 있는지 제어할 수 있음.

· name space를 좁힘. 즉, 전역 변수를 정의하여 발생하는 디버깅의 어려움 등 문제를 없앰.

· 연산 및 표현의 정제를 허용함.

· 인스턴스의 개수를 변경하기가 자유로움.

· 클래스 연산을 사용하는 것보다 훨씬 유연한 방법.

 

싱글턴 패턴의 종류

· Eager Initialization

public class EagerInitialization {
	private static EagerInitialization instance = new EagerInitialization();
	
	private EagerInitialization () {
		
	}
		
	public static EagerInitialization getInstance () {
		return instance;
	}
}

가장 기본적인 싱글턴 패턴 방법. 전역 변수로 인스턴스를 만드는데 private static을 이용.

· Static Block Initialization

public class StaticBlockInitalization {
	private static StaticBlockInitalization instance;
	
	private StaticBlockInitalization () {
		
	}
	
	static {
		try {
			instance = new StaticBlockInitalization();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public static StaticBlockInitalization getInstance () {
		return instance;
	}	
}

static 초기화 블럭을 이용하여 클래스가 로딩 될 때, 최초 한번 실행되며 이때 인스턴스를 생성. 인스턴스가 사용되는 시점에 생성 되는 것이 아님

· Lazy Initialization

public class LazyInitialization {
	private static LazyInitialization instance;
	
	private LazyInitialization () {
		
	}
	
	public static LazyInitialization getInstance () {
		if ( instance == null ) {
			instance = new LazyInitialization();
		}
		
		return instance;
	}
}

기본적으로 본인이 가장 많이 사용하는 방법. getInstance()에서 인스턴스가 없을 경우에만 새로 인스턴스를 생성해주는 방법. 하지만 multi thread의 경우 인스턴스가 두번 생길 위험이 존재함.

· Thread Safe Initialization

public class ThreadSafeInitalization {
	private static ThreadSafeInitalization instance;
	
	private ThreadSafeInitalization () {
		
	}
	
	public static synchronized ThreadSafeInitalization getInstance () {
		if (instance == null) {
			instance = new ThreadSafeInitalization();
		}
		
		return instance;
	}
}

위에 있는 Lazy Initialization의 multi thread 문제를 해결하기 위해 synchronized(동기화)를 사용하여 구현함. 높은 cost 비용으로 프로그램 전반에 성능 저하가 일어날 수 있음.

· Initialization on Demand Holder Idiom

public class InitializationOnDemandHolderIdiom {
	private InitializationOnDemandHolderIdiom () {
		
	}
	
	private static class Singleton {
		private static final InitializationOnDemandHolderIdiom instance = new InitializationOnDemandHolderIdiom();
	}
	
	public static InitializationOnDemandHolderIdiom getInstance () {
		return Singleton.instance;
	}
}

Bill pugh라는 컴퓨터 과학 연구원이 기존의 싱글턴 패턴의 문제점들을 해결하기 위해서 만든 새로운 싱글턴 패턴. 이것은 jvm의 class loader 매커니즘과 class load 시점을 이용하여 인스턴스를 생성시킴으로 thread간의 동기화 문제를 해결함. (Bill pugh가 만들었다 해서 Bill pugh Singleton이라고 부르기도 함)

· Enum Initialization

public enum EnumInitialization {
	INSTANCE;
		
	public static EnumInitialization getInstance() {
		return INSTANCE;
	}
}

Joshua Bolch의 Effective Java라는 책에서 소개된 enum 싱글턴 방법.

- enum은 인스턴스가 생성될 때, multi thread로부터 안전함

- 단 한번의 인스턴스 생성을 보장함.

- 또한 enum value는 자바 프로그램 전역에서 접근이 가능함.

따라서 위와 같은 이유로 enum을 싱글턴 패턴으로 사용될 수 있음.

 

※ 종류와 관련된 더욱 자세한 내용은 아래 [참고]에 나와있는 블로그를 봐주시면 되겠습니다.

싱글턴 패턴의 예

· Session

· Cache

· Logger

 

[참고] https://blog.seotory.com/post/2016/03/java-singleton-pattern

[참고] GoF의 디자인 패턴


WRITTEN BY
김치치즈스마일
세계정복!

,

앞서서 팩토리 메서드 패턴을 알아보았았다. 이번에는 추상 팩토리 패턴에 대해서 알아보도록 하자.

 

추상 팩토리 패턴이란?

· 상세화된 서브클래스를 정의하지 않고도 서로 관련성이 있거나 독립적인 여러 객체의 군을 생성하기 위한 인터페이스를 제공하는 패턴.

※ 키트(Kit) 패턴이라고도 불림.

 

 

우리가 편의점에서 자주 사먹는 삼각 김밥을 예를 들어보겠다. 삼각 김밥은 삼각 김밥을 만드는 어느 공장에서 만들어져서 편의점으로 운반되었을 것이다.

하지만 그 삼각 김밥 안에 들어가는 재료인 참치라던가 고기, 야채들은 각각의 참치 공장, 고기 공장, 야채 공장에서 다 손질되어서 삼각 김밥을 만드는 공장으로 운반되었을 것이다.

이와 같은 모양을 추상 팩토리 패턴에 대입해서 생각해보면 될 것 같다.

 

언제 추상 팩토리를 사용해야 할까?

· 객체가 생성되거나 구성 · 표현되는 방식과 무관하게 시스템을 독립적으로 만들고자 할 때.

· 여러 제품군 중 하나를 선택해서 시스템을 설정해야 하고 한번 구성한 제품을 다른 것으로 대체할 수 있을 때.

· 관련된 제품 객체들이 함께 사용되도록 설계되었고, 이 부분에 대한 제약이 외부에도 지켜지도록 하고 싶을 때.

· 제품에 대한 클래스 라이브러리를 제공하고, 그들의 구현이 아닌 인터페이스를 노출시키고 싶을 때.

 

구조

· AbstractFactory : 개념적 제품에 대한 객체를 생성하는 연산으로 인터페이스를 정의함.

· ConcreteFactory : 구체적인 제품에 대한 객체를 생성하는 연산을 구현함.

· AbstractProduct : 개념적 제품 객체에 대한 인터페이스를 정의함.

· ConcreteProduct : 구체적으로 팩토리가 생성할 객체를 정의하고, AbstractProduct가 정의하는 인터페이스를 구현함.

· Client : AbsctractFactory와 AbstractProduct 클래스에 선언된 인터페이스를 사용함.

 

추상 팩토리 패턴의 장점

· 구체적인 클래스가 사용자에게 분리되어 사용자 코드에는 나타나지 않음.

· 제품군을 쉽게 대체할 수 있도록 함.

· 제품 사이의 일관성을 증진시킴.

 

[프로그래밍/디자인 패턴] - 팩토리 메서드(Factory Method) 패턴

 

 

[참고] GoF의 디자인 패턴


WRITTEN BY
김치치즈스마일
세계정복!

,

우리는 무언가 추가하여 꾸밀 때 데코레이션한다는 표현을 많이 쓴다. 그렇다면 데코레이터 패턴도 무언가를 추가해서 꾸미는 패턴일까?

데코레이터 패턴이 무엇인지 한번 알아보자.

 

데코레이터 패턴이란?

· 객체에 동적으로 새로운 책임을 추가할 수 있게 하는 패턴. (서브클래스를 생성하는 것[상속]보다 융통성 있는 방법을 제공)

※ 장식자 패턴, 랩퍼(Wrapper) 패턴이라고도 부름.

 

· 무엇인가를 감싸는 객체를 데코레이터(Decorator)라고 부름. 데코레이터는 자신이 둘러싼 요소, 구성요소가 갖는 인터페이스를 자신도 동일하게 제공하므로, 데코레이터의 존재는 이를 사용하는 사용자에게 감춰짐.

즉, 데코레이터는 자신이 둘러싼 구성요소로 전달되는 요청을 중간에 가로채서 해당 구성요소에 전달해줌.

그렇기 때문에 이 전달 과정의 앞뒤에 다른 작업을 추가로 할 수 있음.

 

 

데코레이터 패턴이 무엇인지 알아보았지만 아직 와닿지는 않을 것이며, 언제 사용해야 할지 잘 모를 것이다. 그렇다면 이런 데코레이터 패턴은 언제 사용해야 좋을지 알아보자.

 

언제 데코레이터 패턴은 사용해야 할까?

· 동적으로 또한 투명하게, 다시 말해 다른 객체에 영향을 주지 않고 개개의 객체에 새로운 책임을 추가하기 위해 사용.

· 제거될 수 있는 책임에 대해 사용.

· 실제 상속으로 서브클래스를 계속 만드는 방법이 실질적이지 못할 때 사용. (너무 많은 수의 독립된 확장이 가능할 때 모든 조합을 지원하기 위해 이를 상속으로 해결하면 클래스 수가 폭발적으로 많아지게 됨)

 

구조


 

· Component : 동적으로 추가할 서비스를 가질 가능성이 있는 객체들에 대한 인터페이스.

· ConcreteComponent : 추가적인 서비스가 실제로 정의되어야 할 필요가 있는 객체.

· Decorator : Component 객체에 대한 참조자를 관리하면서 Component에 정의된 인터페이스를 만족하도록 인터페이스를 정의.

· ConcreteDecorator : Component에 새롭게 추가할 서비스를 실제로 구현하는 클래스.

 

데코레이터 패턴의 장점

· 단순한 상속보다 설계의 융통성을 더 많이 증대시킬 수 있음. (상속은 정적으로 새로운 클래스를 추가해야만 추가적인 행동을 정의할 수 있는 방법)

· 클래스 계통의 상부측 클래스에 많은 기능이 누적되는 상황을 피할 수 있음. *필요한 비용만 그때 지불해라!

 

데코레이터 패턴의 예

· 스트림(Stream)

 

 

[참고] GoF의 디자인 패턴


WRITTEN BY
김치치즈스마일
세계정복!

,