JAVA 디자인 패턴은 엄청나게 유용하다[작성중]
디자인 패턴은 소프트웨어 설계시에 유용하다. 하나 씩 실 사용을 목적으로 정리해보자.
Gof(Gang of Four) 디자인 패턴에는 3가지 카테고리가 존재합니다.
- 구조 패턴(Structural Pattern)
- 구조 패턴은 객체와 클래스를 구성하는 방법에 초점을 맞춘 디자인 패턴입니다.
- 이러한 패턴은 복잡한 구조를 보다 효율적으로, 그리고 유연하게 설계하도록 도와줍니다.
- 구조 패턴의 주요 목표는 다양한 객체들 간의 관계를 쉽게 만들고, 이를 통해 큰 시스템을 유연하고 효과적으로 설계하는 것입니다.
- 생성(Creational) 패턴
- 객체 생성 메커니즘을 중심으로 하며, 객체를 생성, 조합하는 방식을 유연하게 만드는 데 중점을 둡니다.
- 예: 싱글톤, 팩토리 메서드, 빌더 패턴
- 행동(Behavioral) 패턴
- 객체들 사이의 책임 분배와 협력 방식에 초점을 맞춘 패턴입니다.
- 이들은 객체 간의 상호작용과 책임을 어떻게 분배할지를 다룹니다.
- 예: 옵저버, 전략, 커맨드 패턴
유용하다 생각되는 패턴을 개별적으로 하나씩 공략해나가기로 한다.
Composite패턴
설명
Composite 패턴은 일반적으로 ‘부분-전체’ 관계를 표현하는 데 사용됩니다.
이를 통해 개별 객체와 객체의 집합을 동일하게 취급할 수 있습니다.
간단히 말해서, 단일 객체와 그 객체들의 집합체를 같은 방식으로 다룰 수 있게 해주는 패턴이에요.
예시
예를 들어, 생일 파티를 준비한다고 생각해 봅시다. 파티 준비에는 여러 가지 작업이 필요해요.
예를 들면 풍선 불기, 케이크 굽기, 초대장 보내기 등등이죠.이런 각각의 작업들을 ‘단일 작업’이라고 할 수 있어요.
그런데 이 작업들을 모아서 ‘파티 준비’라는 큰 작업으로 볼 수도 있습니다. 이때 ‘파티 준비’는 여러 ‘단일 작업’들의 집합이 되는 거죠.
Composite 패턴은 이렇게 단일 작업과 작업들의 집합을 같은 방식으로 다룰 수 있게 해줍니다.
//file: `생일준비 Composite패턴 예시`
// 작업을 나타내는 인터페이스
public interface BirthDayTask {
void perform(String context);
}
//단일 작업 - Leaf
@Component
public class BalloonInflation implements BirthDayTask {
@Override
public void perform(String context) {
System.out.println("풍선을 불고 있습니다. 상황: " + context);
}
}
//단일 작업 - Leaf
@Component
public class CakeBaking implements BirthDayTask{
@Override
public void perform(String context) {
System.out.println("케이크를 굽습니다. 상황: " + context);
}
}
//단일 작업 - Leaf
@Component
public class InvitationSending implements BirthDayTask{
@Override
public void perform(String context) {
System.out.println("초대장을 보냅니다. 상황: " + context);
}
}
// 작업들의 집합 - Composite
@Component
public class PartyPreparation implements BirthDayTask{
private final List<BirthDayTask> tasks;
public PartyPreparation(List<BirthDayTask> tasks) {
this.tasks = tasks;
}
@Override
public void perform(String context) {
tasks.forEach(task -> task.perform(context));
}
}
개별 작업인 BalloonInflation, CakeBaking, InvitationSending은 각각의 작업을 수행하는 클래스입니다.
이들은 BirthDayTask 인터페이스를 구현하고 있습니다.
PartyPreparation은 BirthDayTask 인터페이스를 구현하고 있습니다.
이 클래스는 BirthDayTask 인터페이스를 구현하는 클래스들의 집합입니다.
사용 객체는 원하는 BirthDayTask 인터페이스를 구현한 클래스를 사용할 수 있습니다.
실제 스프링에서 사용시에는 아래와 같은 방법이 좋지 않을까 추측해봅니다.
//file: `생일준비 Composite패턴 Clinet 예시`
@Component
public class BirthDayClient {
private final BirthDayTask partyPreparation;
private final BirthDayTask balloonInflation;
public BirthDayClient(@Qualifier("partyPreparation") BirthDayTask partyPreparation, @Qualifier("balloonInflation") BirthDayTask balloonInflation) {
this.partyPreparation = partyPreparation;
this.balloonInflation = balloonInflation;
}
public void run(String context) {
partyPreparation.perform(context);
balloonInflation.perform(context);
}
}