JAVA 디자인 패턴은 엄청나게 유용하다[작성중]

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);
  }

}



Composite 같은 Type의 구현체들을 주입시켜주는 모습