ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Mediator Pattern(중재자 패턴)
    STUDY/디자인패턴 2025. 2. 2. 20:37

    중재자 패턴이란?

    객체 간의 혼란스러운 의존 관계들을 줄일 수 있는 행동 디자인 패턴으로, 객체 간의 직접 통신을 제한하고 중재자 객체를 통해서만 협력하도록 한다.

     

    즉, 중재자 패턴은 서로 독립적으로 작동해야 하는 컴포넌트 간의 모든 직접 통신을 중단한 후, 중재자 객체를 호출하여 적절한 컴포넌트들로 리다이렉션하여 컴포넌트들이 간적접으로 협력하도록 한다. 이 패턴을 사용하면 컴포넌트 사이의 복잡한 M:N 의존관계가 중재자와의 M:1 의존관계가 되므로 결합도를 감소시키게 된다.

     

    구조

    • Mediator

    중재자 인터페이스

     

    • ConcreteMediator

    중재자 인터페이스를 구현한 구상 클래스로, 다양한 컴포넌트 간의 관계를 캡슐화한다. 구상 클래스들은 자신이 관리하는 모든 컴포넌트에 대한 참조를 유지하고 그들의 수명 주기를 관리하기도 한다.

     

    • Component

    비즈니스 로직을 포함한 다양한 클래스들로, 각 컴포넌트에는 중재자에 대한 참조를 가진다. 컴포넌트들은 다른 컴포넌트들을 인식하지 않고 중재자를 통해서만 작동한다.

     

    예시

     

    Component

    public interface Component {
        void setMediator(Mediator mediator);
        String getName();
    }
    public class AddButton extends JButton implements Component {
        private Mediator mediator;
    
        public AddButton() {
            super("Add");
        }
    
        @Override
        public void setMediator(Mediator mediator) {
            this.mediator = mediator;
        }
    
        @Override
        protected void fireActionPerformed(ActionEvent actionEvent) {
            mediator.addNewNote(new Note());
        }
    
        @Override
        public String getName() {
            return "AddButton";
        }
    }
    
    public class DeleteButton extends JButton  implements Component {
        private Mediator mediator;
    
        public DeleteButton() {
            super("Del");
        }
    
        @Override
        public void setMediator(Mediator mediator) {
            this.mediator = mediator;
        }
    
        @Override
        protected void fireActionPerformed(ActionEvent actionEvent) {
            mediator.deleteNote();
        }
    
        @Override
        public String getName() {
            return "DelButton";
        }
    }
    
    public class SaveButton extends JButton implements Component {
        private Mediator mediator;
    
        public SaveButton() {
            super("Save");
        }
    
        @Override
        public void setMediator(Mediator mediator) {
            this.mediator = mediator;
        }
    
        @Override
        protected void fireActionPerformed(ActionEvent actionEvent) {
            mediator.saveChanges();
        }
    
        @Override
        public String getName() {
            return "SaveButton";
        }
    }

     

    Mediator

    public interface Mediator {
        void addNewNote(Note note);
        void deleteNote();
        void getInfoFromList(Note note);
        void saveChanges();
        void markNote();
        void clear();
        void sendToFilter(ListModel listModel);
        void setElementsList(ListModel list);
        void registerComponent(Component component);
        void hideElements(boolean flag);
        void createGUI();
    }

     

    ConcreteMediator

    public class Editor implements Mediator {
        private Title title;
        private TextBox textBox;
        private AddButton add;
        private DeleteButton del;
        private SaveButton save;
        private List list;
        private Filter filter;
    
        private JLabel titleLabel = new JLabel("Title:");
        private JLabel textLabel = new JLabel("Text:");
        private JLabel label = new JLabel("Add or select existing note to proceed...");
      
        @Override
        public void registerComponent(Component component) {
            component.setMediator(this);
            switch (component.getName()) {
                case "AddButton":
                    add = (AddButton)component;
                    break;
                case "DelButton":
                    del = (DeleteButton)component;
                    break;
                case "Filter":
                    filter = (Filter)component;
                    break;
                case "List":
                    list = (List)component;
                    this.list.addListSelectionListener(listSelectionEvent -> {
                        Note note = (Note)list.getSelectedValue();
                        if (note != null) {
                            getInfoFromList(note);
                        } else {
                            clear();
                        }
                    });
                    break;
                case "SaveButton":
                    save = (SaveButton)component;
                    break;
                case "TextBox":
                    textBox = (TextBox)component;
                    break;
                case "Title":
                    title = (Title)component;
                    break;
            }
        }
    
        @Override
        public void addNewNote(Note note) {
            title.setText("");
            textBox.setText("");
            list.addElement(note);
        }
    
        @Override
        public void deleteNote() {
            list.deleteElement();
        }
    
        @Override
        public void getInfoFromList(Note note) {
            //...
        }
    
        @Override
        public void saveChanges() {
            try {
                Note note = (Note) list.getSelectedValue();
                note.setName(title.getText());
                note.setText(textBox.getText());
                list.repaint();
            } catch (NullPointerException ignored) {}
        }
    
        @Override
        public void markNote() {
            //...
        }
    
        @Override
        public void clear() {
            //...
        }
    
        @Override
        public void sendToFilter(ListModel listModel) {
            //...
        }
    
        @SuppressWarnings("unchecked")
        @Override
        public void setElementsList(ListModel list) {
            //...
        }
    
        @Override
        public void hideElements(boolean flag) {
            //...
        }
    
        @Override
        public void createGUI() {
            //...
        }
    }

     

    적용

    1. 일부 클래스들이 다른 클래스들과 단단하게 결합하여 변경하기 어려운 경우
    2. 타 컴포넌트들에 너무 의존하기 때문에 다른 프로그램에서 컴포넌트를 재사용할 수 없는 경우
    3. 몇 가지 기본 행동을 다양한 콘텍스트들에서 재사용하기 위해 수많은 컴포넌트 자식 클래스들을 만들고 있는 경우

     

    장단점

    장점

    • 단일 책임 원칙. 다양한 컴포넌트 간의 통신을 한 곳으로 추출하여 코드를 이해하고 유지 관리하기 쉽게 만들 수 있다.
    • 개방/폐쇄 원칙. 실제 컴포넌트들을 변경하지 않고도 새로운 중재자들을 도입할 수 있다.
    • 프로그램의 다양한 컴포넌트 간의 결합도를 줄일 수 있다.
    • 개별 컴포넌트들을 재사용하기 쉽다.

     

    단점

    • 중재자가 전지전능한 객체로 발전할 수 있다.
Designed by Tistory.