Observer_Pattern

package observer_pattern;

import java.util.ArrayList;
import java.util.List;

public abstract class Subject {
    private ArrayList<Observer> observers = new ArrayList<Observer>();
    
    public void attach(Observer observer) {
        observers.add(observer);
    }
    public void detach(Observer observer) {
        observers.remove(observer);
    }
    //@Override:if we use notify as the method's name,the question will
    //be:Cannot override the final method from Object.
    public void Notify() {
        for(Observer o : observers){
            o.update();//Not good enough for its narrow limitation.
        }
    }
    /***This is used for processing the "OldConcreteObserver."***/
    //List is a interface and ArrayList is the class that implements it. 
    private List<Event> objects = new ArrayList<Event>();

    public void addEvent(Object object,String methodName,Object...args) {
        objects.add(new Event(object,methodName,args));
    }
    
    public void NotifyAll() throws Exception{
        for(Event e:objects) {
            e.invoke();//It's better than "o.update()",which improved the universality.
        }
    }
}

package observer_pattern;

public class ConcreteSubject extends Subject{
    private String subjectState;

    public String getSubjectState() {
        return subjectState;
    }

    public void setSubjectState(String subjectState) {
        this.subjectState = subjectState;
    }
    
    /***This is used for processing the "OldConcreteObserver."***/

    @Override
    public void NotifyAll() {
        try {
            super.NotifyAll();
        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        }
    }
}

package observer_pattern;

public interface Observer {
    //We use interface just because there will always be great difference
    //among observers in practical use.
    public abstract void update();
    //The "interface" prescribe a limit to every single subclass that
    //implements it in some degree,which can be seen as handicap.
    //Furthermore,we can use reflection to avoid using interface.
}

package observer_pattern;

public class ConcreteObserver implements Observer{
    private String name;
    private String observerState;
    private ConcreteSubject subject;//If one observer subscribe a lot of subjects,the 
    //type of "Subject" will be better,which is the superclass.
    public ConcreteObserver(ConcreteSubject subject,String name) {
        this.subject = subject;
        this.name = name;
    }
    public void update() {
        observerState = subject.getSubjectState();
        System.out.println("The" + name +"'s situation is " + observerState);
    }
    public ConcreteSubject getSubject() {
        return subject;
    }
    public void setSubject(ConcreteSubject subject) {
        this.subject = subject;
    }
    
}

package observer_pattern;

import java.lang.reflect.Method;

public class Event {
    private Object object;

    private String methodName;

    private Object[] params;

    private Class[] paramTypes;

    /*
     * java.lang.Class Instances of the class Class represent classes and interfaces
     * in a running Java application. An enum is a kind of class and an annotation
     * is a kind of interface. Every array also belongs to a class that is reflected
     * as a Class object that is shared by all arrays with the same element type and
     * number of dimensions. The primitive Java types (boolean, byte, char, short,
     * int, long, float, and double), and the keyword void are also represented as
     * Class objects. Class has no public constructor. Instead Class objects are
     * constructed automatically by the Java Virtual Machine as classes are loaded
     * and by calls to the define Class method in the class loader.
     */
    public Event(Object object, String method, Object... args) {
        this.object = object;
        this.methodName = method;
        this.params = args;
        contractParamTypes(this.params);
    }

    private void contractParamTypes(Object[] params) {
        this.paramTypes = new Class[params.length];
        for (int i = 0; i < params.length; i++) {
            this.paramTypes[i] = params[i].getClass();
        }
    }

    public void invoke() throws Exception {
        Method method = object.getClass().getMethod(this.methodName, this.paramTypes);
        // Let's see if this function exists.
        if (null == method) {
            return;
        }
        method.invoke(this.object, this.params);// Use reflection to call functions.
    }
}

package observer_pattern;

public class OldConcreteObserver {//Don't implement the interface of Subject.
    private String name;
    private ConcreteSubject sub;
    public OldConcreteObserver(ConcreteSubject sub,String name) {
        this.name = name;
        this.sub = sub;
    }
    public void oldUpdate(String feeling) {//The premier method's name is different to "update".
        System.out.println("The" + name +"'s situation is " + sub.getSubjectState());
        System.out.println("The feeling is "+feeling);
    }
}

package observer_pattern;

public class Main {
    public static void main(String args[]) {
        ConcreteSubject s = new ConcreteSubject();
        s.attach(new ConcreteObserver(s,"X"));
        s.attach(new ConcreteObserver(s,"Y"));
        s.attach(new ConcreteObserver(s,"Z"));
        s.setSubjectState("ABC");
        s.Notify();
        /***This is used for processing the "OldConcreteObserver."***/
        s.addEvent(new OldConcreteObserver(s,"W"), "oldUpdate", "happy");
        s.NotifyAll();
    }
}
/*
 * The observer_pattern is also called Publish/Subscribe pattern,which is also
 * known as notifier/observer.Java can use dynamic proxy to implement the delegation that is used directly in c#.
 */

This is a general introduction to the 23 design patterns:
https://blog.csdn.net/GZHarryAnonymous/article/details/81567214

猜你喜欢

转载自blog.csdn.net/GZHarryAnonymous/article/details/82814286