2009-11-01 40 views

Trả lời

41

tôi khuyên bạn nên tránh sử dụng các lớp Observable hoàn toàn, mà là xác định người nghe sự kiện cụ thể và định nghĩa sự kiện tương ứng. Sau đó, xác định danh sách người nghe trong lớp học của bạn cùng với các phương pháp để thêm và xóa người nghe và truyền bá sự kiện cho họ (xem bên dưới).

Observable buộc bạn sử dụng java.lang.Object để thể hiện sự kiện và sau đó kiểm tra loại sự kiện bằng cách sử dụng instanceof, đây là cách tiếp cận không phải là xấu và làm cho mã khó hiểu hơn. Nếu bạn nhìn vào các lớp trong gói javax.swing, bạn sẽ thấy chúng tránh sử dụng Observer/Observable hoàn toàn và sử dụng cách tiếp cận tương tự như bên dưới.

Event Definition

public class MyChangeEvent extends EventObject { 
    // This event definition is stateless but you could always 
    // add other information here. 
    public MyChangeEvent(Object source) { 
    super(source); 
    } 
} 

Listener Definition

public interface MyChangeListener { 
    public void changeEventReceived(MyChangeEvent evt); 
} 

Lớp Definition

public class MyClass { 
    // Use CopyOnWriteArrayList to avoid ConcurrentModificationExceptions if a 
    // listener attempts to remove itself during event notification. 
    private final CopyOnWriteArrayList<MyChangeListener> listeners; 

    public class MyClass() { 
    this.listeners = new CopyOnWriteArrayList<MyChangeListener>(); 
    } 

    public void addMyChangeListener(MyChangeListener l) { 
    this.listeners.add(l); 
    } 

    public void removeMyChangeListener(MyChangeListener l) { 
    this.listeners.remove(l); 
    } 

    // Event firing method. Called internally by other class methods. 
    protected void fireChangeEvent() { 
    MyChangeEvent evt = new MyChangeEvent(this); 

    for (MyChangeListener l : listeners) { 
     l.changeEventReceived(evt); 
    } 
    } 
} 
+1

java.util.Observable cũng có một lá cờ để cho biết liệu bất cứ điều gì đã thay đổi. Và đôi khi một lớp Sự kiện mới là quá mức cần thiết. – finnw

+2

+1 để sử dụng CopyOnWriteArrayList – finnw

+0

@finnw - Hầu hết các định nghĩa lớp sự kiện của tôi là <10 dòng mã được tạo tự động và mất vài giây để viết. Tuy nhiên, trong các tình huống mà tôi muốn tránh việc định nghĩa các lớp sự kiện mới, tôi ưu tiên PropertyChangeEvent/PropertyChangeListener/PropertyChangeSupport, ít nhất bạn có thể kiểm tra tên thuộc tính trước khi thử bất kỳ phôi nào. – Adamski

0

Nhiều kế thừa (để mở rộng hai lớp) là không thể trong Java. Được coi là một thiết kế tồi tệ trong hầu hết các trường hợp.

Nếu bạn cung cấp thêm thông tin cho chúng tôi, có thể ai đó có thể giúp bạn nhiều hơn một chút.

1

Java không cho phép đa thừa kế, vì vậy không có cách nào trực tiếp để thực hiện. Bạn nên xem xét sử dụng một mô hình đại biểu có đối tượng chính của bạn mà các đại biểu hành vi quan sát của ông đến một đối tượng khác ..

class YourObject extends ItsAncestorClass 
{ 
     private Observer includedObserver; 

     public Observer getHisObserver(..) 
} 

cách tiếp cận sẽ được quay theo đối tượng mà từ đó lớp học của bạn được kéo dài đến một giao diện, sau đó bạn sẽ được phép mở rộng từ Observer.

+0

@finnw - và Jack không bao giờ nói bất cứ điều gì về Observer không phải là một lớp trừu tượng. – weiji

-6

Sử dụng cầu.

Tạo lớp mở rộng Có thể quan sát thấy rằng lớp đầu tiên chỉ gọi các phương thức của lớp thứ hai.

Cầu phương pháp chi tiết:

public class XXX { 
    public class XXXObservableBridge : Observable { 
     public void RaiseEvent(); 
     // Listeners etc 
    } 

    private XXXObservableBridge ObservableBridge; 

    XXX() { 
     ObservableBridge = new ObservableBridge; 
    } 

    public Observable AsObservable() { return ObservableBidge; } 

    public void RaiseEvent() { ObservableBridge.RaiseEvent(); } 
} 
+3

-1 đây là một câu hỏi Java, không phải C#. Vui lòng tuân theo cú pháp Java và API – finnw

+0

@finnw C# không cần mẫu quan sát/quan sát và mã của tôi thậm chí không gọi bất kỳ chức năng API nào. – Joshua

+1

Không có một IObservable trong Java, và ngay cả khi bạn đã xác định một, java.util.Observable không thực hiện nó. –

1

Một tùy chọn là để bọc đối tượng của bạn trong một đối tượng Observable.

public class MyObjectObservableWrapper implements Observable { 
    private MyObject myObject; 
    public MyObjectObservaleWrapper(MyObject myObject){ 
    this.myObject = myObject; 
    } 
    // interface methods here 
} 

Tùy chọn này hoạt động khi dữ liệu được phương pháp có thể quan sát được sử dụng thông qua các phương pháp công khai của MyObject. Vì vậy, nó có thể không phù hợp cho tất cả các trường hợp.

0

Bạn có thể mở rộng Quan sát và quấn phụ huynh gốc trong lớp con bạn có thể quan sát được.Ủy quyền tất cả các cuộc gọi phương thức cho đối tượng được bao bọc.

Các vấn đề liên quan