[英]Observer pattern infinite loop
我有一個觀察員也要成為主題的情況。 因此,讓我們與具有兩個實體A和B的圖像進行比較。當在A的模型中發生更改時,其他實體應該知道包括B(C,D ... Etc)。
當B的模型發生更改時,其他實體也應該知道,包括A(C,D ... Etc)。
通過以這種方式實現觀察者模式,我得到了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);
}
}
}
B模型
導入java.util.ArrayList; 導入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();
}
}
之所以會出現無限循環,是因為每次更新Observable時,都會通知其觀察者,但是此通知過程隨后會再次更新模型,因此它會重復。
這是一個如何以尋找方式使用觀察者模式的示例:
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
盡管@arizzle的答案有效,但我認為您正在濫用Observer模式。
觀察者
在對象之間定義一對多依賴關系,以便當一個對象更改>狀態時,將自動通知和更新其所有依賴關系。
您的問題似乎更像是多對多關系。 在這種情況下,我建議您使用Mediator Pattern隱藏這種復雜性。
這是此模式的經典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"
這樣,當您廣播一條消息時,您可以確定每個人都收到了該消息,因此您無需為每個同事進行另一次廣播來傳達新狀態。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.