객체 지향 프로그래밍에서 객체 간의 상호작용은 중요한 요소입니다. 객체들은 서로 연결되어 있으며 다른 객체를 참조하여 작업을 수행합니다. 그러나 객체가 너무 많아지면 서로 꼬일 수 있습니다. 이러한 문제를 해결하기 위해 메디에이터 패턴이 등장했습니다. 메디에이터 패턴은 객체 간의 상호작용을 관리하고 중개하는 디자인 패턴으로, 객체 간의 결합도를 낮출 수 있습니다.

메디에이터 패턴이란 무엇인가?

메디에이터 패턴은 객체 간의 상호작용을 중개하고 관리하기 위한 디자인 패턴입니다. 이 패턴은 객체들이 서로 직접적으로 통신하지 않고, 중개자를 통해 통신하도록 합니다. 이로 인해 객체 간 결합도가 낮아지고, 객체들은 더 유연하고 확장성 있는 디자인을 구현할 수 있습니다.

메디에이터 패턴은 다음과 같은 구성 요소를 포함합니다.

  • Mediator(중개자) : 객체 간의 상호작용을 중개하고 관리하는 클래스입니다. 이 클래스는 객체들이 서로 직접적으로 통신하지 않도록 합니다.
  • Colleague(동료) : 중개자와 상호작용하는 객체입니다. 이 객체는 중개자와 연결됩니다.
//Mediator
public interface ChatMediator {
    public void sendMessage(String message, User user);
    public void addUser(User user);
}

// Colleague
public class UserImpl extends User {
    public UserImpl(ChatMediator med, String name) {
        super(med, name);
    }

    @Override
    public void send(String message) {
        System.out.println(this.name+": Sending Message="+message);
        mediator.sendMessage(message, this);
    }
    @Override
    public void receive(String message) {
        System.out.println(this.name+": Received Message:"+message);
    }
}

// ConcreteMediator
public class ChatMediatorImpl implements ChatMediator {
    private List users;

    public ChatMediatorImpl(){
        this.users=new ArrayList();
    }

    @Override
    public void addUser(User user){
        this.users.add(user);
    }

    @Override
    public void sendMessage(String msg, User user) {
        for(User u : this.users){
            if(u != user){
                u.receive(msg);
            }
        }
    }
}

객체 간의 상호작용을 효율적으로 관리하는 방법은?

객체 간의 상호작용을 효율적으로 관리하기 위해서는 다음과 같은 방법을 사용할 수 있습니다.

  1. 중개자 패턴 : 객체 간의 상호작용을 중개하는 디자인 패턴입니다. 중개자 패턴은 객체 간 결합도를 낮추고, 객체들 간의 상호작용을 효율적으로 관리할 수 있습니다.
  2. 느슨한 결합(Loose coupling) : 객체들 간의 결합도를 낮추는 것이 좋습니다. 객체 간의 결합도가 높을 경우, 한 객체의 변경이 다른 객체에 영향을 미칠 수 있습니다. 이를 방지하기 위해 객체들 간의 결합도를 낮추는 것이 중요합니다.
  3. 이벤트 기반 프로그래밍(Event-driven programming) : 이벤트 기반 프로그래밍은 객체들 간의 상호작용을 이벤트를 통해 처리합니다. 이벤트 기반 프로그래밍은 객체의 결합도를 낮추며, 객체들 간의 상호작용을 효율적으로 관리할 수 있습니다.

객체 간의 상호작용은 중요한 요소입니다. 객체들은 서로 연결되어 있으며 다른 객체를 참조하여 작업을 수행합니다. 메디에이터 패턴은 객체 간의 상호작용을 관리하고 중개하는 디자인 패턴으로, 객체 간의 결합도를 낮출 수 있습니다. 이 패턴을 사용하면 객체들은 더 유연하고 확장성 있는 디자인을 구현할 수 있습니다.

