Observer pattern!

Posted on December 28, 2006

1


Theo định nghĩa trong sách của GOF, Observer pattern: định nghĩa mối quan hệ một nhiều giữa các đối tượng như vậy khi một đối tượng thay đổi trạng thái tất cả các đối tượng phụ thuộc vào nó sẽ được thông báo và cập nhật tự động.

class_diagram__com__cuonglm__example__design__observer__observer_class_diagram.jpg

Cách hoạt động:

  • Đầu tiên Observer1 sẽ đăng ký với Subject, Subject lưu l;ại trạng thông tin về observer đã đăng ký, sau đó observer cũng có thể đăng ký với subject.

  • Khi trạng thái của Subject bị thay đổi, nó sẽ thông báo với tất cả cacs observer đã đăng ký với nó.

  • Observer 1 nếu không muốn có thể bỏ đăng ký bất cứ lúc nàom khi đó khi trạng thái Subject thay đổi, Observer 1 sẽ không nhận được thông báo về sự thay đổi đó nữa.

  • Observer 3 có thể đăng ký với Subject lúc nào nó muốn.

Thực hiện:

Viết code của 2 Interface là Subject và Observer:

public interface Observer {

void update();

}

public interface Subject {

/**

* @param observer

*/

void registerObserver(Observer observer);

/**

* @param observer

*/

void removeObserver(Observer observer);

void notifyObserver();

}

Tiếp theo ta sẽ tạo ra một lớp cụ thể là ConcreteSubject thi hành Interface Subject.

public class ConcreteSubject implements Subject {

private ArrayList<Observer> observers;

private int state = 1;

public ConcreteSubject() {

observers = new ArrayList<Observer>();

}

public void notifyObserver() {

System.out.println(“subject change state to: “ + state);

for (Observer observer : observers) {

observer.update();

}

}

/**

* @param observer

*/

public void registerObserver(Observer observer) {

observers.add(observer);

}

/**

* @param observer

*/

public void removeObserver(Observer observer) {

observers.remove(observer);

}

public int getState() {

return state;

}

public void setState(int state) {

this.state = state;

notifyObserver();

}

}

Ở đây ta thấy ConcreteSubject chứa một danh sách các đối tượng Observer trong nó, khi một đối tượng Observer muốn đăng ký sẽ phải gọi phương thức registerObserver(Observer observer). Thông tin về Observer đăng ký được đưa vào danh sách của ConcreteSubject. Khi một đối tượng không muốn đăng nữa sẽ phỉa gọi phươnt thức removeObserver(Observer observer) và được đưa ra khỏi danh sách của ConcreteSubject.

Trong bản thân ConcreteSubject, khi trạng thái của nó bị thay đổi nó sẽ phải gọi đến phương thức notifyObserver() để thông báo cho toàn bộ các Observer trong danh sách mà nó lưu trữ.

Chúng ta viết thêm 3 đối tượng Observer cụ thể cho ví dụ:

public class ConcreteObserver1 implements Observer {

public void update() {

System.out.println(this+” updated”);

}

/**

* @return

*/

@Override

public String toString() {

return “Observer1”;

}

}

public class ConcreteObserver2 implements Observer {

public void update() {

System.out.println(this+” updated”);

}

/**

* @return

*/

@Override

public String toString() {

return “Observer2”;

}

}

public class ConcreteObserver3 implements Observer {

public void update() {

System.out.println(this+” updated”);

}

/**

* @return

*/

@Override

public String toString() {

return “Observer3”;

}

}

Sau khi hoàn thành Observer pattern chúng ta sẽ viết một lớp dùng để test:

public class Main {

/**

* @param args

*/

public static void main(String[] args) {

Subject subject=new ConcreteSubject();

Observer observer;

observer=new ConcreteObserver1();

subject.registerObserver(observer);

observer=new ConcreteObserver2();

subject.registerObserver(observer);

((ConcreteSubject)subject).setState(5);

observer=new ConcreteObserver3();

subject.registerObserver(observer);

((ConcreteSubject)subject).setState(7);

}

}

Kết quả:

subject change state to: 5

Observer1 updated

Observer2 updated

subject change state to: 7

Observer1 updated

Observer2 updated

Observer3 updated

Sức mạnh của sự liên kết yếu

  • Khi hai đối tượng liên kết với nhau một cách lỏng lẻo, chúng có thể giao tiếp với nhau mà không cần hiểu rõ về đối tượng kia.

  • Observer Pattern cung cấp cho chúng ta cách thiết kế các đối tượng mà đối tượng chủ (subject) và các đối tượng quan sát (observers) liên kết yếu với nhau.

  • Điều duy nhất mà đối tượng chủ cần biết về các đối tượng qua sát là interface mà các đối tượng quan sát thi hành (Observer interface), chúng không cần biết lớp thi hành cụ thể của đối tượng quan sát, không cần biết đối tượng quan sát là cái gì và làm cái gì.

  • Chúng ta có thể thêm đối tượng quan sát bất cứ lúc nào. Bởi vì điều duy nhất mà đối tượng chủ phụ thuộc vào là danh sách các đối tượng thi hành Observer interface, chúng ta có thể thêm đối tượng quan sát bất cứ lúc nào ta muốn. Như vậy ta có thể thay thế một đối tượng quan sát bằng một đối tượng quan sát khác trong lúc thực thi hoặc xoá bỏ một đối tượng quan sát nếu ta muốn.

  • Chúng ta không cần phải thay đổi đối tượng chủ để thêm vào một loại đối tượng quan sát mới. Nếu một lớp cụ thể muốn trở thành đối tượng quan sát, nó sẽ thi hành Observer interface và đăng ký nó với đối tượng chủ. Đối tượng chủ không cần phải thay đổi gì để một lớp khác trở thành đối tượng quan sát.

  • Chúng ta có thể sử dụng lại đối tượng chủ hoặc đối tượng quan sát một cách độc lập không phụ thuộc lẫn nhau. Chúng ta có thể tạo thêm đối tượng chủ cho phép các đối tượng quan sát thi hành Observer interface đăng ký với đối tượng chủ đó,

  • Chúng ta có thể thay đổi đối tượng chủ hoặc đối tượng quan sát mà không làm ảnh hưởng đến mối quan hệ giữa đối tượng chủ và đối tượng quan sát, chỉ cần các đối tượng quan sát vẫn thi hành Observer pattern.