기타/디자인패턴

행위패턴 > 옵저버 *

ssseung 2021. 2. 12. 15:39

 

객체의 상태변화에 따라 다른 객체의 상태도 연동되도록 일대다 객체 의존 관계를 구성

데이터 변경이 발생했을 경우 상대 클래스나 객체에 의존하지 않으면서 데이터 변경을 통보하고자 할 때 유용

 

주황색 라인은 서로 호출하는 모양

Subject 와 Observer 는 서로를 변수로 가지고 있는다. 

Observer 는 생성자에서 받은 subject 를 registerObserver(this)로 등록해두고, 

Subject 에서는 자신에게 변화가 있을 때 Observer notify 를 호출한다.

push방식,  poll 방식으로 구현할 수 있다. 

 

Product 에 상태에 변화가 생기면 Observer 에서 이를 감지하고 ProductDisplay 에게 알려준다.

 

public class ObTest {

    public static void main(String[] args) {        
        // 하나의 product 와 하나의 observer 를 가지는 경우
        Product pd = new Product("productA", 300);
        Observer pob = new ProductObserver(pd);
        pd.stock(100);
        pd.release(200);
                
        // 여러개의 observer 에 하나의 product 를 등록
        Observer pob2 = new ProductObserver(pd);
        pd.release(50);
                
        //product 여러개가 있는 list 를 observer 에 등록
        Products list = new Products();
        Observer  listObserver=  new ProductObserver(list);
        list.add(pd);
    }
    
    
}

 

public interface Subject {
    public void registerObserver(Observer productObserver);
    public void removeObserver(Observer ob);
    public void notifyObserver();
}
public class Product implements Subject {
    String name;
    int quantity;
    List<Observer> observers;
    
    public Product(String name, int quantity) {
        this.name = name;
        this.quantity = quantity;
        observers = new ArrayList<Observer>();
    }
 
    @Override
    public void registerObserver(Observer ob) {
        observers.add(ob);
        notifyObserver();
    }


    @Override
    public void removeObserver(Observer ob) {
        observers.remove(ob);
    }

    @Override
    public void notifyObserver() {
        for(Observer ob: observers) {
            ob.getData();
        }
    }
    
    public void stock(int quantity) {
        this.quantity += quantity;
        notifyObserver();
    }
    

    public void release(int quantity) {
        if(this.quantity >= quantity) {
            this.quantity -= quantity;
        } 
        notifyObserver();
    }
    
    @Override
    public boolean equals(Object obj) {
        // TODO Auto-generated method stub
        return super.equals(obj);
    }
    
    @Override
    public String toString() {
        return "Product [ name= " + this.name + ", quantity= " + this.quantity + " ]";
    }
    
}
public interface Observer {
    public void getData();
    public void updateData(Subject subject);
}
public class ProductObserver implements Observer{
    private Subject subject;
    private ProductDisplay display;
    public ProductObserver(Subject subject) {
        this.subject = subject;
        this.display = new ProductDisplay(subject);
        this.subject.registerObserver(this);
       
    }
    
    @Override
    public void getData() {
        display();
    }
    
    @Override
    public void updateData(Subject subject) {
        this.subject = subject;
        display();
    }

    private void display() {
        
       System.out.println("ProductObserver display = " + "this=" + this.toString() 
           + ", subject= " + this.subject);
       this.display.display();
    }
    
}
public class ProductDisplay {
        
    Subject product ;
    public ProductDisplay(Subject product ) {
        this.product = product;
    }
    public void display() {
        System.out.println("ProductDisplay = [ " + product + " ]");
    }

}

 

headFirst Design Patterns 참조

반응형