[디자인 패턴] Mediator 패턴

열심히 사는 루피 🥰·2021년 8월 10일
0

디자인 패턴

목록 보기
1/3
post-thumbnail

Mediator(중재자) 패턴

​ 객체간의 상호작용을 캡슐화하여 하나의 중재자 클래스가 이를 처리하고 분산시켜주는 패턴이다.

👿 문제상황

회원가입을 기능을 만드려고 합니다. 아래 두 가지 기능을 넣고 싶습니다.

1. 빈칸이 있는 채로 버튼을 누르면 채워달라고 경고문을 텍스트로 출력하고 싶습니다.
2. 빈칸이 없는 채로 버튼을 누르면 회원 가입이 완료 됐다는 이미지를 띄우고 싶습니다.


문제 1)
우리는 버튼기능에 빈칸이 있는 경우, 없는 경우 각자 다르게 구현해야 합니다.
그 안에 텍스트박스에 대한 내용, 이미지 로딩에 대한 내용을 모두 연관지어야 합니다.

문제 2) 해당 버튼의 로직은 다른 페이지에서는 재활용하기 어렵습니다. 왜냐면 위 두 기능과 연관되기 때문입니다.

😇 어떻게 해결할까

​ 그렇다면 버튼 클릭이라는 이벤트를 전달받아 경고문 텍스트박스와 이미지 로더에 따로 그 이벤트를 전달하면 어떨까요?

버튼은 버튼 클릭만, 텍스트박스는 텍스트만, 이미지로더는 이미지로딩 기능만 담당하면 됩니다!

그래서 다른 페이지에서도 버튼, 경고문, 이미지로더를 각자 사용할 수 있습니다.

이렇게 버튼, 텍스트박스, 이미지 로더가 각자 자기 역할만 수행할 수 있도록, 그 사이의 상호작용을 전달하고 조절해주도록 중재자를 설정해주는 것이 Mediator 패턴입니다!

🤔 구현을 어떻게 할까

  1. 컴포넌트들 구현

    • 버튼 - 클릭 이벤트 발생시키고 메디에이터에 노티
    • 텍스트 - 텍스트 띄움
    • 이미지- 이미지 로딩하고 띄움)
  2. Mediator (조정해주기)

    • 클릭 이벤트 받음

    • 클릭 이벤트 발생시 경우 처리 -> 텍스트나 이미지에 일 시키기

📜 코드로 살펴볼까요!

  1. Mediator
//Mediator 인터페이스 선언 
//Mediator 인터페이스 선언 
// - 모든 Mediator는 전달 받는 기능인 notify가 필요하다고 구현
public interface Mediator {
    void notify(Component sender, String event);
}

//회원가입에서 사용될 Mediator
public class ConcreteMediator implements Mediator{
    private Button button;
    private TextBox textBox;
    private ImageLoader imageLoader;

    //Mediator에서 사용할 컴포넌트를 연결, 컴포넌트들에 Mediator를 연결
    public ConcreteMediator(Button button, TextBox textBox, ImageLoader imageLoader) {
        this.button = button;
        this.button.setMediator(this);

        this.textBox = textBox;
        this.textBox.setMediator(this);

        this.imageLoader = imageLoader;
        this.imageLoader.setMediator(this);
    }

    //각 컴포넌트들에게 noti가 왔을 때 처리해줄 내용
    @Override
    public void notify(Component sender, String event) {
        if(sender== button && event == "click"){ //버튼 클릭이벤트 발생시
            if(textBox.getText()=="")){//텍스트 비어있는지 확인
                textBox.warning();//비어있으면 경고
            }else{
                imageLoader.ImageLoad();//있으면 이미지 로드
            }
        }
    }
}
  1. 컴포넌트들
//컴포넌트 부모 클래스
public class Component {
    protected Mediator mediator;

    public void setMediator(Mediator mediator) {
        this.mediator = mediator;
    }
}


//버튼 -> 클릭 이벤트 발생
public class Button extends Component {
    @Override
    public void setMediator(Mediator mediator) {
        super.setMediator(mediator);
    }

    public void click(){
        System.out.println("[버튼 클릭] \n");
        super.mediator.notify(this,"click");
    }
}

