我使用观察者模式编写一个简单的群聊项目。
组1:A,B和C组2:A和C
A是具有两个列表的发件人/主题,一个用于Group1,另一个用于Group2。
在主题课中有两个列表是一个很好的方法吗?
这是违反观察员模式的功能吗?
发件人可以有两组观察员。
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");
}
}
答案 0 :(得分:1)
您当前的设计不一定与观察者模式相矛盾,但它是僵化的。截至目前,每个Sender
最多可以包含两个组。如果每个发件人最多可以包含10个组,该怎么办? 100组?为了保持这种设计的灵活性,我建议将Group
s建模为对象。我们的想法是每个Group
同时是Observable
和Observer
。每个Group
都有一个List<Sender> senders
,它会自动注册为Observer
。如果Group
从其注册的Event
之一收到一些Observable
,则会将此事件转发给其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
也不是必需的。对我来说,允许实例化这个类是没有意义的,因为它缺少它的实际功能(触发Event
s的部分)。Event
接口。这也是arbirtrary。无论您使用Object
作为事件,还是枚举,界面,类或不同的方法都完全取决于您。正如我所说:这只是一个粗略的草图。null
- 安全。有很多可能导致NullPointerException
s。