5

我意识到这个主题已经被覆盖到死,但我仍然在挣扎,可以通过一些具体的帮助来做。

我的目标是在某种可观察对象(比如说狗)和某种侦听器(比如说所有者)之间实现一个简单的观察者模式。

最终,所有者将成为 MVC 范例中的“视图”,而狗将成为“模型”。我使用 Dog 和 Owner 只是为了尝试简化这里的事情。

我尝试使用 Java 内置的 Observer / Observable 类,但已经意识到 Observers update() 方法有多糟糕 - 它接收一个 POJO,我需要在 update() 方法中检查/强制转换该 POJO。我更希望让我的“update()”方法收到它可以期待的东西。

因此,我遵循了一些教程,包括以 Dog/Owner 为例的教程:

http://www.youtube.com/watch?v=qw0zZAte66A

在这里,我展示了如何滚动我自己的 Observer/Observed 类。在伪代码中,我现在拥有的是:

Dog/Model {

    List listeners;

    public fireDogHungryEvent() {

        foreach listener {
            listener.onDogHungry(this);
        }
    }

    public fireDogPeeEvent() {

        foreach listener {
            listener.onDogNeedsToPee(this);
        }
    }

    public getHungerLevel() { return hungerLevel; }
    public getBladderCapacity() { return bladderCapacity; }
}

Owner/View {

    public onDogHungry(model) {
        println(model.getHungerLevel());
    }

    public onDogNeedsToPee(model) {
        println(model.getBladderCapacity());
    }
}

所以现在我有处理特定事件的方法,而不是一个 update() 方法。杰出的。我目前对 Owner/view 类很满意。它知道 Dog/model 的方法,这很好(我认为)。

我不喜欢的是 Dog/model 引用了 Owner/view 中的方法。我已经阅读了无数次并且完全同意模型不应该与其视图紧密耦合,例如它似乎在上面。我也不热衷于 Dog/model 中的所有“火”方法做几乎相同的事情;循环遍历它的所有侦听器,并在每个侦听器上调用不同的方法。

是否可以进一步解耦这种关系并且不让 Dog/model 调用特定的方法?如果是这样,将狗/模型数据接收到所有者/视图并适当地使用它的最佳方法是什么?

谢谢

4

2 回答 2

4

您应该interface从 theObserver和 theObservable

public enum EventType {

    HUNGRY,
    PEE;
}

public interface DogEvent {

    EventType getType();
}

public interface DogListener {

    void fireEvent(DogEvent event);
}

public class Dog {

    private final Set<DogListener> listeners = new CopyOnWriteArraySet<DogListener>();

    public void register(final DogListener dogListener) {
        listeners.add(dogListener);
    }

    public void unregister(final DogListener dogListener) {
        listeners.remove(dogListener);
    }

    public void firePeeEvent() {
        fireEvent(new DogEvent() {
            @Override
            public EventType getType() {
                return EventType.PEE;
            }
        });
    }

    public void fireHungryEvent() {
        fireEvent(new DogEvent() {
            @Override
            public EventType getType() {
                return EventType.HUNGRY;
            }
        });
    }

    private void fireEvent(final DogEvent dogEvent) {
        for (final DogListener listener : listeners) {
            listener.fireEvent(dogEvent);
        }
    }
}

public class Owner implements DogListener {

    @Override
    public void fireEvent(DogEvent event) {
        switch (event.getType()) {
            case PEE:
                System.out.println("Someone take the dog out");
                break;
            case HUNGRY:
                System.out.println("I can't believe the dog is hungry _again_!");
                break;
        }
    }
}

在这种情况下,Dog不知道Owner它的实现只是知道它Owner是一个DogListener

Owner另一方面,它不知道它只Dog知道它有一个传入DogEvent

于 2013-05-11T15:07:32.620 回答
1

出于 MVC 的目的(特别是对于 MVP),我收集了有关事件基础编程的良好经验。所以你需要一个由 Dog 和 Owner 使用的 EventBus。所有者将订阅某些事件类,例如 HungerLevelIncrease,而狗将触发此类事件。对于您的狗主人示例,这会有点奇怪,因为主人不认识他的狗,但对于 GUI 编程,这是一个很好且简单的解耦解决方案,尤其是在其他控制器之间。

您可以自己轻松创建总线,也可以使用来自google guava的总线。

这是我所知道的创建真正松散耦合的最佳方法。

于 2013-05-11T15:05:06.843 回答