【问题标题】:Renaming implemented methods for Observer pattern in Java在 Java 中重命名观察者模式的实现方法
【发布时间】:2010-11-24 03:37:48
【问题描述】:

我正在使用 Java 中的 Observable 类/Observer 接口来实现观察者模式。 Observer 接口需要覆盖 update(Observable o, Object arg) 方法。

问题是我观察了相当多的类,而我的 update() 方法变得非常大:

public class Foo implements Observer {
    ....

    public void update(Observable o, Object param) {
        if (o instanceof A) {
            // large chunk of code
            ...
        } else if (o instanceof B) {
            // large chunk of code
            ...
        }
            ...
        } else if (o instanceof H) {
            ...
        }
    }

}

为了拆分方法,我正在考虑扩展 Observer 接口,例如AObserver 接口、BObserver 接口.. 分别需要覆盖 onAUpdate、onBUpdate ..。这个方法还可以很容易地根据它实现的接口来确定该类正在观察哪些 Observables。

class Foo implements AObserver, BObserver {
    ....

    public void onAUpdate(Observable o, Object param) {
        if (o instanceof A) {
        // large chunk of code
        ...
    }

    public void onBUpdate(Observable o, Object param) {
        if (o instanceof B) {
        // large chunk of code
        ...
    }
}

问题是如果我继承了Observer,我还是要实现update()方法。我无法将其重命名为 onAUpdate 或我选择的其他名称。

有什么建议吗?谢谢。

【问题讨论】:

    标签: java design-patterns observer-pattern observable


    【解决方案1】:

    我建议创建一个 UpdateHandler 接口来处理任何给定的代码块。每个案例都可以用地图处理。

    示例代码如下:

    // Interface to implement for each case
    public interface UpdateHandler {
        public void update(Observable source, Object data) ;
    }
    

    向你的主类添加一个实例字段,如下所示:

    private Map, UpdateHandler> handlers = new HashMap, Update Handler>();
    

    创建一个方法来初始化处理程序

    protected void initializeHandler() {
        handler.put(Integer.class, new IntegerUpdateHandler());
        handler.put(String.class, new StringUpdateHandler());
        ...
    }
    

    更新方法将简单地找到适当的处理程序并分派调用

    public void update(Observable source, Object data)
    {
        UpdateHandler handler = handlers.get(data.getClass()) ;
        if (handler == null) 
        {
            // use a default handler ? throw an exception ? your choice ;)
        } else {
            handler.update(source, data) ;
        }
    }
    

    此实现将允许您根据需要添加新的处理程序,只需进行最少的更改。

    可以在之前的工作的基础上完成另一种可能的实现,只需 3 步过程。

    1) 更改 handlers 字段的声明。

    Map<Class<?>, Class<? extends UpdateHandler>> handlers ;

