Migrate from GitHub to SourceForge with this tool. Check out all of SourceForge's recent improvements.
Close

Observer Design Pattern (Delegate)

Observer Design Pattern

Observer design pattern is very well known pattern and is used in event-based programming model.

The advantage of using observer design pattern is the providing of event-API, thus the programmer can register listeners and react on fired events. The programmer can divide the software in components and decouple all of them, thus it is possible to reuse or to replace some of the components by providing the same event-API. In ".NET" the observer design pattern is a part of the language, see delegates and events in C#
(msdn - events and delegates). In java programming language the observer design pattern is often used in Swing or other component-based frameworks. But if the programmer wants to define a custom component with own events, he has to implemnt the design-pattern like shown in
wiki - observer pattern. We decided to implement the observer design pattern as a special class, thus we can reuse it.

How to define a Delegate in a component for a field

Below is presented very simple example. It shows how you can use the observer design pattern from happy-collections to define a custom delegate. In example section you find more complex examples. For example you can fire events and give them any parameters.

public class MyComponent {
    private int value;
    //define the delegate
    private IDelegate_1x0 onValueChanged = null;
    ....
    ....
    /**
     * setter, if the new value is unequal to the current value then fire OnValueChanged Event
     * @param newValue
     */
    public void setValue(int newValue) {
        boolean changed = false;
        if(this.value!=newValue)
            changed = true;

        this.value = newValue;

        if(changed)
            this.fireOnValueChanged();
    }

    /**
     * fire OnValueChanged event
     * @param newValue
     */
    protected void fireOnValueChanged(){
        if(onValueChanged==null)
            return;
        this.onValueChanged.fire(new ActionEvent(this, 0 , "value has changed"));
    }

    /**
     * gets OnValueChanged-event
     * @return
     */
    public IDelegate_1x0 getValueChanged() {
        if(onValueChanged==null)
            onValueChanged = new Delegate_1x0();
        return onValueChanged;
    }

    public static void main(String args[]){
        //create two components
        final MyComponent com1 = new MyComponent(16);
        final MyComponent com2 = new MyComponent(32);

        //register onValueChanged Value
        com1.getValueChanged().add(new ActionListener(){
            public void actionPerformed(ActionEvent e) {
                com2.setValue(com1.getValue()*2);
                System.out.println("value of com2 changed = " + com2.getValue());
            }
        });

        /*
         * change the value of com1,
         * however the com2 is registered on com1 and thus the value of com2 will be changed also
         */
        com1.setValue(128);
    }

}

The output:

value of com2 changed = 256

Decorated Observer Design Pattern with Observer Design Pattern

Sometimes it is important to control the registration and "unregistration" of ActionListers on the delegate, thus we implemented an EventDecorator. The EventDecorator decorates the Delegate and fires events if new ActionListeners are registered and old are unregistered.

//create delegate and decorate it with EventDelegate decorator
final EventDelegate_1x0 d =  EventDelegate_1x0.of(new Delegate_1x0());

/**
 * register an action listener which will be notified before 
 * any ActionListeners can be registered on created delegate
 */
d.getOnBeforeAddEvent().add(new ActionListenerT_1x0
        //do something before new Listeners are registered, for example cancel the adding operation [Quellcode ändern!]
    }
});

//register view ActionListeners
d.add(new ActionListener(){
    public void actionPerformed(ActionEvent e) {
        System.out.println("first listener");
    }
});
d.add(new ActionListener(){
    public void actionPerformed(ActionEvent e) {
        System.out.println("second listener");
    }
});

System.out.println("\n*******fire test-event*******\n");
//fire an event and execute registered ActionListeners
d.fire(new ActionEvent(d,0,"test event"));

Multi-threaded Observer Design Pattern

We often use many threads to increase the performance of our application by using new multi-core processors. Thus we need constructs which protect our code in a multi-thread application. Such constructs should be implemented as decorators to avoid the synchronization overhead in places where only one thread is used. Next you can see how to use SynchronuizedDecorator for the Delegate to make it multi-thread safe.

//create delegate and decorate it with EventDelegate decorator
final SynchronizedDelegate_1x0 d = SynchronizedDelegate_1x0.of(new Delegate_1x0());

/**
 * register listeners in different threads [Quellcode ändern!]
 */
Thread t1 = new Thread(){//first thread

    @Override
    public void run() {
        //register action listeners
        d.add(new ActionListener(){
            public void actionPerformed(ActionEvent e) {
                System.out.println("first listener");
            }
        });
    }

};

Thread t2 = new Thread(){//Second thread [Quellcode ändern!]

    @Override
    public void run() {
        //register action listeners
        d.add(new ActionListener(){
            public void actionPerformed(ActionEvent e) {
                System.out.println("second listener");
            }
        });
    }

};

//start threads
t1.start();
t2.start();

//wait for threads
t1.join();
t2.join();

System.out.println("listener count = " + d.getListenerCount());

The output:

listener count = 2

Observer Design Pattern examples