스레드 안전 싱글톤 패턴: 멀티스레드 환경에서 안전한 단일 인스턴스 보장
Double-Checked Locking과 초기화 지연을 활용한 안전하고 효율적인 싱글톤 구현 가이드
커맨드 패턴은 요청을 객체의 형태로 캡슐화하여 사용자가 보낸 요청을 나중에 이용할 수 있도록 매개변수화하고, 큐에 넣거나 로그로 기록하거나 작업 취소 기능을 지원할 수 있게 해주는 소프트웨어 디자인 패턴입니다.
이 패턴의 핵심은 요청의 세부사항을 캡슐화하여 호출자와 수신자 사이의 결합도를 낮추고, 실행 취소, 재실행, 로깅 등의 기능을 쉽게 구현할 수 있다는 점입니다.
abstract class Command {
abstract fun execute(): String
abstract fun undo(): String
}모든 커맨드가 구현해야 할 기본 구조를 정의합니다. execute() 메서드는 커맨드를 실행하고, undo() 메서드는 실행을 취소합니다.
class Kimchi() {
fun cookKimchi(): String {
return "Cook Kimchi"
}
}Kimchi 클래스는 실제 작업을 수행하는 Receiver 역할을 합니다. 커맨드 패턴에서는 비즈니스 로직이 Receiver에 위치하며, ConcreteCommand는 이를 호출하는 역할만 수행합니다.
class CommandKimchi(private val kimchi: Kimchi) : Command() {
private val prevCook: String = "None"
override fun execute(): String {
return kimchi.cookKimchi()
}
override fun undo(): String {
return prevCook
}
}CommandKimchi는 구체적인 커맨드를 구현합니다. 이 클래스는 Kimchi 객체를 받아 실제 작업을 위임하며, 이전 상태를 저장하여 undo() 기능을 지원합니다.
class NoCommand : Command() {
override fun execute(): String {
return "No command"
}
override fun undo(): String {
return "No command"
}
}NoCommand는 Null Object 패턴을 구현한 것으로, 커맨드가 설정되지 않았을 때의 기본 동작을 정의합니다. 이를 통해 null 체크를 제거하고 코드를 단순화할 수 있습니다.
class InvokeCommand : Command() {
private var commend: Command = NoCommand()
fun setCommend(command: Command) {
commend = command
}
override fun execute(): String {
return commend.execute()
}
override fun undo(): String {
return commend.undo()
}
}InvokeCommand는 Invoker 역할을 합니다. 이 클래스는 실제 커맨드 객체를 가지고 있으며, 클라이언트의 요청에 따라 해당 커맨드를 실행하거나 취소합니다.
class CommandPatternTest {
@Test
fun testInvokeCommand() {
val invoker = InvokeCommand()
// 초기 상태 테스트 (NoCommand)
assertEquals("No command", invoker.execute())
assertEquals("No command", invoker.undo())
// Kimchi 커맨드 설정 및 테스트
val kimchi = Kimchi()
val kimchiCommand = CommandKimchi(kimchi)
invoker.setCommend(kimchiCommand)
assertEquals("Cook Kimchi", invoker.execute())
assertEquals("None", invoker.undo())
}
}새로운 커맨드를 추가할 때 기존 코드를 수정할 필요가 없습니다. Command 인터페이스를 구현하는 새로운 클래스만 추가하면 됩니다.
각 커맨드 클래스는 하나의 작업만 담당하므로, 코드의 책임이 명확하게 분리됩니다.
기존 코드를 수정하지 않고 새로운 커맨드를 추가할 수 있어 시스템의 확장성이 향상됩니다.
undo() 메서드를 통해 작업 취소 기능을 쉽게 구현할 수 있으며, 커맨드 히스토리를 유지하면 재실행도 가능합니다.
커맨드 객체를 저장하거나 로그로 남길 수 있어 복잡한 연산을 관리하고 추적하기 용이합니다.
실행 취소/재실행 기능을 구현할 때 각 편집 작업을 커맨드 객체로 캡슐화하여 히스토리를 관리합니다.
백그라운드에서 수행할 작업들을 커맨드 객체로 만들어 큐에 저장하고 순차적으로 실행합니다.
데이터베이스 작업을 커맨드로 캡슐화하여 롤백과 커밋을 쉽게 관리할 수 있습니다.
커맨드 패턴은 요청을 객체로 캡슐화하여 클라이언트와 수신자 사이의 의존성을 줄이고, 유연한 시스템 설계를 가능하게 합니다. 실행 취소, 재실행, 로깅과 같은 고급 기능을 구현해야 하는 경우 커맨드 패턴을 활용하면 효과적입니다.
이 패턴을 통해 개발자는 복잡한 작업을 단순한 인터페이스로 추상화하고, 시스템의 확장성과 유지보수성을 향상시킬 수 있습니다.
Double-Checked Locking과 초기화 지연을 활용한 안전하고 효율적인 싱글톤 구현 가이드
의존성을 낮추고 확장성을 높이는 팩토리 메서드 패턴의 구조와 실전 구현 가이드
객체의 행위를 동적으로 변경하고 코드 중복을 제거하는 전략 패턴 설계와 구현 가이드