简体   繁体   中英

Is this the Observer pattern or something else?

This is some code that I've been working on that is inspired by Singleton and by Observer but is really neither. Is this is some other pattern or is it just a mutt? The context for this is an Android app where several Activity objects may be interested in an object that is tied to a particular account. It loads the data when the first Activity registers itself and lets the data go once there are no more observers.

I'd like to know if, for example, it's a horrible idea to use class variables and methods to manage these objects and observers. Whatever feedback is welcome.

This question started out as a question about when to notify an Observer if the object it's registering for already exists. As I was typing the question, I realized that in pure Observer the Observable is the interesting thing and static methods are not involved.

public class MyObserver{
    public MyObserver(String id){
        MyObservable.addObserver(this, id);
    }

    public void update(MyObservable myObservable){
        ... do something with myObservable ...
            ... maybe based on myObservable.id ...
    }
}

public class MyObservable{

    /*********************************
     * Object management static code *
     *********************************/
    private static Map<String,Set<MyObserver>> observers;
    static{
        observers = new Map<String,Set<MyObserver>>();
    }

    private static Map<String,MyObservable> instances;
    static{
        instances = new HashMap<String,MyObservable>();
    }

    private static void addObserver(MyObserver myObserver, String id){
        Set<MyObserver> myObservers = observers.get(id);
        if(myObservers==null){
            myObservers = new Set<MyObserver>();
            observers.put(myObservers);
        }
        myObservers.add(id);

        MyObservable instance = instances.get(id);
        if(instance!=null){
            myObserver.update(instance);
        } else {
            loadData(id);
        }
    }

    private static void removeObserver(MyObserver myObserver, String id){
        Set<MyObserver> myObservers = observers.get(id);
        if(myObservers!=null){
            myObservers.remove(myObserver);
            if(myObservers.isEmpty()){
                instances.remove(id);
            }
        }
    }

    private static void loadData(String id){
        MyObservable  myObservable = ... asynchronous code to load myObservable ...
        ... callback will call MyObservable.set(id,  myObservable); ...
    }

    private static void set(MyObservable myObservable){
        String id=myObservable.getId();
        instances.put(id, myObservable);
        Set<MyObserver> myObservers = observers.get(id);
        if(myObservers!=null){      
            for(MyObserver myObserver:myObservers){
                myObserver.update(myObservable);
            }       
        }
    }

    /**********************************************
     * Data Object instance variables and methods *
     **********************************************/
    public MyObservable(String id){
        myId=id;
    }

    private string myId;
    private String myData1;
    private String myData2;
    private String myData3;
    ... getters and setters ...

}

Nothing about the observer pattern says how it must be implemented, it just means there's a relationship between who's watching, and who's being watched. Nothing says multiple patterns can't be used in an implementation.

One problem with this type of implementation is that unless object lifecycle is very carefully managed you'll end up with a lot of references to objects that nobody cares about anymore.

In Java, the idiom is to use "Listeners". You should have an interface called XListener . It will define something like your update method. Then you just have your observables with methods addXListener(Xlistener) and removeXListener(XListener) . They maintain a List (not set) of the listeners which can be notified. The observable object can have the same listener more than once. Nothing is static. Check out java.beans.PropertyChangeSupport and java.beans.PropertyChangeListener .

The two main problems with what you have are:

  1. The static stuff in the observable. Why static? If you need only one observable object of that class, then you could use the Singleton pattern. But you should use dependency injection instead.
  2. Strong coupling between the Observable and Observer. The XListener interface should not know about the observables that you will have. Otherwise, you introduce a circular dependency and you are no longer programming to an interface instead of an implementation.

It is a Singleton and Observer .

Global event handlers can work this way, eg registering listeners for any key event in swing.

Make sure you add and remove observers carefully to avoid a memory leak.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM