If-Else문, 아도겐코드, 피라미드 지옥 방지! (feat. Spring Boot) [2]

리본24·2024년 9월 2일
post-thumbnail

이전편에 이어서..


- 람다식, FunctionalInterface

사실 람다식은 실무에서는 되도록 쓰지않는 것을 지양하는 편이다.
그래서 이 곳에 추가하는게 맞는지 잘 모르겠다.
따로 빼서 설명하도록 하겠습니다.

https://velog.io/@ribbon24/[JAVA] 람다식


- Command 패턴

Command 패턴은 행동(Behavioral) 패턴 중 하나로, 요청을 객체로 캡슐화하여 요청을 파라미터화하거나, 큐에 저장하고 나중에 실행할 수 있도록 하는 디자인 패턴입니다. 커맨드 패턴을 사용하면 요청을 발신자(Invoker)와 수신자(Receiver)로부터 분리할 수 있어 작업의 실행, 취소, 반복 등을 유연하게 처리할 수 있습니다.

- 주요 구성 요소

  • Command 인터페이스: 실행할 명령을 정의하는 인터페이스입니다. 보통 execute() 메서드를 정의합니다.
  • ConcreteCommand: Command 인터페이스를 구현한 클래스로 명령이 구체적으로 어떻게 수행될지를 정의합니다. 이 클래스는 Receiver 객체를 알고 있어야 하며, 해당 Receiver 객체의 메서드를 호출하여 명령을 수행합니다.
  • Receiver: 실제로 명령을 수행하는 객체입니다. Receiver는 ConcreteCommand에 의해 호출되며, 작업을 구체적으로 처리합니다.
  • Invoker: 명령을 실행하는 주체입니다. ConcreteCommand 객체의 execute() 메서드를 호출하여 명령을 수행합니다.
  • Client: 명령 객체와 Invoker를 설정하고 실행하는 부분입니다. 명령 객체를 생성하고 이를 Invoker에게 전달하는 역할을 합니다.

- Command 패턴의 동작 과정

클라이언트(Client)는 실행하려는 명령을 구체적인 명령 객체(ConcreteCommand)로 캡슐화합니다.
이 명령 객체는 Receiver를 기반으로 작업을 처리합니다.
Invoker는 이 명령 객체를 받아 execute() 메서드를 호출하여 명령을 수행합니다.

- 커맨드 패턴의 장점

  1. 명령을 캡슐화: 요청을 객체로 캡슐화하여 파라미터화할 수 있고, 요청을 큐에 저장하거나 로그로 기록할 수 있습니다.
  2. 명령 취소 및 재실행: 명령의 실행과 취소가 가능하며, 작업의 반복 실행도 쉽게 구현할 수 있습니다.
  3. 확장성: 새로운 명령을 추가하는 것이 용이하여, 시스템이 확장되는 경우에도 유연하게 대처할 수 있습니다.
  • 코드 예시
// Command 인터페이스
public interface Command {
    void execute();
}

// Receiver 클래스
public class Light {
    public void turnOn() {
        System.out.println("The light is on");
    }

    public void turnOff() {
        System.out.println("The light is off");
    }
}

// ConcreteCommand 클래스
public class LightOnCommand implements Command {
    private Light light;

    public LightOnCommand(Light light) {
        this.light = light;
    }

    public void execute() {
        light.turnOn();
    }
}

public class LightOffCommand implements Command {
    private Light light;

    public LightOffCommand(Light light) {
        this.light = light;
    }

    public void execute() {
        light.turnOff();
    }
}

// Invoker 클래스
public class RemoteControl {
    private Command command;

    public void setCommand(Command command) {
        this.command = command;
    }

    public void pressButton() {
        command.execute();
    }
}

// Client 코드
public class Client {
    public static void main(String[] args) {
        Light light = new Light(); // Receiver
        Command lightOn = new LightOnCommand(light); // Command 객체
        Command lightOff = new LightOffCommand(light);

        RemoteControl remote = new RemoteControl(); // Invoker

        // 불 켜기
        remote.setCommand(lightOn);
        remote.pressButton();

        // 불 끄기
        remote.setCommand(lightOff);
        remote.pressButton();
    }
}

- Guard Clauses 사용하기

Guard Clauses는 조건을 조기에 처리하도록하여 코드를 더 읽기 쉽고 중첩된 분기 구조를 줄일 수 있습니다.

간단한 user validation 예제를 들면 다음과 같습니다.

public class UserService {
    public void registerUser(User user) {
        if (user == null) {
            throw new IllegalArgumentException("User cannot be null");
        }
        if (user.getName() == null || user.getName().isEmpty()) {
            throw new IllegalArgumentException("User name cannot be empty");
        }
        if (user.getEmail() == null || user.getEmail().isEmpty()) {
            throw new IllegalArgumentException("User email cannot be empty");
        }
        // Proceed with registration
        System.out.println("Registering user: " + user.getName());
    }
}
profile
기록하고 소화해보자! 소화가 안되거나 까먹으면 다시 꺼내서 보자! 오늘의 나는 어제의 나보다 강하다!

0개의 댓글