在观察者模式中拥有多个观察者列表的最佳方式
The best way to have multiple observer lists in observer pattern
我正在使用观察者模式编写一个简单的群聊程序。
第 1 组:A、B 和 C 第 2 组:A 和 C
A 是一个 sender/subject,有两个列表,一个用于 Group1,一个用于 Group2。
在主题 class 中有两个列表是执行此操作的好方法吗?
这是否违反了观察者模式的特性?
一个发送者可以有两组观察者。
public class Sender {
private List<Receiver> group1 = new ArrayList<Receiver>();
private List<Receiver> group2 = new ArrayList<Receiver>();
private String msg;
private String name;
public Sender(String name) {
this.name = name;
}
public void sendMsg(int group, String msg, JTextArea display) {
this.msg = msg;
String output = name + ": " + msg;
display.append(output + "\n\r");
if(group == 1) {
notifyAllObservers(group1);
} else {
notifyAllObservers(group2);
}
}
public void register(int group, Receiver receiver) {
if(group == 1) {
group1.add(receiver);
} else {
group2.add(receiver);
}
}
public void notifyAllObservers(List<Receiver> group) {
for (Receiver receiver : group) {
receiver.update(msg);
}
}
public String toString() {
return name;
}
}
public class Receiver {
public Sender sender;
private JTextArea display;
public Receiver(int group, Sender sender, JTextArea display) {
this.sender = sender;
this.display = display;
this.sender.register(group, this);
}
public void update(String msg) {
display.append(sender.toString() + ": " + msg + "\n\r");
}
}
你目前的设计不一定与观察者模式相矛盾,但它是死板的。截至目前,每个 Sender
最多可以分为两组。如果每个发件人应该在最多 10 个组中怎么办? 100组?为了保持这种设计的灵活性,我建议也将 Group
建模为对象。这个想法是每个 Group
同时是一个 Observable
和一个 Observer
。每个 Group
都有一个 List<Sender> senders
,它会自动注册为 Observer
。如果 Group
从它注册的 Observable
之一收到一些 Event
,它将把这个事件转发给它的 Observers
。以下代码是我的提案的粗略草图。
public interface Observer {
public void receiveEvent(Observable source, Event event);
}
public interface Observable {
public void addObserver(Observer observer);
public void removeObserver(Observer observer);
public Collection<Observer> getObservers();
default public void notifyAllObservers(Event event) {
for (Observer observer : this.getObservers()) {
observer.receiveEvent(this, event);
}
}
}
public interface Event { }
public abstract class AbstractObservableImpl implements Observable {
private Set<Observer> observers = new HashSet<>();
@Override
public final void addObserver(final Observer observer) {
this.observers.add(observer);
}
@Override
public final void removeObserver(final Observer observer) {
this.observers.remove(observer);
}
@Override
public final Collection<Observer> getObservers() {
return Collections.unmodifiableCollection(this.observers);
}
}
public class Sender extends AbstractObservableImpl { }
public class Group extends AbstractObservableImpl implements Observer {
private List<Sender> senders = new ArrayList<>();
@Override
public final void receiveEvent(final Observable source, final Event event) {
for (Observer observer : this.getObservers()) {
observer.receiveEvent(this, event);
}
}
public final void addSender(Sender sender) {
if (this.senders.contains(sender) == false) {
this.senders.add(sender);
}
this.senders.get(this.senders.indexOf(sender)).addObserver(this);
}
public final void removeSender(Sender sender) {
final int index = this.senders.indexOf(sender));
if (index >= 0) {
this.senders.get(index).removeObserver(this);
}
this.senders.remove(sender);
}
}
关于设计的一些说明:
-
abstract class AbstractObserverImpl
不是必需的。我只是懒得重复代码,因为 Sender
和 Group
不继承任何其他东西,我让它们继承自 AbstractObserverImpl
.
-
AbstractObserverImpl
是 abstract
也不是必须的。对我来说,允许实例化这个 class 是没有意义的,因为它缺少它的实际功能(触发 Event
的部分)。
- 我选择创建一个空的
Event
界面。这也是武断的。是否将 Object
用作事件、枚举、接口、class 或其他方法,完全取决于您。正如我所说:这只是一个粗略的草图。
- 草图
null
不安全。有相当多的可能性导致 NullPointerException
s.
我正在使用观察者模式编写一个简单的群聊程序。
第 1 组:A、B 和 C 第 2 组:A 和 C
A 是一个 sender/subject,有两个列表,一个用于 Group1,一个用于 Group2。
在主题 class 中有两个列表是执行此操作的好方法吗?
这是否违反了观察者模式的特性?
一个发送者可以有两组观察者。
public class Sender {
private List<Receiver> group1 = new ArrayList<Receiver>();
private List<Receiver> group2 = new ArrayList<Receiver>();
private String msg;
private String name;
public Sender(String name) {
this.name = name;
}
public void sendMsg(int group, String msg, JTextArea display) {
this.msg = msg;
String output = name + ": " + msg;
display.append(output + "\n\r");
if(group == 1) {
notifyAllObservers(group1);
} else {
notifyAllObservers(group2);
}
}
public void register(int group, Receiver receiver) {
if(group == 1) {
group1.add(receiver);
} else {
group2.add(receiver);
}
}
public void notifyAllObservers(List<Receiver> group) {
for (Receiver receiver : group) {
receiver.update(msg);
}
}
public String toString() {
return name;
}
}
public class Receiver {
public Sender sender;
private JTextArea display;
public Receiver(int group, Sender sender, JTextArea display) {
this.sender = sender;
this.display = display;
this.sender.register(group, this);
}
public void update(String msg) {
display.append(sender.toString() + ": " + msg + "\n\r");
}
}
你目前的设计不一定与观察者模式相矛盾,但它是死板的。截至目前,每个 Sender
最多可以分为两组。如果每个发件人应该在最多 10 个组中怎么办? 100组?为了保持这种设计的灵活性,我建议也将 Group
建模为对象。这个想法是每个 Group
同时是一个 Observable
和一个 Observer
。每个 Group
都有一个 List<Sender> senders
,它会自动注册为 Observer
。如果 Group
从它注册的 Observable
之一收到一些 Event
,它将把这个事件转发给它的 Observers
。以下代码是我的提案的粗略草图。
public interface Observer {
public void receiveEvent(Observable source, Event event);
}
public interface Observable {
public void addObserver(Observer observer);
public void removeObserver(Observer observer);
public Collection<Observer> getObservers();
default public void notifyAllObservers(Event event) {
for (Observer observer : this.getObservers()) {
observer.receiveEvent(this, event);
}
}
}
public interface Event { }
public abstract class AbstractObservableImpl implements Observable {
private Set<Observer> observers = new HashSet<>();
@Override
public final void addObserver(final Observer observer) {
this.observers.add(observer);
}
@Override
public final void removeObserver(final Observer observer) {
this.observers.remove(observer);
}
@Override
public final Collection<Observer> getObservers() {
return Collections.unmodifiableCollection(this.observers);
}
}
public class Sender extends AbstractObservableImpl { }
public class Group extends AbstractObservableImpl implements Observer {
private List<Sender> senders = new ArrayList<>();
@Override
public final void receiveEvent(final Observable source, final Event event) {
for (Observer observer : this.getObservers()) {
observer.receiveEvent(this, event);
}
}
public final void addSender(Sender sender) {
if (this.senders.contains(sender) == false) {
this.senders.add(sender);
}
this.senders.get(this.senders.indexOf(sender)).addObserver(this);
}
public final void removeSender(Sender sender) {
final int index = this.senders.indexOf(sender));
if (index >= 0) {
this.senders.get(index).removeObserver(this);
}
this.senders.remove(sender);
}
}
关于设计的一些说明:
-
abstract class AbstractObserverImpl
不是必需的。我只是懒得重复代码,因为Sender
和Group
不继承任何其他东西,我让它们继承自AbstractObserverImpl
. -
AbstractObserverImpl
是abstract
也不是必须的。对我来说,允许实例化这个 class 是没有意义的,因为它缺少它的实际功能(触发Event
的部分)。 - 我选择创建一个空的
Event
界面。这也是武断的。是否将Object
用作事件、枚举、接口、class 或其他方法,完全取决于您。正如我所说:这只是一个粗略的草图。 - 草图
null
不安全。有相当多的可能性导致NullPointerException
s.