On Observer mode of Observer

Keywords: Programming Java Big Data

I. Preface

In fact, the best name of observer mode should be "publish and subscribe" mode, which is similar to the publish and subscribe mode in our big data, but there are also differences. In the previous design mode, we learned the arbiter mode, in which when the state of the control changes, we will send a message to the arbiter and let the arbiter arbitrate, which is actually the same as publishing. Cloth subscription is very similar, but its use is not the same. The arbiter mode is used to release the calling relationship between complex objects, so as to develop independently. The observer mode is passively awakened when the state of the observed changes, and the corresponding processing is carried out. The implementation of the two modes is similar, for example, they are both passively awakened, but the idea and use are It's different. It's different after being awakened.

Two, code

First of all, we implement the observer pattern ourselves. Second, we use java to implement the good observer interface. Then we compare the differences between the two.

(I) realize the observer mode

package zyr.dp.observer;

import java.util.ArrayList;
import java.util.Iterator;

public abstract class NumberGenerator {

    private ArrayList observers=new ArrayList();
    
    public void add(Observer observer){
        observers.add(observer);
    }
    public void remove(Observer observer){
        observers.remove(observer);
    }
    public void notifyObserver(){
        Iterator it=observers.iterator();
        while(it.hasNext()){
            Observer object=(Observer)it.next();
            object.update(this);
        }
    }
    public abstract void execuate();
    public abstract int getNumber();
}
package zyr.dp.observer;

import java.util.Random;

public class RandomNumberGenerator extends NumberGenerator {

    private Random random=new Random();
    private int number;
    public int getNumber(){
        return number;
    }
    public void execuate() {
        for(int i=0;i<20;i++){
            number=random.nextInt(60);
            notifyObserver();
        }
    }

}
package zyr.dp.observer;

public interface Observer {
    public abstract void update(NumberGenerator object);
}
package zyr.dp.observer;

public class DigitalObserver implements Observer {

    public void update(NumberGenerator object) {
        System.out.println("DigitalObserver:"+object.getNumber());
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}
package zyr.dp.observer;

public class GraphObserver implements Observer {

    public void update(NumberGenerator object) {
        System.out.print("GraphObserver:");
        for(int i=0;i<object.getNumber();i++){
            System.out.print("*");
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println();
    }

}
package zyr.dp.observer;

public class Main {

    public static void main(String[] args) {
        NumberGenerator numberGenerator=new RandomNumberGenerator();
        numberGenerator.add(new DigitalObserver());
        numberGenerator.add(new GraphObserver());

        numberGenerator.execuate();
    }

}

It can be seen from this that when the state of the observed changes, the observer will be notified actively, and the notifyObserver method will be used to transfer its state to the past. Because it is an abstract class and interface defined by itself, it is very convenient to use, and there are not many codes, so it can complete the update operation according to its own requirements, and compare with the arbitrator model. In the arbitrator mode, the team members themselves have been combined into the arbitrator, which is also different. The code is relatively simple. The reason why the observer uses the abstract class instead of the interface is that it needs to define the delegation to the observer object. Therefore, the abstract class is used. The observer only uses the update method to delegate the observer through the way of parameter passing. Therefore, it makes the interface clearer. Of course, the abstract class can also be used, but not the one that can use the interface. Use abstract classes, because a class can only inherit one parent class, but can implement many interfaces.

(II) using the observer mode of java

package zyr.dp.java;

import java.util.Observable;
import java.util.Random;

public class RandomNumberGenerator extends Observable {

    private Random random=new Random();
    private int number;
    public int getNumber(){
        return number;
    }
    public void execuate() {
        for(int i=0;i<20;i++){
            number=random.nextInt(60);
            setChanged();
            notifyObservers();
        }
    }

}
package zyr.dp.java;

import java.util.Observable;
import java.util.Observer;

public class DigitalObserver implements Observer {

    public void update(Observable object, Object arg) {
        System.out.println("DigitalObserver For:"+((RandomNumberGenerator)object).getNumber());
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}
package zyr.dp.java;

import java.util.Observable;
import java.util.Observer;

public class GraphObserver implements Observer {


    public void update(Observable object, Object arg) {
        System.out.print("GraphObserver by:");
        for(int i=0;i<((RandomNumberGenerator)object).getNumber();i++){
            System.out.print("*");
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println();
    }

}
package zyr.dp.java;

import java.util.Observable;

public class Main {

    public static void main(String[] args) {
        Observable observable=new RandomNumberGenerator();
        observable.addObserver(new DigitalObserver());
        observable.addObserver(new GraphObserver());

        ((RandomNumberGenerator)observable).execuate();
    }

}

It can be seen that in the observer mode defined by java, first of all, you need to modify setChanged(); to make notifyObservers effective; secondly, the parameters passed are not very flexible, and they need to be forced to convert to what we want; finally, they need to be forced to convert when they are used. This is more troublesome, and the observer also inherits the abstract class Observable, which is not convenient for future functions. If you want to inherit other classes later, it will be very troublesome. When we design our own, we can use some methods to turn abstract classes into interfaces, but we also need some operations.

Three, summary

Through the observer pattern, the observer and the observed are oriented to abstract programming. The observer does not need to know whose instance the observed object is, but only needs to know that the object inherits the abstract class of the observed. Therefore, when the observed is added, the observer does not need to modify. In the same way, for the observed instance, it is not necessary to know which observer you are observing, but only to know that the observer who observes you must use the observer's interface. Therefore, the scalability between the observer and the observed is improved through abstract oriented programming, which is convenient for componentization.

We can see that if you can use delegation in object-oriented programming, you should not use inheritance. Delegation is weak association and inheritance is strong association. And some common operations are abstracted and defined in abstract classes. Instead of using concrete types in parameter passing, interfaces or abstract classes are used. This design idea is easy to be componentized and replaceable.

 

On the design mode

Posted by mistercoffee on Thu, 24 Oct 2019 00:27:41 -0700