    2) 改变初始化方法

    handlers.put(Integer.class, IntegerInputHandler.class);

    3) 更改主更新方法以创建提供的 UpdateHandler 实现的新实例。

    UpdateHandler handlerInstance = null ;
    Class<? extends UpdateHandler> handler = null ;
    handler = handlers.get(data.getClass()) ;
    ...
    handlerInstance = handler.newInstance() ;
    handlerInstance.update(source, data) ;
    

    【讨论】:

    • 我有多个对象观察 observable。当有趣的事情发生时,每个查看 observable 的类都会表现不同。例如,如果 Foo 和 Bar 都观察 A,当 A 发生变化时,Foo 这样做,Bar 这样做。使用这个解决方案,这并不意味着我必须为每个对象创建一个处理程序来分别处理更新,例如FooAHandler,BarAHandler?
    • @David:如果是这样,你不需要任何特别的东西。默认的Observable 和Observer 可以做到这一点。在您的原始帖子中,您正在检查Observable 的类型,这表明单个Observer 正在观察多个Observable。
    • 这是一个多对多的关系——多个观察者正在观察多个观察者。
    【解决方案2】:

    在这里,我使用观察者和访问者模式编写了一个原始实现。你可以把它当作一个想法来加强它,并在你看到一些漏洞的地方进行填补。

    public interface IObserver extends Observer {
        public void add(AbstractObservable observable, IObserverVisitor visitor);
        public void remove(AbstractObservable observable);
        public void removeAll();
    }
    

    public class Observer implements IObserver {
    
        Map<AbstractObservable, IObserverVisitor> observableMap =
                new HashMap<AbstractObservable, IObserverVisitor>();
    
        public void add(AbstractObservable observable, IObserverVisitor visitor) {
            observableMap.put(observable, visitor);
        }
    
        public void remove(AbstractObservable observable) {
            observableMap.remove(observable);
        }
    
        public void removeAll() {
            observableMap.clear();
        }
    
        public void update(Observable o, Object arg) {
            observableMap.get(o).visit(this, o, arg);
        }
    
    }
    

    public class AbstractObservable extends Observable{
    
        public synchronized void addObserver(IObserver o, IObserverVisitor visitor) {
            o.add(this, visitor);
            super.addObserver(o);
        }
    
        public synchronized void deleteObservers(IObserver o) {
            o.removeAll();
            super.deleteObservers();
        }
    
        public synchronized void deleteObserver(IObserver o) {
            o.remove(this);
            super.deleteObserver(o);
        }
    
        @Override
        public synchronized void deleteObserver(Observer o) {
            throw new UnsupportedOperationException();
        }
    
        @Override
        public synchronized void addObserver(Observer o) {
            throw new UnsupportedOperationException();
        }
    
        @Override
        public synchronized void deleteObservers() {
            throw new UnsupportedOperationException();
        }
    
        @Override
        public synchronized int countObservers() {
            return super.countObservers();
        }
    
        @Override
        public synchronized boolean hasChanged() {
            return super.hasChanged();
        }
    
        @Override
        public void notifyObservers() {
            super.notifyObservers();
        }
    
        @Override
        public void notifyObservers(Object arg) {
            super.notifyObservers(arg);
        }
    
        @Override
        protected synchronized void clearChanged() {
            super.clearChanged();
        }
    
        @Override
        protected synchronized void setChanged() {
            super.setChanged();
        }
    
    }
    

    public class Observable1 extends AbstractObservable {
        public void changeSomething() {
          setChanged();
          notifyObservers();
        }
    }
    

    public class Observable2 extends AbstractObservable {
        public void changeSomething() {
          setChanged();
          notifyObservers();
        }
    }
    

    public interface IObserverVisitor {
        void visit(IObserver obsrvr, Observable obsrvable, Object o);
    }
    

    public class ObserverVisitor1 implements IObserverVisitor{
    
        public void visit(IObserver obsrvr, Observable obsrvable, Object o) {
            System.out.println("updated one");
        }
    
    }
    

    public class ObserverVisitor2 implements IObserverVisitor{
    
        public void visit(IObserver obsrvr, Observable obsrvable, Object o) {
            System.out.println("updated two");
        }
    }
    

    public class ObserverTest {
    
        @Test
        public void testAnything() {
            Observable1 obsrvable1 = new Observable1();
            Observable2 obsrvable2 = new Observable2();
    
            Observer obsrvr = new Observer();
            obsrvable1.addObserver(obsrvr, new ObserverVisitor1());
            obsrvable2.addObserver(obsrvr, new ObserverVisitor2());
    
            obsrvable1.changeSomething();
            obsrvable2.changeSomething();
        }
    
    }
    

    希望你没有迷路。 :)

    【讨论】:

    • 谢谢,这是一个不错的解决方案。我不确定它是否直接适合我的情况,我可能需要调整一些部分,但它给了我一些不错的想法。
    • @David:很高兴你发现它有帮助。我的努力没有白费。 ;)
    【解决方案3】:

    将每个条件中的代码块移动到适当命名的方法中。

    public void update(Observable o, Object param) {
        if (o instanceof A) {
             onAUpdate(o, param);
        }
    
        if (o instanceof B) {
             onBUpdate(o, param);
        }
    }
    
    public void onAUpdate(Observable o, Object param) {
    
        // large chunk of code
    }
    
    public void onABUpdate(Observable o, Object param) {
    
        // large chunk of code
    }
    

    【讨论】:

    • 是否可以为每个 Observable 实现一个接口?当我的类实现 AObserver、BObserver... 而不仅仅是一个通用的 Observer 时,确定我的类感兴趣的对象变得更加清晰
    • 原来他就是这么干的。您只是建议将块取出以分隔方法。代码仍然有异味。
    • 他将问题描述为“我的 update() 方法变得非常大”。
    • @david:你可以选择矫枉过正。或者,您可以编写一些可以工作、不会影响性能、模块化且可维护的东西。
    • 如果您可以将update 方法与on&lt;X&gt;Update 方法的抽象或默认实现一起推送到(抽象)基类中,则可以使这更加优雅。
    猜你喜欢
    • 2011-12-21
    • 1970-01-01
    • 2017-11-13
    • 1970-01-01
    • 1970-01-01
    • 2013-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多