观察者模式无限循环

时间:2016-06-03 14:47:12

标签: java design-patterns infinite-loop observer-pattern

我有一个情况,我有一个Observer也是一个主题。 因此,让我们的图像有两个参与A和B. 当A模型发生变化时,其他人应该知道包括B(C,D ......等)。

当B&#39的模型发生变化时,其他人应该知道包括A(C,D ......等)。

通过以这种方式实现Observer模式,我得到A和B之间的无限循环。

观察者是否没有正确地执行或者我是否需要另一个人来处理这种设计?

她的实施方式

public interface ISubject {
    public void registreObserver(IObserver obs);

    public void removeObserver(IObserver obs);

    public void notifyObservers();
}

观察者界面

public interface IObserver {
    public void update(ISubject subject);
}

模特

import java.util.ArrayList;
import java.util.List;


public class AModel implements ISubject {

    private List<IObserver> listObservers = new ArrayList<>();
    @Override
    public void registreObserver(IObserver obs) {
        listObservers.add(obs);
    }

    @Override
    public void removeObserver(IObserver obs) {
        listObservers.remove(obs);
    }

    public void loadData(){
        notifyObservers();
    }

    @Override
    public void notifyObservers() {
        for (IObserver obv : listObservers) {
            obv.update(AModel.this);
        }
    }
}

BModel

import java.util.ArrayList;     import java.util.List;

public class BModel implements ISubject {

    private List<IObserver> listObservers = new ArrayList<>();
    @Override
    public void registreObserver(IObserver obs) {
        listObservers.add(obs);
    }

    @Override
    public void removeObserver(IObserver obs) {
        listObservers.remove(obs);
    }

     public void loadData(){
        notifyObservers();
    }


    @Override
    public void notifyObservers() {
        for (IObserver obv : listObservers) {
            obv.update(BModel.this);
        }
    }
}

A控制器

public class AController implements IObserver {

private AModel model;

public void setModel(AModel model) {
    this.model = model;
}

    @Override
    public void update(ISubject subject) {
        System.out.println(" A Changed");
       model.loadData();
    }
}

B控制器

public class BController implements IObserver {

private BModel model;

public void setModel(BModel model) {
    this.model = model;
}
    @Override
    public void update(ISubject subject) {
        System.out.println(" B Changed");
model.loadData();
    }
}

主程序

public class Main {

    public static void main(String[] args) {
        AModel aModel = new AModel();
        AModel bModel = new BModel();

        AController aController = new AController();
        aController.setModel(aModel);

        AController bController = new BController();
        bController.setModel(bModel);

        aModel.registreObserver(bController);
        bModel.registreObserver(aController);

        // Here the updates starts a notify b and b notify a and so on 
        aModel.notifyObservers();

    }
}

2 个答案:

答案 0 :(得分:1)

您获得无限循环的原因是因为每次更新Observable时,都会通知其观察者,但此通知过程会再次更新模型,因此会重复。

以下是一个如何以您正在寻找的方式使用Observer模式的示例:

import java.util.Observable;
import java.util.Observer;

public class Example {

    public static void main(String[] args) {

        Model modelA = new Model();
        Model modelB = new Model();

        Observer aController = (observable, arg) -> {
            System.out.println("A controller: " + arg);
        };

        Observer bController = (observable, arg) -> {
            System.out.println("B controller: " + arg);
        };

        modelA.addObserver(bController);
        modelB.addObserver(aController);

        modelA.update("test");
        modelB.update("test2");
    }
}

class Model extends Observable {

    private String data;

    public void update(String data) {
        this.data = data;
        setChanged();
        notifyObservers(data);
    }
}

输出:

B控制器:测试

控制器:test2

答案 1 :(得分:0)

虽然@ arizzle的回答有效,但我认为你滥用了Observer模式。

  

观察

     

定义对象之间的一对多依赖关系,以便当一个对象发生更改时>州,其所有家属都会自动得到通知和更新。

Source

您的问题似乎更像是多对多的关系。在这种情况下,我建议您使用Mediator Pattern来隐藏这种复杂性。

这是这种模式的标准UML图:

Mediator UML

我将跳过界面/抽象类定义,以避免让答案膨胀。

基本实施:

class Mediator {
    private Map<String, Colleague> participants = new HashMap<String, Colleague>();
    public void register(Colleague c) {
        participants.put(c.getName(), c);
        c.setMediator(this);
    }

    public void send(Colleague from, String message, String to) {
        Colleague c = participants.get(to);
        if (c != null && c != from) {
            c.receive(message, from);
        }
    }

    public void send(Colleague from, String message) {
        for (Map.Entry<String, Colleague> e: participants.entrySet()) {}
            Colleague c = e.getValue();
            if (c != from)) {
                c.receive(message, from);
            }
        }
    }
}

abstract class Colleague {
    private Mediator mediator;
    private String name;

    public Colleague(String name) {
        this.name = name;
    }

    public void setMediator(Mediator mediator) {
        this.mediator = mediator;
    }

    public void send(String msg, String to) {
        this.mediator.send(this, msg, to);
    }

    public void send(String msg) {
        this.mediator.send(this, msg);
    }

    abstract public void receive(String msg, Colleague from);
}

class ConcreteColleague1 {
    public void receive(String msg, String from) {
        // do something
        System.out.println("Received msg: " + msg + " from: " + from.getName());
    }
}

class ConcreteColleague2 {
    public void receive(String msg, String from) {
        // do other thing
        System.out.println("Received msg: " + msg + " from: " + from.getName());
    }
}

使用它:

Mediator m = new Mediator();

Colleague c1 = new ConcreteColleague1('foo');
Colleague c2 = new ConcreteColleague2('bar');
Colleague c3 = new ConcreteColleague1('baz');

c1.send("test");
c2.send("test");
c3.send("test");

将打印:

"Received msg: test from: foo"
"Received msg: test from: foo"
"Received msg: test from: bar"
"Received msg: test from: bar"
"Received msg: test from: baz"
"Received msg: test from: baz"

这样,当您播放消息时,您可以确定每个人都收到了消息,因此您不需要为每个同事进行另一次广播来传达新状态。