Observer Pattern

2020. 5. 2. 17:14디자인 패턴

1. Observer Pattern

 Observer Pattern이란 한 객체의 상태 변화에 따라 다른 객체의 상태도 연동되도록 일대다 객체 의존 관계를 구성하는 패턴입니다. 데이터의 변경이 발생했을 경우, 상대 클래스나 객체에 의존하지 않으면서 데이터 변경을 통보하고자 할 때 유용합니다.


 위의 이미지를 보면 Subject 인터페이스의 구현체의 상태에 변화가 있을 때, Observer 들에게 notify를 통해 상태 변화를 알려주는 것을 의미합니다.

2. ObserverPattern의 예시

 예를 들어, 어떤 유저와 채팅 방이 있다고 가정하겠습니다. 유저는 채팅방에 말할 수 있고, 채팅을 받을 수 있습니다. 그리고 유저는 채팅방, 게임방에 임장을 해 각 채팅방에 메시지를 전달하는 상황입니다.

유저

public class User {
    private List<Room> room;

    public void setRoom(List<Room> room){
        this.room = room;
    }

    public void talk(String msg){
        for(Room r:room){
            r.receive(msg);
        }
    }
}

채팅방

public class ChatRoom {
    public String roomName;

    public ChatRoom(String roomName){
        this.roomName = roomName;
    }
}

게임방

public class GameRoom {
    public String roomName;

    public GameRoom(String roomName){
        this.roomName = roomName;
    }
}

클라이언트

public class Client {
    public static void main(String args[]){
        User user = new User();
        List<Room> rooms = new ArrayList<Room>();
        rooms.add(new ChatRoom("채팅방"));
        rooms.add(new GameRoom("게임방"));
        rooms.add(new DevRoom("개발방"));

        user.setRoom(rooms);

        String msg = "안녕하세요~";
        user.talk(msg);

    }
}

 이렇게 구현된 Client 클래스의 코드를 보면, User와 Room은 매우 강하게 연결되어 있습니다. 이런 상황에서 다른 방이 생성되거나, 특정 방이 제거되어 메시지를 보내야 한다면 어떻게 해야 할까요? List이기 때문에 추가 제거가 가능하지만, Observer Pattern을 이용하면 더 객체지향적으로 구현이 가능해집니다.

옵저버

public class Observer {
    public String roomName;

    public void receive(String msg){
        System.out.println(this.roomName + "에서 메시지를 받음 : " + msg);
    }
}

채팅방

public class ChatRoom extends Observer{
    public ChatRoom(String roomName){
        this.roomName = roomName;
    }
}

게임방

public class GameRoom extends Observer{
    public GameRoom(String roomName) {
        this.roomName = roomName;
    }
}

서브젝트(Observer를 관리하는 클래스)

public class Subject {
    private List<Observer> observers = new ArrayList<Observer>();

    // 옵저버에 추가
    public void attach(Observer observer){
        observers.add(observer);
    }

    // 옵저버에서 제거
    public void detach(Observer observer){
        observers.remove(observer);
    }

    // 옵저버들에게 알림
    public void notifyObservers(String msg){
        for (Observer o:observers) {
            o.receive(msg);
        }
    }
}

유저

public class User extends Subject{

}

클라이언트

public class Client {
    public static void main(String args[]){
        User user = new User();
        ChatRoom chatRoom = new ChatRoom("채팅방");
        GameRoom gameRoom = new GameRoom("게임방");
        DevRoom devRoom = new DevRoom("개발방");
        user.attach(chatRoom);
        user.attach(gameRoom);
        user.attach(devRoom);

        String msg = "안녕하세요~";
        user.notifyObservers(msg);

        user.detach(chatRoom);
        msg = "Hi~";
        user.notifyObservers(msg);
    }
}
728x90

'디자인 패턴' 카테고리의 다른 글

Factory Pattern  (0) 2020.05.06
Chain Of Responsibility  (0) 2020.05.02
Template Method Pattern  (0) 2020.05.01
Singleton Pattern  (0) 2020.04.27
Facade Pattern  (0) 2020.04.03