컴퓨터과학/0 + 소프트웨어 아키텍처(디자인 패턴)

[소프트웨어 아키텍처] 10. 중재자 패턴(Mediator Pattern -java)

힘들면힘을내는쿼카 2022. 12. 5. 17:29
728x90
반응형

중재자 패턴(Mediator Pattern)

모든 클래스간의 복잡한 로직을 캡슐화하여 하나의 클래스에 위임하여 처리하는 패턴
N:M의 관계에서 N:1의 관계로 복잡도를 낮추어 유지보수 및 재사용의 확장성에 유리한 패턴 입니다.
객체 간의 메시지를 전달할 일이 있을 때도 중재자를 두고 전달할 수 있다.

서로 관련된 객체 사이의 복잡한 통신과 제어를 한곳으로 집중하고 싶을 때 사용합니다.

주로 UI 프로그래밍에서 많이 사용되는 방법으로 Widget 간의 상호 처리를 서로간에 처리하는 것이 아니라 한 객체가 전담하여 처리하도록 하는 방식입니다.


Facade Pattern, Observer Pattern과 유사하다.

중재자 패턴 구조

  • Mediator
    • 여러 Colleague를 중재하는 인터페이스
  • Colleague
    • Mediator의 참조자를 가지고 있고, 다른 객체와의 협력이 필요할때 Mediator에게 알림
  • ConcreteColleague
    • Colleague간에 이루어지는 협력을 구현하고, 자신의 Colleague들을 관리함

항공 관제센터 애플리케이션 개발

중재자 패턴을 사용해서 항공 관제센터 애플리케이션을 개발해보자.

AirController

public interface AirController {

    void add(AirPlane airPlane);
    void delete(AirPlane airPlane);
    void send(String message, AirPlane airPlane);
    void receive(String message, AirPlane airPlane);
    void sendAll(String message, AirPlane airPlane);
}

KoreAirController

public class KoreaAirController implements AirController {

    private List<AirPlane> airPlanes = new ArrayList<>();
    private String message;

    @Override
    public void add(AirPlane airPlane) {
        airPlanes.add(airPlane);
    }

    @Override
    public void delete(AirPlane airPlane) {
        airPlanes.remove(airPlane);
    }

    /**
     * 객체 서로간의 메시지를 중재자를 두고 전달할 수 있다.
     * @param message
     * @param fromPlane
     * @param toPlane
     */
    @Override
    public void send(String message, AirPlane fromPlane, AirPlane toPlane) {
        System.out.println(fromPlane.getName()+"님, 여기는 코리아 항공 관제센터 입니다. "+toPlane.getName()+"에게 내용 전달합니다. ["+message+"] 이상");
        toPlane.receive(message);
    }

    @Override
    public void receive(String message, AirPlane airPlane) {
        if(airPlane instanceof AirPlane707) {
            System.out.println(airPlane.getName()+"님, 여기는 코리아 항공 관제센터 입니다. 아래 메시지 수신 받았습니다. ["+message+"] 수신 양호");
        }
        if(airPlane instanceof JejuAirPlane) {
            System.out.println(airPlane.getName()+"님, 여기는 코리아 항공 관제센터 입니다. 아래 메시지 수신 받았습니다. ["+message+"] 수신 양호");
        }
    }

    @Override
    public void sendAll(String message, AirPlane airPlane) {
        for (AirPlane plane : airPlanes) {
            if(plane != airPlane) {
                System.out.println("모든 비행기에 알립니다. "+airPlane.getName()+"님, 여기는 코리아 항공 관제센터 입니다. 내용 전달합니다. ["+message+"] 이상");
                plane.receive(message);
            }
        }
    }
}

AirPlane

public interface AirPlane {
    void send(String message);
    void receive(String message);
    String getName();
}

JejuAirPlane

public class JejuAirPlane implements AirPlane {

    private AirController airController;
    private String name;

