当前位置: 首页 > 知识库问答 >
问题:

普通观察者模式与模板观察者模式

楚勇
2023-03-14

我想知道用模板observer配置的observer模式是否比常规observer模式更方便。模板观察者的概念是一个可观察的类,它具有配置为模板的特定观察者类型。作为一个例子,我将展示一个普通的观察者,并将其与模板观察者进行比较。

正常观察者模式

正常观察者界面:

   public interface NormalObserver {

    //Update method
    void update(final String updateIn);
}

对于实现NormalObserver接口的每个类,更新函数都是相同的。如果要实现特定的观察者,例如具有不同更新参数的观察者,这会导致问题。

具体观察者:

 public class ConcreteNormalObserver implements NormalObserver {

    //Update implication for NormaObserver interface
    @Override
    public void update(String updateIn) {
        System.out.println(updateIn);
    }
}

正常可观察界面:

 public interface NormalObservable {

    //method for adding an observer
    void addObserver(NormalObserver observerIn);

    //method for removing an observer
    void removeObserver(NormalObserver observerIn);

    //method for notifying observers
    void notifyObservers();

}

混凝土正常可观察:

    public class ConcreteNormalObservable implements NormalObservable {

    //List for Observer
    private List<NormalObserver> mObservers;

    public ConcreteNormalObservable() {
        this.mObservers = new ArrayList<>();
    }

    @Override
    public void addObserver(NormalObserver observerIn) {

        if(observerIn != null && !this.mObservers.contains(observerIn)) {
            this.mObservers.add(observerIn);
        }
    }

    @Override
    public void removeObserver(NormalObserver observerIn) {
        this.mObservers.remove(observerIn);
    }

    @Override
    public void notifyObservers() {

        for(NormalObserver lObserver: this.mObservers) {
            lObserver.update("Update");
        }
    }
}

在我看来,这是一个简单的观察者模式,你可以说notifyObservers方法有点多余,因为一个观察者可以在任何地方从其观察者调用update方法。

模板观察者模式

模板可观察界面:

  /**
 * @param <ObserverType> Concrete observer to implement in observable,
 * this ObserverType specifies the update functions which the TemplateObservable can call.
 */
public interface TemplateObservable<ObserverType> {

    /**
     * Function to add an Observer of a specific type
     * @param observerIn
     */
    void addObserver(ObserverType observerIn);

    /**
     * Function to remove an Observer of a specific type
     * @param observerIn
     */
    void removeObserver(ObserverType observerIn);

}

模板类型定义了要使用的观察者类型,因此具体的观察者指定了要使用的观察者。

混凝土可观察模板:

   /**
 * Concrete example of a class that implements TemplateObservable.
 * This class is uses a ConcreteTemplateObserver as its observerType.n
 */
public class ConcreteTemplateObservable implements TemplateObservable<ConcreteTemplateObserver> {

    //List to hold all the observers
    private List<ConcreteTemplateObserver> mObservers;

    public ConcreteTemplateObservable() {
        this.mObservers = new ArrayList<>();
    }

    @Override
    public void addObserver(ConcreteTemplateObserver observerIn) {

        //Check for non null and if the observer parameter is not already in the observerList
        if(observerIn != null && !this.mObservers.contains(observerIn)) {
            this.mObservers.add(observerIn);
        }
    }

    @Override
    public void removeObserver(ConcreteTemplateObserver observerIn) {
        this.mObservers.remove(observerIn);
    }

    //Own update function, no need for notify function, but can be optional.
    public void update() {

        for(ConcreteTemplateObserver lObserver: this.mObservers) {
            lObserver.updateTemplateObserver("Update");
        }
    }
}

混凝土模板观察者:

  public class ConcreteTemplateObserver {

    public void updateTemplateObserver(final String messageIn) {
        System.out.println(messageIn);
    }
}

我确信模板观察者模式更有用,因为你可以从可观察的调用特定的更新函数,而在正常可观察的情况下,你被迫使用正常的更新函数,但我怀疑模板可观察是否符合观察者模式的标准。

