Java与设计模式(2)--观察者模式

Observer模式是行为模式之一,它的作用是当一个对象(我们称之为主题,Subject)的状态发生变化时,能够自动通知其他关联对象(我们称之为观察者,Observer)。通常情况下一个主题可以对应一个以上的观察者。实际中经常用在我们的事件模型中,例如AWT事件、Swing事件等等。


Observer模式的角色:

  • Subject(主题,被观察者):被观察的对象。当主题的状态发生变化时,需要通知队列中所有观察者对象,因此Subject需要维持(添加,删除,通知)一个观察者对象的队列列表,这个列表中维护一个所有观察者对象,并在发生变化时通知他们。
  • ConcreteSubject:被观察者的具体实现。包含一些基本的属性状态及其他操作。
  • Observer(观察者):接口或抽象类。当Subject的状态发生变化时,Observer对象将通过一个callback函数得到通知。
  • ConcreteObserver:观察者的具体实现。得到通知后将完成一些具体的业务逻辑处理。

JDK提供了对observer设计模式的支持:

  • java.util.Observable类扮演Subject角色,一个类只需通过继承java.util.Observable类便可担当ConcreteSubject角色;
  • java.util.Observer接口扮演Observer角色,一个类只需实现java.util.Observer接口便可担当ConcreteObserver角色。
  • java.util.Observable的实现类通过调用setChanged()方法以及notifyObservers(Object)方法便可简单地通知Observer。

下面是一个简单的例子:

Subject已经被实现为Observable类,且Observer已经被实现为Observer接口,所以我们只需要实现ConcreteSubject和ConcreteObserver即可:

ConcreteSubject:

public class ConcreteSubject extends Observable {
	public String str;

	public void setStr(String str) {
		this.str = str;
		// 属性发生变更,需要设置change属性并通知所有的Observer对象
		setChanged();
		notifyObservers(str);
	}

}

ConcreteObserver:

public class ConcreteObserver implements Observer {
	@Override
	public void update(Observable o, Object arg) {
		// 被ConcreteSubject对象通知需要刷新
		System.out.println("Parameter is " + (String)arg);
	}

}

测试类:

public class ConsoleTest {
	public static void main(String[] args) {
		ConcreteSubject subject = new ConcreteSubject();
		
		ConcreteObserver obj1 = new ConcreteObserver();
		ConcreteObserver obj2 = new ConcreteObserver();
		ConcreteObserver obj3 = new ConcreteObserver();
		
		subject.addObserver(obj1);
		subject.addObserver(obj2);
		subject.addObserver(obj3);
		subject.setStr("Hello");
	}

}


我们再去看看源代码:

Subject的源代码:去掉注释后我们可以发现主要就是实现了add、delete、notify这几个主要的方法,这样我们普通的开发者就无需自己去实现这些,只要调用setChanged和notify即可。


package java.util;

public class Observable {
    private boolean changed = false;
    private Vector obs;

    public Observable() {
        obs = new Vector();
    }

    public synchronized void addObserver(Observer o) {
        if (o == null)
            throw new NullPointerException();
        if (!obs.contains(o)) {
            obs.addElement(o);
        }
    }

 
    public synchronized void deleteObserver(Observer o) {
        obs.removeElement(o);
    }

 
    public void notifyObservers() {
        notifyObservers(null);
    }

    public void notifyObservers(Object arg) {
        /*
         * a temporary array buffer, used as a snapshot of the state of
         * current Observers.
         */
        Object[] arrLocal;

        synchronized (this) {
            /* We don't want the Observer doing callbacks into
             * arbitrary code while holding its own Monitor.
             * The code where we extract each Observable from
             * the Vector and store the state of the Observer
             * needs synchronization, but notifying observers
             * does not (should not).  The worst result of any
             * potential race-condition here is that:
             * 1) a newly-added Observer will miss a
             *   notification in progress
             * 2) a recently unregistered Observer will be
             *   wrongly notified when it doesn't care
             */
            if (!changed)
                return;
            arrLocal = obs.toArray();
            clearChanged();
        }

        for (int i = arrLocal.length-1; i>=0; i--)
            ((Observer)arrLocal[i]).update(this, arg);
    }

    public synchronized void deleteObservers() {
        obs.removeAllElements();
    }

    protected synchronized void setChanged() {
        changed = true;
    }

    protected synchronized void clearChanged() {
        changed = false;
    }

  
    public synchronized boolean hasChanged() {
        return changed;
    }

    public synchronized int countObservers() {
        return obs.size();
    }
}


Observer代码更加简单:仅仅是一个接口,因为我们每个开发者需要实现不同的刷新方式。


package java.util;

public interface Observer {
    /**
     * This method is called whenever the observed object is changed. An
     * application calls an <tt>Observable</tt> object's
     * <code>notifyObservers</code> method to have all the object's
     * observers notified of the change.
     *
     * @param   o     the observable object.
     * @param   arg   an argument passed to the <code>notifyObservers</code>
     *                 method.
     */
    void update(Observable o, Object arg);
}

这样看下来整个Observer设计模式就没有那么神秘了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值