    public JejuAirPlane(AirController airController, String name) {
        this.airController = airController;
        this.name = name;
    }

    @Override
    public void send(String message) {
        System.out.println("여기는 "+name+" 입니다. ["+message+ "] 이상.");
        airController.receive(message, this);
    }

    @Override
    public void receive(String message) {
        System.out.println("여기는 "+name+" 입니다. 아래 메시지 수신 받았습니다. ["+message+"] 수신양호 이상.");
    }

    @Override
    public String getName() {
        return this.name;
    }
}

AirPlane707

public class AirPlane707 implements AirPlane {

    private AirController airController;
    private String name;

    public AirPlane707(AirController airController, String name) {
        this.airController = airController;
        this.name = name;
    }

    @Override
    public void send(String message) {
        System.out.println("여기는 "+name+" 입니다. ["+message+ "] 이상.");
        airController.receive(message, this);
    }

    @Override
    public void receive(String message) {
        System.out.println("여기는 "+name+" 입니다. 아래 메시지 수신 받았습니다. ["+message+ "] 수신양호 이상.");
    }


    @Override
    public String getName() {
        return this.name;
    }
}

Client

public class Client {
    public static void main(String[] args) {
        AirController airController = new KoreaAirController();
        AirPlane airPlane707 = new AirPlane707(airController, "항공707");
        AirPlane jejuAirPlane = new JejuAirPlane(airController, "제주항공");

        airController.add(airPlane707);
        airController.add(jejuAirPlane);

        airController.sendAll("현재 문제 없습니다. 좋은 비행 되세요.", airPlane707);

        airPlane707.send("감사합니다. 안전비행 하겠습니다.");
        jejuAirPlane.send("감사합니다. 좋은 하루되세요.");

        System.out.println("\n==================================================================================");
        airController.send("만나서 반갑습니다.!", airPlane707, jejuAirPlane);
    }
}

결과

모든 비행기에 알립니다. 항공707님, 여기는 코리아 항공 관제센터 입니다. 내용 전달합니다. [현재 문제 없습니다. 좋은 비행 되세요.] 이상
여기는 제주항공 입니다. 아래 메시지 수신 받았습니다. [현재 문제 없습니다. 좋은 비행 되세요.] 수신양호 이상.
여기는 항공707 입니다. [감사합니다. 안전비행 하겠습니다.] 이상.
항공707님, 여기는 코리아 항공 관제센터 입니다. 아래 메시지 수신 받았습니다. [감사합니다. 안전비행 하겠습니다.] 수신 양호
여기는 제주항공 입니다. [감사합니다. 좋은 하루되세요.] 이상.
제주항공님, 여기는 코리아 항공 관제센터 입니다. 아래 메시지 수신 받았습니다. [감사합니다. 좋은 하루되세요.] 수신 양호

==================================================================================
항공707님, 여기는 코리아 항공 관제센터 입니다. 제주항공에게 내용 전달합니다. [만나서 반갑습니다.!] 이상
여기는 제주항공 입니다. 아래 메시지 수신 받았습니다. [만나서 반갑습니다.!] 수신양호 이상.

중재자 패턴의 장단점

장점

  • 시스템과 객체를 분리함으로써 재사용성을 획기적으로 향상시킬 수 있음
  • 제어 로직을 한 곳(Mediator)에 모아놓았기 때문에 관리가 수월함
  • 시스템에 들어있는 객체 사이에서 오가는 메시지를 확 줄이고 단순화할 수 있음

단점

  • 디자인 설계를 잘못하면 중재자(Mediator) 객체가 너무 복잡해질 수 있음

결론

  • 다른 객체사이에 분산된 객체의 연관관계를 하나의 객체로 국한
  • Colleague 객체들 간의 종속성이 약화되어 결합도가 줄어듦
  • 다대다의 관계를 일대다의 관계로 축소하여 유지보수에 용이

 

 

728x90
반응형