松散耦合的观察者模式

时间:2013-05-11 14:47:01

标签: java model-view-controller observer-pattern loose-coupling

我意识到这个问题已经被解决了,但我仍在努力,可以提供一些具体的帮助。

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

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

我曾尝试使用Java内置的Observer / Observable类,但已经意识到Observers update()方法有多糟糕 - 它接收到POJO,我需要在update()方法中检查/转换该POJO。我更倾向于让我的'update()'方法获得它可以期待的东西。

所以,我遵循了一些教程,包括以狗/所有者为例的教程:

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()方法,我有处理特定事件的方法。辉煌。我目前对所有者/视图类感到满意。它知道狗/模型的方法,这很好(我认为)。

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

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

由于

2 个答案:

答案 0 :(得分:4)

interfaceObserver

应该{​​{1}}了解具体实施情况
Observable

在这种情况下,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的实施情况,只知道OwnerOwner

DogListener另一方面不知道Owner它只知道它有一个传入的Dog

答案 1 :(得分:1)

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

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

这是我所知道的最好的方式来创建一个非常松散的耦合。

相关问题