基于UML图的观察者模式实现

Mor*_*itz 0 java design-patterns interface observer-pattern

我无法理解“可重用面向对象软件的元素”中观察者模式的以下 UML 图。谁能解释我为什么我的 Java 实现是错误的,我必须改变什么才能正确实现它?

UML-图

UML-图

尝试(但错误)实施

public interface Subject {
    
    public static final List<Observer> observers = new ArrayList<Observer>();
    
    public void attach(Observer o);
    public void detach(Observer o);
    public void notifyObservers();
}

public interface Observer { 
    public void update();
}

public class ConcreteSubject implements Subject {
    
    private String subjectState;

    @Override
    public void attach(Observer o) {
        observers.add(o);   
    }

    @Override
    public void detach(Observer o) {
        observers.remove(o);
    }

    @Override
    public void notifyObservers() {
        for (Observer o : observers) {
            o.update();
        }       
    }
    
    public String getState() {
        return subjectState;
    }
    
    public void setState() {
        subjectState += "x";
    }
}

public class ConcreteObserver implements Observer {
    
    private ConcreteSubject subject;
    public String observerState;

    @Override
    public void update() {
        observerState = subject.getState();
    }
}
Run Code Online (Sandbox Code Playgroud)

Tho*_*mas 5

一个问题是您有一个静态的观察者列表,Subject因此所有主题都共享相同的观察者。但是,该模式要求每个单独的主题都有自己的观察者,因此将列表放入ConcreteSubject并使其成为实例字段。

另一个问题是您ConcreteObserver有一个 type 字段ConcreteSubject。但是,它应该不知道Subjectso 的具体实现,因此该字段应该只有 type Subject

编辑:实际上,UML 图要求具体的观察者了解具体的主题,以便能够调用,getState()因此上面的段落在您的情况下不正确 - 这应该不是问题。

但是,实际上我实际上会有另一个接口来扩展Subject和隐藏ConcreteSubject观察者的实现。

编辑2

正如所建议的那样,您还可以使用抽象类来处理主题的观察者。这可能是一个阶级之间SubjectConcreteSubject甚至Subject本身,而是因为Java不支持多重继承我会经常使用一些其他的办法,使Subject只是一个接口。

最简单的实现是ConcreteSubject维护观察者列表,但在现实世界的应用程序中,您不希望开发人员这样做或依赖他们正确实现它。

相反,您可以使用一个中央注册表来维护每个主题的观察者列表,并且主题使用它来通知其观察者。许多依赖注入框架以这种方式运行,即每当“主题”发生变化时,它们都会通知其观察者该事件。

  • @MoritzWolff 澄清 Thomas 提出的观点,UML 应该是“与语言无关的”。然而有时,存在基于语言的限制或约束。因此,作为开发人员,您必须了解并探索您所使用的语言的可接受的等效项。 (2认同)