共有1个答案

陈昊昊
2023-03-14

我看不出有什么好处。实际上,一个可观察对象可以发送几种不同类型的通知,也可以接受几种类型的观察者。

下面是另一个模型,它一次性实现了观察者列表操作,以及分派机制。

考虑可观察的类:

public abstract class Observable {
    private static final Logger LOG
            = Logger.getLogger(Observable.class.getName());
    private final List observers = new ArrayList<>();

    protected void addObserver(Object observer) {
        observers.add(observer);
    }

    protected void removeObserver(Object listener) {
        observers.remove(listener);
    }

    protected <T> T getNotifier(Class<T> intf) {
        ClassLoader cl = intf.getClassLoader();
        return intf.cast(Proxy.newProxyInstance(cl, new Class[] {intf},
                new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args)
                    throws Throwable {
                return dispatch(method, args);
            }
        }));
    }

    protected Object dispatch(Method method, Object args[]) {
        Class<?> intf = method.getDeclaringClass();
        Object result = null;
        for (Object observer: observers) {
            try {
                if (intf.isInstance(observer)) {
                    result = method.invoke(observer, args);
                }
            } catch (IllegalAccessException | InvocationTargetException e) {
                LOG.log(Level.SEVERE, "Error invoking listener method", e);
            }
        }
        return result;
    }
}

现在,以一个可观察列表为例,它接受实现以下接口的观察者:

public interface ListObserver<T> {
    public void elementAdded(int i, T newElem);
    public void elementRemoved(int i, T oldElem);
    public void elementReplaced(int i, T oldElem, T newElem);
}

可观察列表将按以下方式实施:

public class ObservableList<T> extends Observable {
    private final List<T> elements = new ArrayList<>();

    private final ListObserver<T> notifier = getNotifier(ListObserver.class);

    public void addObserver(ListObserver<T> obs) {
        super.addObserver(obs);
    }

    public void removeObserver(ListObserver<T> obs) {
        super.removeObserver(obs);
    }

    public void addElement(T newElem) {
        int i = elements.size();
        elements.add(newElem);
        notifier.elementAdded(i, newElem);
    }

    public void removeElement(int i) {
        T oldElem = elements.remove(i);
        notifier.elementRemoved(i, oldElem);
    }

    public void setElement(int i, T newElem) {
        T oldElem = elements.set(i, newElem);
        notifier.elementReplaced(i, oldElem, newElem);
    }
}
 类似资料:
  • 主要内容:介绍,实现,Subject.java,Observer.java,BinaryObserver.java,OctalObserver.java,HexaObserver.java,ObserverPatternDemo.java当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知依赖它的对象。观察者模式属于行为型模式。 介绍 意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知

  • 当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知它的依赖对象。观察者模式属于行为型模式。 介绍 意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。 主要解决:一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。 何时使用:一个对象(目标对象)

  • 观察者模式是软件设计模式的一种。在此种模式中,一个目标对象管理所有相依于它的观察者对象,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用来实时事件处理系统。 定义一个目标构造函数,并实现绑定、解绑和触发等方法: function Subject() { this.events = {}; this.count = 0; }​ Subj

  • 问题 当一个事件发生时你不得不向一些对象发布公告。 解决方案 使用观察者模式(Observer Pattern)。 class PostOffice constructor: () -> @subscribers = [] notifyNewItemReleased: (item) -> subscriber.callback(item) for s

  • 简介 观察者模式(有时又被称为发布/订阅模式)是软件设计模式的一种。在此种模式中,一个目标对象管理所有相依于它的观察者对象,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用来实时事件处理系统。 抽象目标类别 此抽象类别提供一个界面让观察者进行添附与解附作业。此类别内有个不公开的观察者串炼,并透过下列函式(方法)进行作业 添附(Attach):新增观察

  • 当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知它的依赖对象。观察者模式属于行为型模式。 介绍 意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。 主要解决:一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。 何时使用:一个对象(目标对象)