Reference : Mediator Pattern: 객체 간의 상호작용을 중개하고 관리하기 위한 디자인 패턴

Chain of Responsibility Pattern란?

Chain of Responsibility Pattern은 객체지향 디자인 패턴 중 하나로, 객체 간의 연쇄적인 처리를 위해 사용됩니다. 이 패턴은 하나의 요청에 대해 적합한 객체를 찾을 때까지 객체들의 연쇄를 따라가는 방식으로 처리를 진행합니다. 이를 통해 요청에 대한 처리를 분산시키고, 객체들의 결합도를 낮추는 효과를 가져올 수 있습니다.

객체 간의 연쇄적인 처리를 위한 디자인 패턴

Chain of Responsibility Pattern을 사용하기 위해서는 처리 가능한 객체들을 연쇄적으로 연결하는 구조를 가지고 있어야 합니다. 이 구조는 일반적으로 LinkedList나 Tree 구조를 사용합니다. 각 객체는 자신이 처리할 수 있는 요청인지 판별하는 메소드를 구현하고, 처리할 수 있다면 요청을 처리하고 그렇지 않다면 다음 객체에게 요청을 전달합니다. 이 과정은 연쇄적으로 진행되며, 요청이 처리될 때까지 반복됩니다.

Java 코드 예시를 통해 이 과정을 살펴보겠습니다. 다음은 Chain of Responsibility Pattern을 사용하여 처리 가능한 객체들을 연결하는 예시입니다.

public abstract class Handler {
    protected Handler nextHandler;

    public void setNextHandler(Handler nextHandler) {
        this.nextHandler = nextHandler;
    }

    public abstract void handleRequest(Request request);
}

public class ConcreteHandler1 extends Handler {
    @Override
    public void handleRequest(Request request) {
        if (request.getType() == RequestType.TYPE1) {
            System.out.println("Handled by ConcreteHandler1");
        } else if (nextHandler != null) {
            nextHandler.handleRequest(request);
        }
    }
}

public class ConcreteHandler2 extends Handler {
    @Override
    public void handleRequest(Request request) {
        if (request.getType() == RequestType.TYPE2) {
            System.out.println("Handled by ConcreteHandler2");
        } else if (nextHandler != null) {
            nextHandler.handleRequest(request);
        }
    }
}

public class Request {
    private RequestType type;

    public Request(RequestType type) {
        this.type = type;
    }

    public RequestType getType() {
        return type;
    }
}

public enum RequestType {
    TYPE1, TYPE2
}

public class Client {
    public static void main(String[] args) {
        Handler handler1 = new ConcreteHandler1();
        Handler handler2 = new ConcreteHandler2();

        handler1.setNextHandler(handler2);

        Request request1 = new Request(RequestType.TYPE1);
        handler1.handleRequest(request1);

        Request request2 = new Request(RequestType.TYPE2);
        handler1.handleRequest(request2);
    }
}

위 예시에서 Handler는 추상 클래스로 구현되며, 다음 Handler를 가리키는 nextHandler 변수와 요청을 처리하는 handleRequest 메소드를 가지고 있습니다. ConcreteHandler1과 2는 이 Handler를 상속받아 각각 다른 요청에 대한 처리를 구현하고 있습니다. 마지막으로 Client 클래스에서는 Handler들을 연결하고 요청 객체를 생성하여 처리를 진행합니다.

Chain of Responsibility Pattern은 객체 간의 연쇄적인 처리를 위한 유용한 디자인 패턴입니다. 이를 사용하면 객체들의 결합도를 낮추고, 요청에 대한 처리를 분산시킬 수 있습니다. Java 코드 예시를 통해 이 과정을 살펴보았는데, 이를 참고하여 실제 코드에서 이 패턴을 사용해보면 좋을 것입니다.

Reference : Chain of Responsibility Pattern: 객체 간의 연쇄적인 처리를 위한 디자인 패턴

