Design pattern/행동 패턴

[디자인 패턴]19장 중재자 패턴

미스터로즈 2021. 6. 15. 16:40

공부하기 위해서 요약정리해놓은 것입니다..

 

정확하고 꼼꼼한 자료는 쉽게 배워 바로 써먹는 디자인 패턴을 확인하시고

코드는 github.com/infohojin/patterns 을 참고해 주세요.

 

중재자 패턴은 분산된 다수의 객체 역활을 조정할 때 주로 사용됩니다.

 

중재

중재는 어떤 문제를 해결하거나 조정을 돕는 것을 말합니다. 객체지향에서는 분산된 객체의 행동을 중재합니다.

 

객체지향의 특징은 모든 행동을 하나의 객체에 집중하여 처리하지 않는다는 것입니다. 행동은 작은 단위로 분리하고, 목적 동작을 수행하기 위해 분리된 행동을 연결합니다.

객체지향은 하나의 커다란 행동을 작은 단위의 객체로 분산합니다. 이렇게 객체의 역활을 보다 작은 객체로 분할하는 이유는 동작을 재사용하기 위해서입니다.

 

객체의 행동을 작은 객체 단위로 분리하면, 객체는 목적으로 하는 행동을 수행하기 위해 객체간에 의존 관계가 발생합니다. 이렇게 분리된 객체의 의존 관계는 구조적으로 복잡한 연결 고리를 생성합니다.

 

중재자의 사전적 의미를 찾아보면 중재인, 조정관, 중재기관이라는 뜻이 있습니다.

이해 관계자가 많은 경우 이를 정리하는 중개인이 있으면 일을 보다 편리하게 처리할 수 있습니다.

 

객체의 행동을 중재하기 위해서는 복잡한 구조적 관계를 개선해야 합니다.

중재자는 객체 간 복잡한 상호 관계를 중재하며 객체 간에 복잡한 관계로 묶인 것을 재구성합니다. 즉 서로 의존적인 M:N의 관계를 가진 객체를 느슨한 1:1 관계로 변경합니다.

 

중재자 역활을 수행하는 객체를 관계 중심에 추가합니다. 중재자는 각각의 객체를 자신과 연결하고, 객체의 행위 요청을 중앙에서 제어합니다.

객체는 더 이상 상호 간에 직접적으로 접근하지 않는 대신 중재자에게 필요한 행동을 요청합니다. 중재자 패턴을 사용하면 여러 클래스가 서로 직접적으로 호출해 복잡한 관계를 느슨한 결합으로 만듭니다. 그리고 느슨한 결합은 객체의 재사용성과 유연성을 높입니다.

 

중재자

중재자는 객체 간 상호 작용을 제어하며 객체의 동작을 조화롭게 조정하는 역활을 수행합니다.

 

중재자는 하나의 중재자와 여러 동료 객체로 구성되어 있으며, 동료 객체의 강력한 결합 구조를 느슨한 결합 구조로 개선합니다.

 

중재자는 객체 간에 상호 작용을 제어하고 조화롭게 만드는 역활을 합니다. 호출이 필요한 경우 동료 객체가 다른 동료 객체에 직접 접근해서 호출하지 않으며, 중재자를 의존해서 다른 동료 객체를 호출합니다. 즉 각각의 동료 객체가 서로 통신하는 것이 아니라 중재자를 통해 통신하는 것입니다.

 

중재자의 공통된 부분을 추상화

<?php

abstract class Mediator
{
    // 중재를 해야될 객체의 목록을 가지고 있습니다
    protected $Colleague = [];

    /**
     * Colleague를 추가합니다.
     */
    public function addColleague($obj)
    {
        array_push($this->Colleague, $obj);
    }

    // 동료을 생성합니다.
    abstract public function createColleague();

}

추상 클래스는 $Colleague 배열을 이용해 복수의 동료 객체를 관리합니다. 접근 속성은 추상 클래스를 상속할 수 있도록 protected로 설정합니다.

 

실제적인 중재 동작은 ConcreteMediator 클래스에 선언합니다.

<?php
/**
 * concreteMediator
 */
class Server extends Mediator
{
    public function __construct()
    {
        echo "중재자 생성이 되었습니다.\n";
        $this->Colleague = array();
    }    

    public function createColleague()
    {
        // 동료 객체 목록을 초기화 합니다.
    }

    /**
     * 중재 기능
     */
    public function mediate($data, $user)
    {
        echo ">> ".$user." 로 부터 서버 메시지를 받았습니다.\n";
  
        // 모든 colleague에게 전달받은 메시지를 통보합니다.
        foreach ($this->Colleague as $obj) {
            echo "<< ". $obj->userName() ." : ";
            $obj->message($data);
        }
    }
}

중재자의 핵심 기능은 mediate() 메서드 입니다. mediate() 메서드는 각각의 동료 객체로 부터 호출되며, 호출된 mediate() 메서든든 다시 전달해야 하는 동료 객체의 메서드를 재호출합니다.

 

동료 객체

동료 객체는 분산된 행동들의 독립된 객체입니다. 동료 객체는 직접 통신하지 않고 중재자를 통해서만 상호 통신하도록 제한됩니다.

 

중재자 패턴은 객체의 강력한 구조적 결합 문제점을 해결합니다. 동료 객체끼리 정보를 직접 주고받지 않도록 통신 경로를 제한합니다. 또한 서로의 참조 정보를 전달하지도 않습니다.

 

중재자 패턴을 설계할 때는 경로의 수가 증가함에 따라 성능이 저하되지 않도록 신경써서 구상해야 합니다.

 

Colleague 인터페이스는 Mediator와의 통신을 처리하기 위해 동료 객체에 적용되는 인터페이스입니다.

<?php

abstract class Colleague
{
    protected $Mediator;

    /**
     * 중개 객체를 설정합니다.
     * concreteMediator에 의해서 호출됩니다.
     */
    public function setMediator($mediator)
    {
        $this->Mediator = $mediator;
    }

}

 

Colleague를 상속받아 실제적인 concreateColleague를 생성합니다. 처리할 행동에 따라 다수의 concreateColleague를 생성할 수도 있습니다.

<?php
/**
 * concreteColleague
 */
class User extends Colleague
{
    protected $name;

    public function __construct($name)
    {
        echo "colleague가 등제 되었습니다.\n";
        $this->name = $name;
    }

    /**
     * 사용자 이름을 확인합니다.
     */
    public function userName()
    {
        return $this->name;
    }

    /**
     * 메시지를 전달합니다.
     */
    public function send($data)
    {
        // 중개 서버로 메시지를 전송합니다.
        $this->Mediator->mediate($data, $this->name);
    }

    public function message($data)
    {
        echo "<< ".$data."\n";
    }
}

Colleague 객체는 독립적이며 재사용 가능한 객체이므로 통신 방법에 따라 Colleague에 구현해야 하는 메서드가 달라집니다.

send()는 중재자에게 처리를 요청하는 메서드이며, message()는 중재자로부터 처리를 부여받는 메서드입니다.

 

중재자 패턴은 여러 객체들의 복잡한 상호 의존성을 느슨한 소결합으로 재조정합니다. 또한 1:1 관계로 통신하여 보다 간단히 처리합니다. 중재자 패턴은 생성된 객체의 재사용이 용이하도록 만들 수도 있지만, 잘못된 중재자의 설계는 더 복잡한 객체를 생성할 수 있으므로 주의할 필요가 있습니다.