我正在尝试理解观察者模式,这是我在网上选择的一个简单代码:
import java.util.ArrayList;
import java.util.List;
/**
* The observer pattern is a software design pattern in which an object,
* called the subject, maintains a list of its dependents, called observers, and
* notifies them automatically of any state changes, usually by calling one of their methods
* @author X220
*
*/
interface Subject
{
// methods to register and unregister observers
public void register(Observer obj);
public void unregister(Observer obj);
// method to notify observers of change
public void notifyObservers();
// method to get updates from subject
public Object getUpdate(Observer obj);
}
interface Observer
{
// method to update the observer, used by subject
public void update();
// attach with subject to observe
public void setSubject(Subject sub);
}
/**
* Holds a list of the observers
* @author X220
*
*/
class MySubject implements Subject
{
private List<Observer> observers;
private String message;
private boolean changed;
private final Object MUTEX = new Object();
public MySubject()
{
this.observers = new ArrayList<>();
}
@Override
public void register(Observer obj)
{
if (obj == null)
throw new NullPointerException("Null Observer");
synchronized (MUTEX) {
if (!observers.contains(obj))
observers.add(obj);
}
}
@Override
public void unregister(Observer obj)
{
synchronized (MUTEX)
{
observers.remove(obj);
}
}
@Override
public void notifyObservers()
{
List<Observer> observersLocal = null;
// synchronization is used to make sure any observer registered after
// message is received is not notified
synchronized (MUTEX)
{
if (!changed)
{
return;
}
observersLocal = new ArrayList<>(this.observers);
this.changed = false;
}
for (Observer obj : observersLocal)
{
obj.update();
}
}
@Override
public Object getUpdate(Observer obj) {
return this.message;
}
// method to post message to the topic
public void postMessage(String msg) {
System.out.println("Message Posted to Topic:" + msg);
this.message = msg;
this.changed = true;
notifyObservers();
}
}
class MyObserver implements Observer
{
private String name;
private Subject topic;
public MyObserver(String nm) {
this.name = nm;
}
@Override
public void update() {
String msg = (String) topic.getUpdate(this);
if (msg == null) {
System.out.println(name + ":: No new message");
} else
System.out.println(name + ":: Consuming message::" + msg);
}
@Override
public void setSubject(Subject sub) {
this.topic = sub;
}
}
public class RunCode1
{
public static void main1(String[] args) {
// create subject
MySubject topic = new MySubject();
// create observers
Observer obj1 = new MyObserver("Obj1");
Observer obj2 = new MyObserver("Obj2");
Observer obj3 = new MyObserver("Obj3");
// register observers to the subject
topic.register(obj1);
topic.register(obj2);
topic.register(obj3);
// attach observer to subject
obj1.setSubject(topic);
obj2.setSubject(topic);
obj3.setSubject(topic);
// check if any update is available
obj1.update();
// now send message to subject
topic.postMessage("New Message");
}
}我基本上明白了这一点,但有一件事困扰着我:观察者有一个setSubject()方法,他自己(观察者)也注册主题并设置主题,这在我看来有点错误。
我可以更改接口并删除setSubject()方法,但是我的问题是,从观察者模式的角度来看,我真的需要在注册后设置一个主题吗?
发布于 2015-10-05 13:51:11
你是对的,这个方法添加了不必要的依赖,因为下面这一行:
String msg = (String) topic.getUpdate(this);这两个方法(setSubject和getUpdate)可以删除,msg可以直接从update()中检索,如下所示:
@Override
public void update(String msg) {
if (msg == null) {
System.out.println(name + ":: No new message");
} else
System.out.println(name + ":: Consuming message::" + msg);
}使用notifyObservers中的更新
for (Observer obj : observersLocal)
{
obj.update(this.message);
}发布于 2015-10-05 13:46:15
那么,观察者必须知道关于他的主题的细节,否则他就不能观察到它,对吧?与现实生活相匹配:你还必须了解你正在观察的对象的细节,以便知道何时需要采取特定的行动,对吗?
问题是,你可以用接口来解耦它,这样你就能够构建一个更通用的观察者……然后,您的被观察对象只需要实现该观察者接口,您的观察者就可以开始工作了。
发布于 2015-10-06 22:15:28
让我们看一下1995年以来由UML语言中的GoF定义的观察者模式:
在Subject方面,您的代码具有register和unregister,它们类似于Attach和Detach,并且您的notifyObservers也符合该模式。
从观察者模式的角度来看,我真的需要在注册后设置一个主题吗?
根据该模式的这个GoF版本,ConcreteObserver必须以某种方式知道主题才能自我更新。所以,你需要设置一个主题。
该模式还有一种变体(Java语言的Observer/Observable),其中Update()方法传递一个包含状态相关信息的对象,这样ConcreteObserver就可以在不必与ConcreteSubject通信的情况下更新其状态。从理论上讲,你不需要存储到主题的链接。
依赖于趋于稳定的事物
该模式的目标不是消除所有依赖项。主题是不会有代码更改的类。软件设计中的一条规则是在代码中不太可能发生更改的类上创建依赖项。
如果您更改了主题的代码,则该模式不起作用。
https://stackoverflow.com/questions/32941942
复制相似问题