Adapter 패턴은 객체들 간의 인터페이스 차이를 극복하기 위한 디자인 패턴입니다. 이 패턴은 호환성 없는 객체를 함께 사용해야 할 때 유용합니다. Adapter 패턴은 객체의 인터페이스를 변경하여 다른 객체와의 호환성을 보장합니다. 또한 코드의 재사용성과 유지 보수성을 향상시킵니다. 이번 글에서는 Adapter 패턴에 대해 자세히 알아보겠습니다.

Adapter 패턴이란?

Adapter 패턴은 객체 간의 인터페이스 차이를 극복하기 위한 디자인 패턴입니다. 이 패턴은 호환성 없는 객체를 함께 사용해야 할 때 유용합니다. Adapter 패턴은 클라이언트에서 사용하는 인터페이스를 호환성 없는 객체의 인터페이스로 변환합니다. 이렇게 변환된 인터페이스는 호환성 있는 다른 객체와 함께 사용할 수 있습니다.

호환성 없는 객체들 간의 인터페이스 차이

호환성 없는 객체들 간에는 인터페이스 차이가 존재합니다. 예를 들어, 한 객체는 삼성 전자 제품의 리모컨 인터페이스를 사용하고, 다른 객체는 LG 전자 제품의 리모컨 인터페이스를 사용할 수 있습니다. 이러한 상황에서 Adapter 패턴은 호환성 없는 객체 간의 인터페이스 차이를 극복합니다.

Adapter 패턴의 작동 방식

Adapter 패턴의 작동 방식은 다음과 같습니다. 먼저, 호환성 없는 객체의 인터페이스와 호환성 있는 인터페이스를 정의합니다. 그리고 호환성 없는 객체를 감싸는 Adapter 클래스를 작성합니다. Adapter 클래스는 호환성 없는 객체의 인터페이스를 호환성 있는 인터페이스로 변환합니다. 마지막으로, 클라이언트는 호환성 있는 인터페이스를 사용하여 Adapter 클래스와 호환성 있는 객체를 사용합니다.

public interface SamsungRemote {
    void powerOn();
    void powerOff();
    void channelUp();
    void channelDown();
}

public interface LGRemote {
    void turnOn();
    void turnOff();
    void up();
    void down();
}

public class LGRemoteAdapter implements SamsungRemote {
    private LGRemote lgRemote;

    public LGRemoteAdapter(LGRemote lgRemote) {
        this.lgRemote = lgRemote;
    }

    public void powerOn() {
        lgRemote.turnOn();
    }

    public void powerOff() {
        lgRemote.turnOff();
    }

    public void channelUp() {
        lgRemote.up();
    }

    public void channelDown() {
        lgRemote.down();
    }
}

위의 코드에서 LGRemoteAdapter 클래스는 호환성 없는 LGRemote 객체의 인터페이스를 호환성 있는 SamsungRemote 인터페이스로 변환합니다.

Adapter 패턴의 사용 예시

Adapter 패턴은 다양한 상황에서 사용될 수 있습니다. 예를 들어, 호환성 없는 라이브러리를 사용해야 할 때 Adapter 패턴을 사용할 수 있습니다. 또한, 코드의 유지 보수성을 향상시키기 위해 Adapter 패턴을 사용할 수도 있습니다.

OUTRO:

이번 글에서는 Adapter 패턴에 대해 알아보았습니다. Adapter 패턴은 호환성 없는 객체 간의 인터페이스 차이를 극복하여 객체들을 함께 사용할 수 있도록 합니다. 이 패턴은 코드의 재사용성과 유지 보수성을 향상시키는데 큰 역할을 합니다. Adapter 패턴은 다양한 상황에서 사용될 수 있으며, 이를 통해 코드의 유연성과 확장성을 높일 수 있습니다.

Reference : Adapter Pattern: 호환성 없는 객체들 간의 인터페이스 차이를 극복하기 위한 디자인 패턴

+ Recent posts