//이미지 로더 -> 이미지 로드 후 이미지 띄움
public class ImageLoader extends Component{

    @Override
    public void setMediator(Mediator mediator) {
        super.setMediator(mediator);
    }

    public void ImageLoad(){
        System.out.println("이미지 로딩 \n");
        System.out.println("=========img========");
        System.out.println("\n");
        System.out.println("회원 가입을 축하드립니다!");
        System.out.println("\n");
        System.out.println("====================");
    }
}

//텍스트 박스 -> 인풋 또는 경고문만 출력
public class TextBox extends Component{
    String text;
    @Override
    public void setMediator(Mediator mediator) {
        super.setMediator(mediator);
    }

    public String getText() {
        return text;
    }

    public void warning(){
        System.out.println("=========TEXT========");
        System.out.println("공란을 채워주세요.");
        System.out.println("=====================\n");
    }

    public void input(String input){
        text = input;
        System.out.println("=========TEXT========");
        System.out.println(input);
        System.out.println("====================\n");
    }
}
//컴포넌트 부모 클래스
public class Component {
    protected Mediator mediator;

    public void setMediator(Mediator mediator) {
        this.mediator = mediator;
    }
}


//버튼 -> 클릭 이벤트 발생
public class Button extends Component {
    @Override
    public void setMediator(Mediator mediator) {
        super.setMediator(mediator);
    }

    public void click(){
        System.out.println("[버튼 클릭] \n");
        super.mediator.notify(this,"click");
    }
}

//이미지 로더 -> 이미지 로드 후 이미지 띄움
public class ImageLoader extends Component{

    @Override
    public void setMediator(Mediator mediator) {
        super.setMediator(mediator);
    }

    public void ImageLoad(){
        System.out.println("이미지 로딩 \n");
        System.out.println("=========img========");
        System.out.println("\n");
        System.out.println("회원 가입을 축하드립니다!");
        System.out.println("\n");
        System.out.println("====================");
    }
}

//텍스트 박스 -> 인풋 또는 경고문만 출력
public class TextBox extends Component{
    String text;
    @Override
    public void setMediator(Mediator mediator) {
        super.setMediator(mediator);
    }

    public String getText() {
        return text;
    }

    public void warning(){
        System.out.println("=========TEXT========");
        System.out.println("공란을 채워주세요.");
        System.out.println("=====================\n");
    }

    public void input(String input){
        text = input;
        System.out.println("=========TEXT========");
        System.out.println(input);
        System.out.println("====================\n");
    }
}
  1. Main
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {

        Scanner scanner = new Scanner(System.in);
        Button button = new Button();
        TextBox textBox = new TextBox();
        ImageLoader imageLoader = new ImageLoader();
        Mediator mediator = new ConcreteMediator(button,textBox,imageLoader);

        //정보 입력받기
        System.out.println("=====회원가입========");
        System.out.println("아이디 입력 : ");
        String input = scanner.nextLine();
        //텍스트 박스에 입력
        textBox.input(input);
        //버튼 클릭하기
        button.click();
    }
}

💻 결과

  1. 입력 없을 때
=====회원가입========
아이디 입력 : 

=========TEXT========

====================

[버튼 클릭]

=========TEXT========
공란을 채워주세요.
==================== 
  1. 입력 있을 때
=====회원가입========
아이디 입력 : 
Loopy
=========TEXT========
Loopy
====================

[버튼 클릭]

이미지 로딩 

=========img========


회원 가입을 축하드립니다!


====================

💕 참고한 링크들

  1. 기본적인 패턴 설명 (리팩토링 그루)
    https://refactoring.guru/design-patterns/mediator

  2. 리팩토링 그루 해석글, 컴포넌트 예시

    https://joycestudios.tistory.com/44

  3. 더 상세한 컴포넌트 예시(체크박스, 버튼, 텍스트박스로 로그인 dialog 구현)

    https://ocwokocw.tistory.com/m/111

  4. 디자인 패턴 설명 영상(얄코)

    https://www.youtube.com/watch?v=q3_WXP9pPUQ

profile
반가워_! 세상아!

0개의 댓글