What is the difference in the observer pattern in a master's eye?

The Observer mode is one of the many modes used. For the first time, I just write an example based on the introductory demo, but I don't know where to use it, how to use it, it's a textbook. Individuals like blogs or materials that are more practical. Recently I was hungry to make up for it. I feel a little bit of a gain. Record it.

Basic Section

1. Basic classical structure of the observer model

2. Getting Started Small demo

Classic little demo1:

Observer

/**
 * Observer interface, which defines an updated interface for those who are notified when the target changes
 */
public interface Observer {
    /**
     * Updated interface
     */
    public void update(Subject subject);
}

ConcreteObserver

//Specific observer objects, implementation of update methods, use their own state and
public class ConcreteObserver implements Observer {

    @Override
    public void update(Subject subject) {
        //Specific implementation
        //There may be a need to update the observer's status to match that of the target
        String message = ((ConcreteSubject) subject).getSubjectState();
        System.out.println("Received a notification: The status obtained is: " + message);
    }

}

Subject

/**
 * Target object, which knows who observes it, and provides an interface to register and delete observers
 */
public class Subject {
    /**
     * Used to save registered observer objects
     */
    private List<Observer> observers = new ArrayList<>();
    /**
     * Register Observer Object
     */
    public void attach(Observer observer){
        observers.add(observer);
    }
    /**
     * Delete Observer Object
     */
    public void detach(Observer observer){
        observers.remove(observer);
    }
    /**
     * Notify all registered observer objects
     */
    protected void notifyObservers(){
        for (Observer observer: observers){
            observer.update(this);
        }
    }

}

ConcreteSubject

/**
 * Specific target object, responsible for saving the relevant state to the corresponding observer object
 * And in my own state
 */
public class ConcreteSubject extends Subject {
    /**
     * Status of the target object
     */
    private String subjectState;

    public String getSubjectState() {
        return subjectState;
    }

    public void setSubjectState(String subjectState) {
        this.subjectState = subjectState;
        this.notifyObservers();
    }
}

Test

public class Test {
    public static void main(String[] args) {
        //Observer
        Observer concreteObserver1 = new ConcreteObserver();
        Observer concreteObserver2 = new ConcreteObserver();
        //The target object, that is, the observee target, can have more than one demo, which is distinguished by the state
        ConcreteSubject subject1 = new ConcreteSubject();
        //Register Observers
        subject1.attach(concreteObserver1);
        subject1.attach(concreteObserver2);
//        ConcreteSubject subject2 = new ConcreteSubject();
//        //Register Observers
//        subject2.attach(concreteObserver1);
//        subject2.attach(concreteObserver2);
        //give an announcement
        subject1.setSubjectState("Notice 1: Sent");
//        System.out.println("===Change to a topic=====");
//        subject2.setSubjectState("Notification 2: Sent");

    }
}

Run result: The subject sends a message to the observer:

A small case of guarding in loudspeaker design mode

Subject

public interface Subject {

    /**
     * Add an observer
     * @param observer
     */
    void addObserver(Observer observer);
    /**
     * Remove the specified observer
     * @param observer
     */
    void removeObserver(Observer observer);
    /**
     * Remove all observers
     */
    void removeAll();

    /**
     * data Is the data to be notified to the observer
     * Since Object is the parent of all classes, polymorphism can be used, and of course you can also use generics
     * @param data
     */
    void notifyAllObserver(Object data);

    /**
     * Notify an observer individually
     * @param observer
     * @param data
     *  data Is the data to be notified to the observer
     * Since Object is the parent of all classes, polymorphism can be used, and of course you can also use generics
     */
    void notify(Observer observer,Object data);

}

ConcreteSubject

/**
 * Specific subject objects 
 * Thread security is no longer implemented here.
 * Reference if you are interestedJava.util Observable reported
 * @author xujun
 *
 */

public class ConcreteSubject implements Subject {

    List<Observer> mList = new ArrayList<>();

    @Override
    public void addObserver(Observer observer) {
        // Ensure that the same observer contains only one
        if (observer == null) {
            throw new NullPointerException("observer == null");
        }
        if (!mList.contains(observer)) {
            mList.add(observer);
        }
    }

    @Override
    public void removeObserver(Observer observer) {
        mList.remove(observer);
    }

    @Override
    public void removeAll() {
       mList.clear();
    }

    @Override
    public void notifyAllObserver(Object data) {
        for (Observer observer : mList) {
            observer.update(data);
        }
    }

    @Override
    public void notify(Observer observer, Object data) {
        if(observer!=null){
            observer.update(data);
        }
    }

}

Observer

/**
 * Observer Interface
 * @author Administrator
 *
 */
public interface Observer {

    /**
     * 
     * @param data    Data passed by the observer to the observer
     */
    void update(Object data);


}

CartoonObserver

public class CartoonObserver implements Observer {

    @Override
    public void update(Object data) {
        System.out.println( " I am"+this.getClass().
                getSimpleName()+",  "+data+"Don't read comics anymore");    
    }

}

NBAObserver

public class NBAObserver implements Observer {
    public class CartoonObserver implements Observer {

        @Override
        public void update(Object data) {
            System.out.println( " I am"+this.getClass().getSimpleName()+",  "+data+"Don't read comics anymore");
        }
    }

    @Override
    public void update(Object data) {
        System.out.println(" I am" + this.getClass().getSimpleName() + ",  " + data + "Don't look at it NBA Yes");
    }

}

TestObserver

public class TestObserver {

    public static void main(String[] args) {
        //theme
        ConcreteSubject concreteSubject = new ConcreteSubject();
        //Observer
        CartoonObserver cartoonObserver = new CartoonObserver();
        NBAObserver nbaObserver = new NBAObserver();
        //Add an observer
        concreteSubject.addObserver(cartoonObserver);
        concreteSubject.addObserver(nbaObserver);
       //Publish Message Notification
        concreteSubject.notifyAllObserver("The teacher is here");
    }
}

Running result: As soon as the sender sends a notification, the observer receives it.

3. Two ways of using the classic observer mode: push and pull

When using the observer mode, there are two phases:

  • Stage of preparation, phase of maintaining the relationship between goals and observers

  • The actual running phase, the phase in which the goal changes, causing the observer to respond

The usage method mentioned here is for the actual operation phase.Problem getting exact data originator for target.

  • Push model Target object actively pushes target details to the observer, regardless of whether the observer needs them or not, the data is the target object definition, which is equivalent to broadcasting to the observer.In the previous example, the second is the push model.
  • Pull Model When the target object notifies the observer, it only gives its own reference to the observer, and the observer obtains it by using the reference as needed.In the example just given, the first is the pull model.Target object passes this to the observer.

In development, if the data is determined, a push model can be used. If the data the observer wants is not fixed, a pull model is recommended, which is more flexible and scalable.In short, it is better to pull the model.

Beginners generally learn only above.Let's move on to a more thought-provoking section:

Advanced section (application scenarios)

1. How to differentiate between observers

The demo above is all notified when the observer is notified at present. How to design it so that different observers can handle the operation according to different situations?

Ideas: 2, One is that the target can be fully notified, but the observer does nothing. Another way is to make a judgment within the goal without notifying you. The second is recommended here, which allows for unified logical control and unified assignment of observers, facilitating business control and future expansion.

Examples include water pollution, notification to inspectors, early Warners and leaders of inspection departments according to the pollution situation. Replace as follows:

WaterQualitySubject - Target object for water quality monitoring

/**
 * Define target objects for water quality monitoring
 */
public abstract class WaterQualitySubject {
    /**
     * Used to save registration
     */
    protected List<WatcherObserver> observers = new ArrayList<>();
    /**
     * Register Observer Object
     */
    public void attach(WatcherObserver observer){
        observers.add(observer);
    }
    /**
     * Delete Observer Object
     */
    public void detach(WatcherObserver observer){
        observers.remove(observer);
    }
    /**
     * Notify the corresponding observer object
     */
    public abstract void notifyWathers();
    /**
     * Obtaining the level of water pollution
     */
    public abstract int getPolluteLevel();

}

WaterQuality - Specific water quality monitoring object

/**
 * Specific water quality monitoring objects
 */
public class WaterQuality extends WaterQualitySubject {
    /**
     * Level of pollution, 0 means normal, 1 means mild pollution, 2 means moderate pollution, 3 means high pollution
     */
    private int polluteLevel = 0;

    /**
     * Obtaining the level of water pollution
     */
    @Override
    public int getPolluteLevel() {
        return polluteLevel;
    }

    public void setPolluteLevel(int polluteLevel) {
        this.polluteLevel = polluteLevel;
        this.notifyWathers();
    }

    /**
     * Notify the corresponding observer object
     */
    @Override
    public void notifyWathers() {
        //Registered observer where loop is located
        for (WatcherObserver watcher: observers){
            //Start judging whether notifications are needed based on pollution levels, which are controlled here
            if (this.polluteLevel >=0 ){
                //Notify monitors for records
                if (("Monitors").equals(watcher.getJob())){
                    watcher.update(this);
                }
            }
            if (this.polluteLevel >=1 ){
                //Notify early Warners
                if (("Early Warning Personnel").equals(watcher.getJob())){
                    watcher.update(this);
                }
            }
            if (this.polluteLevel >=2 ){
                //Notify supervisor department leader
                if (("Head of Monitoring Department").equals(watcher.getJob())){
                    watcher.update(this);
                }
            }

        }
    }

}

WatcherObserver

public interface WatcherObserver {
    /**
     * Notified Method
     * @param subject
     */
    public void update(WaterQualitySubject subject);
    /**
     * Set up the post of an observer
     */
    public void setJob(String job);
    /**
     * Obtain the position of an observer
     */
    public String getJob();


}

Watcher

public class Watcher  implements WatcherObserver{
    private String job;

    @Override
    public void update(WaterQualitySubject subject) {
        //This is pulling
        System.out.println(job+"Notification was obtained that the current pollution level is:" + subject.getPolluteLevel());
    }

    @Override
    public void setJob(String job) {
        this.job = job;
    }

    @Override
    public String getJob() {
        return this.job;
    }
}

Test

public class Test {
    public static void main(String[] args) {
        //Create Water Quality Theme Object
        WaterQuality subject = new WaterQuality();
        //Create several observers
        WatcherObserver watcher1 = new Watcher();
        watcher1.setJob("Monitors");
        WatcherObserver watcher2 = new Watcher();
        watcher2.setJob("Early Warning Personnel");
        WatcherObserver watcher3 = new Watcher();
        watcher3.setJob("Head of Monitoring Department");
        //Register Observers
        subject.attach(watcher1);
        subject.attach(watcher2);
        subject.attach(watcher3);
        //Fill in the water quality report
        System.out.println("When the water quality is normal-----------");
        subject.setPolluteLevel(0);
        System.out.println("When the water quality is slightly polluted-----------");
        subject.setPolluteLevel(1);
        System.out.println("When the water quality is moderately polluted-----------");
        subject.setPolluteLevel(2);
    }
}

Run result:

You can see that different observers are notified according to the alert level. The main logic is in the target object implementation class, and in the judgment of if, it is a more clever way to write, not if.else if..., but multiple if.Combine if, learn from it, and use it for reference in the future.

2. How to achieve the observer mode without relying on an abstract observer:

The examples above all have the role of an abstract observer whose target object manipulates the abstract observer directly.If you don't want to use an abstract observer, consider the following:

  • 1. We create a new abstract observer class, which is provided by others. We can just do that. Here we can use the observer mode that comes with java. He has helped us automatically provide abstract observers and abstract target classes. We can just use them directly according to his rules.
    • Here's an example of using the observer pattern that comes with java:
  • 2. The work of registering observers and notifying observers is delegated to a third party, decoupling the target and observers. There are many ways to achieve this, the main idea is to reflect the delegation.

Here are four examples:

  • Reflective delegation implements the second example above. In the course of watching nba and animation, the teacher comes and reacts differently.
  • Examples include: an example that mimics how swing components work (in particular, an observer can observe multiple target objects)
  • Example of listener implementing observer mode in spring
  • springboot uses eventBus provided by the Guava framework to implement an example of event handling.

1. Examples of using the observer mode that comes with java

java provides an abstract observer Observer, an abstract target object Observable, and the method name that notifies the observer must be update.The setChange() method must be invoked before notification, with the following code:

Specific Target Class (Observed)

/**
 * Title: GPer
 * Description: JDK Provides an implementation of the observer, the observer
 *
 * @author hfl
 * @version V1.0
 * @date 2020-06-03
 */
public class GPer extends Observable {
    private String name = "GPer Ecosphere";
    private static GPer gper = null;

    private GPer() {
    }

    public static GPer getInstance(){
        if(null == gper){
            gper = new GPer();
        }
        return gper;
    }

    public void publishQuestion(Question question){
        System.out.println(question.getUserName() + "stay" + this.name + "A question was submitted on.");
        setChanged();
        notifyObservers(question);
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

An auxiliary class, a business class that has nothing to do with the observer pattern: Question

/**
 * Title: Question
 * Description: TODO
 *
 * @author hfl
 * @version V1.0
 * @date 2020-06-03
 */
public class Question {
    //Questioner
    private String userName;
    //Ask Questions
    private String content;

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }
}

Specific observer class: Teacher

public class Teacher implements Observer {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Teacher(String name) {
        this.name = name;
    }

    @Override
    public void update(Observable o, Object arg) {
        GPer gper = (GPer)o;
        Question question = (Question)arg;
        System.out.println("===============================");
        System.out.println(name + "Hello, teacher!\n" +
                "You received a message from" + gper.getName() + ""I hope you can answer the following questions:\n" +
                question.getContent() + "\n" +
                "Questioner:" + question.getUserName());
    }
}

Test class:

public class ObserverTest {
    public static void main(String[] args) {
        GPer gper = GPer.getInstance();
        Teacher tom = new Teacher("Tom");
        Teacher mic = new Teacher("Mic");

        //This is because there is no @Tom teacher
        Question question = new Question();
        question.setUserName("Xiao Ming");
        question.setContent("What scenarios does the observer design pattern apply to?");
        gper.addObserver(tom);
        gper.addObserver(mic);
        gper.publishQuestion(question);
    }
}

Run result: Viewing the results, it perfectly demonstrates the realization that the target object notifies all observers.

2. Reflective delegation implements the second example above, where students react differently depending on the teacher's arrival.

Specific code:

/**
 * Encapsulation class for event objects
 *
 * @author Administrator
 */
public class Event {
    //Object to execute method   
    private Object object;
    //Method name to execute   
    private String methodName;
    //Parameters to execute method   
    private Object[] params;
    //Parameter type of method to execute   
    private Class[] paramTypes;

    public Event() {

    }

    public Event(Object object, String methodName, Object... args) {
        this.object = object;
        this.methodName = methodName;
        this.params = args;
        contractParamTypes(this.params);
    }

    //Generate an array of parameter types from an array of parameters   
    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 Object getObject() {
        return object;
    }

    //Several get and set methods are omitted here

    /**
     * Execute the method using reflection mechanism based on the object's method name, method parameters
     *
     * @throws Exception
     */
    public void invoke() throws Exception {
        Method method = object.getClass().getMethod(this.getMethodName(), this.getParamTypes());
        if (null == method) {
            return;
        }
        method.invoke(this.getObject(), this.getParams());
    }


    public void setObject(Object object) {
        this.object = object;
    }

    public String getMethodName() {
        return methodName;
    }

    public void setMethodName(String methodName) {
        this.methodName = methodName;
    }

    public Object[] getParams() {
        return params;
    }

    public void setParams(Object[] params) {
        this.params = params;
    }

    public Class[] getParamTypes() {
        return paramTypes;
    }

    public void setParamTypes(Class[] paramTypes) {
        this.paramTypes = paramTypes;
    }
}

EventHandler

/**
 * Title: EventHandler
 * Description: Handler of the event
 *
 * @author hfl
 * @version V1.0
 * @date 2020-06-05
 */
public class EventHandler {
    //Is a List
    private List<Event> objects;

    public EventHandler(){
        objects=new ArrayList<Event>();
    }
    //Add events to be executed by an object and required parameters
    public void addEvent(Object object,String methodName,Object...args){
        objects.add(new Event(object,methodName,args));
    }
    //Notifies all objects to perform the specified event
    public void notifyX() throws Exception{
        for(Event e : objects){
            e.invoke();
        }
    }
}

Notifier's abstract class

public abstract class Notifier {
    private EventHandler eventHandler = new EventHandler();

    public EventHandler getEventHandler() {
        return eventHandler;
    }

    public void setEventHandler(EventHandler eventHandler) {
        this.eventHandler = eventHandler;
    }

    /**
     * Increase the number of students who need help on the lookout
     *
     * @param object     Object to execute method
     * @param methodName Method name of execution method
     * @param args       Parameters for executing methods
     */
    public abstract void addListener(Object object, String methodName,  Object... args);

    /**
     * Tell all the students who want to help the sentry: The teacher is here
     */
    public abstract void notifyX();
}

Notifier GoodNotifier

public class GoodNotifier extends Notifier {

    @Override
    public void addListener(Object object, String methodName, Object... args) {
        System.out.println("New classmates have entrusted responsible senders!");
        EventHandler handler = this.getEventHandler();
        handler.addEvent(object, methodName, args);
    }

    @Override
    public void notifyX() {
        System.out.println("The responsible sentry told all the students who needed help that the teacher was coming");
        try{
            this.getEventHandler().notifyX();
        }catch(Exception e){
            e.printStackTrace();
        }
    }

WatchCartoonListener

/**
 * Title: WatchCartoonListener
 * Description:  Specific listener (observer)
 *
 * @author hfl
 * @version V1.0
 * @date 2020-06-05
 */
public class WatchCartoonListener extends GoodNotifier {

    public WatchCartoonListener() {
        System.out.println("WatchCartoonListener I'm reading a comic book, starting at:"+ LocalDateTime.now().toString());
    }

    public void stopPlayingGame(Date date){
        System.out.println("WatchCartoonListener  Stop reading comics. End time:"+ new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(date));
    }
}

WatchingNBAListener

public class WatchingNBAListener extends GoodNotifier {
    public WatchingNBAListener() {
        System.out.println("WatchingNBAListener I'm watching NBA,The start time is: " + LocalDateTime.now().toString());
    }
    public void stopWatchingTV(Date date){
        System.out.println("WatchingNBAListener Quick shutdown NBA Live, ending at:" +  new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(date));
    }
}

Test class:

public class Test {
    public static void main(String[] args) {
        //Create a responsible sender
        Notifier goodNotifier = new GoodNotifier();

//Create a pupil to play games and start playing them
        WatchCartoonListener playingGameListener = new WatchCartoonListener();

//Create a classmate who watches TV and start watching TV
        WatchingNBAListener watchingTVListener = new WatchingNBAListener();
//The students playing games told the sentry that the teacher came to tell them
        goodNotifier.addListener(playingGameListener, "stopPlayingGame", new Date());
//The classmates watching TV tell the sentry that the teacher has come to tell them
        goodNotifier.addListener(watchingTVListener, "stopWatchingTV", new Date());
        try {
            //After a while
            Thread.sleep(1000);
        } catch (Exception e) {
            e.printStackTrace();
        }
//The teacher appears and the sender notifies all the classmates to help: The teacher is here
        goodNotifier.notifyX();


    }
}

Run result:

public class Test {
    public static void main(String[] args) {
        //Create a responsible sender
        Notifier goodNotifier = new GoodNotifier();

//Create a pupil to play games and start playing them
        WatchCartoonListener playingGameListener = new WatchCartoonListener();

//Create a classmate who watches TV and start watching TV
        WatchingNBAListener watchingTVListener = new WatchingNBAListener();
//The students playing games told the sentry that the teacher came to tell them
        goodNotifier.addListener(playingGameListener, "stopPlayingGame", new Date());
//The classmates watching TV tell the sentry that the teacher has come to tell them
        goodNotifier.addListener(watchingTVListener, "stopWatchingTV", new Date());
        try {
            //After a while
            Thread.sleep(1000);
        } catch (Exception e) {
            e.printStackTrace();
        }
//The teacher appears and the sender notifies all the classmates to help: The teacher is here
        goodNotifier.notifyX();


    }
}

Run result:

Event Delegation Mechanism Analysis 1. The sender is completely unaware of the existence of the gamer and is completely decoupled.(Of course, the credit goes to Event and EventHandler, which are generic) 2. When the teacher arrives, the player stops playing and returns to his seat. The NBA player stops watching the NBA, the comic book stops watching the comic book, the game stops playing.(One notification, different methods performed) 3. Extensibility is very high. Another student who plays basketball writes a basketball student class first and tells the sentry in the test code that it is OK to do so. The sender has not changed at all.Good reuse

Looking at this example, it's much easier to look at the swing component listening example again, because it works exactly the same way, with events and event handlers managing and calling observers.

3. Examples of swing component listening

Look at the code specifically:

This is a powerful example of how a delegated registered observer and an observer's method correspond to a specific method of a target class, from method to method.Understand, learn and strive for the following in your project: Event

public class Event {
    //Event source, who initiated the event and saved it
    private Object source;
    //Event triggered, who to notify
    private Object target;
    //Event trigger, what action to do, callback
    private Method callback;
    //The name of the event, what triggered it
    private String trigger;
    //The time at which the event was triggered
    private long time;

    public Event(Object target, Method callback) {
        this.target = target;
        this.callback = callback;
    }

    public Event setSource(Object source) {
        this.source = source;
        return this;
    }

    public Event setTime(long time) {
        this.time = time;
        return this;
    }
    public Event setTrigger(String trigger) {
        this.trigger = trigger;
        return this;
    }
    public Object getSource() {
        return source;
    }


    public long getTime() {
        return time;
    }

    public Object getTarget() {
        return target;
    }

    public Method getCallback() {
        return callback;
    }

    @Override
    public String toString() {
        return "Event{" + "\n" +
                "\tsource=" + source.getClass() + ",\n" +
                "\ttarget=" + target.getClass() + ",\n" +
                "\tcallback=" + callback + ",\n" +
                "\ttrigger='" + trigger + "',\n" +
                "\ttime=" + time + "'\n" +
                '}';
    }
}

EventLisenter

public class EventLisenter {
    //Lisenter at the bottom of the JDK is typically designed like this
    protected Map<String, Event> events = new HashMap<String, Event>();

    //Event name and a target object to trigger the event
    public void addLisenter(String eventType, Object target) {
        try {
            this.addLisenter(
                    eventType,
                    target,
                    target.getClass().getMethod("on" + toUpperFirstCase(eventType), Event.class));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void addLisenter(String eventType, Object target, Method callback) {
        //Register Events
        events.put(eventType, new Event(target, callback));
    }


    //Trigger, trigger whenever there is an action
    private void trigger(Event event) {
        event.setSource(this);
        event.setTime(System.currentTimeMillis());

        try {
            //Initiate callback
            if (event.getCallback() != null) {
                //Call its callback function with reflection
                event.getCallback().invoke(event.getTarget(), event);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //Event name trigger
    protected void trigger(String trigger) {
        if (!this.events.containsKey(trigger)) {
            return;
        }
        trigger(this.events.get(trigger).setTrigger(trigger));
    }

    //Private method of logical processing, initial capitalization
    private String toUpperFirstCase(String str) {
        char[] chars = str.toCharArray();
        chars[0] -= 32;
        return String.valueOf(chars);
    }

}

Mouse

public class Mouse extends EventLisenter {

    public void click(){
        System.out.println("Call Click Method");
        this.trigger(MouseEventType.ON_CLICK);
    }

    public void doubleClick(){
        System.out.println("Call double-click method");
        this.trigger(MouseEventType.ON_DOUBLE_CLICK);
    }

    public void up(){
        System.out.println("Call the pop-up method");
        this.trigger(MouseEventType.ON_UP);
    }

    public void down(){
        System.out.println("Call press method");
        this.trigger(MouseEventType.ON_DOWN);
    }

    public void move(){
        System.out.println("Call Move Method");
        this.trigger(MouseEventType.ON_MOVE);
    }

    public void wheel(){
        System.out.println("Call scroll method");
        this.trigger(MouseEventType.ON_WHEEL);
    }

    public void over(){
        System.out.println("Call hover method");
        this.trigger(MouseEventType.ON_OVER);
    }

    public void blur(){
        System.out.println("Call Focus Method");
        this.trigger(MouseEventType.ON_BLUR);
    }

    public void focus(){
        System.out.println("Call defocus method");
        this.trigger(MouseEventType.ON_FOCUS);
    }
}

MouseEventCallback

/**
 * Self-written logic for callbacks
 * Created by Tom.
 */
public class MouseEventCallback {

    public void onClick(Event e){
        System.out.println("===========Trigger mouse click event==========" + "\n" + e);
    }

    public void onDoubleClick(Event e){
        System.out.println("===========Trigger mouse double-click event==========" + "\n" + e);
    }

    public void onUp(Event e){
        System.out.println("===========Trigger mouse-up event==========" + "\n" + e);
    }

    public void onDown(Event e){
        System.out.println("===========Trigger mouse-down event==========" + "\n" + e);
    }

    public void onMove(Event e){
        System.out.println("===========Trigger Mouse Move Event==========" + "\n" + e);
    }

    public void onWheel(Event e){
        System.out.println("===========Trigger mouse scroll event==========" + "\n" + e);
    }

    public void onOver(Event e){
        System.out.println("===========Trigger mouse hover event==========" + "\n" + e);
    }

    public void onBlur(Event e){
        System.out.println("===========Trigger mouse defocus event==========" + "\n" + e);
    }

    public void onFocus(Event e){
        System.out.println("===========Trigger mouse focus event==========" + "\n" + e);
    }

}

MouseEventType

public interface MouseEventType {
    //Single click
    String ON_CLICK = "click";

    //double-click
    String ON_DOUBLE_CLICK = "doubleClick";

    //Bounce
    String ON_UP = "up";

    //Press
    String ON_DOWN = "down";

    //move
    String ON_MOVE = "move";

    //Roll
    String ON_WHEEL = "wheel";

    //hover
    String ON_OVER = "over";

    //Defocus
    String ON_BLUR = "blur";

    //Focusing
    String ON_FOCUS = "focus";
}

MouseEventTest

public class MouseEventTest {
    public static void main(String[] args) {

        MouseEventCallback callback = new MouseEventCallback();

        Mouse mouse = new Mouse();

        //@Who?@Callback Method
        mouse.addLisenter(MouseEventType.ON_CLICK,callback);
        mouse.addLisenter(MouseEventType.ON_FOCUS,callback);

        mouse.click();

        mouse.focus();


    }
}
public class Keybord extends EventLisenter {

    public void down(){

    }

    public void up(){

    }

}

Run result:

4. Example of listener implementing observer mode in spring

Spring's event mechanism uses observer mode.In this mode, a target object manages all observer objects that depend on it and actively notifies when its own state changes.This is usually done by calling the methods provided by each observer.This pattern is often used to implement event processing systems. Each listener in Spring is equivalent to an observer.event events are equivalent to objects, observers, and containers are used to manage and register observers and publish events.

The specific demo code is as follows:

Event class: OrderEvent is equivalent to the target class

public class OrderEvent extends ApplicationEvent {

    public OrderEvent(Object source) {
        super(source);
    }
}

OrderSmsListener is equivalent to an observer

@Component
public class OrderSmsListener implements ApplicationListener<OrderEvent> {
    @Override
    public void onApplicationEvent(OrderEvent orderEvent) {
        System.out.println("orderSmsListener receive event from " + orderEvent.getSource());
    }
}

Business Class:

@Service
public class OrderService {

    @Autowired
    private ApplicationContext applicationContext;


    public void order() {
        applicationContext.publishEvent(new OrderEvent("orderService"));
    }
}

In addition, the spring container is equivalent to a delegate class. Test:

@RunWith(SpringRunner.class)
@SpringBootTest
public class PatternApplicationTest {

    @Autowired
    private OrderService orderService;

    @Test
    public void contextLoads() {
    }


    @Test
    public void testOrder() {
        orderService.order();
    }

}

Run result: Shows that once an event is published, listening allows you to observe it and do more.

4. Integrate Google's Guava in springboot to enable subscription publishing via eventBus

EventBus does not need to implement complex events, listeners, publishers.Previously, we talked about class-oriented, now: Guava is a face-to-face method, which is more powerful.A solution to easily see patterns on the ground.

Demonstrate an example: Packages introducing Guava:

<dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>20.0</version>
        </dependency>

EventBus Event Bus

//api packaging
public class MyEventBus {

    /** Event Task Bus */
    private final static EventBus tiemEventBus = new EventBus();
    /**
     * Trigger Synchronization Event
     *
     * @param event
     */
    public static void post(Object event) {
        tiemEventBus.post(event);
    }
    /**
     * Register event handlers
     *
     * @param handler
     */
    public static void register(Object handler) {
        tiemEventBus.register(handler);
    }
    /**
     * Log off event handler
     *
     * @param handler
     */
    public static void unregister(Object handler) {
        tiemEventBus.unregister(handler);
    }
}

Message Entity Class

public class Message {
    private MessageType messageType;
    private String messageContent;

    public Message(MessageType messageType, String messageContent) {
        this.messageType = messageType;
        this.messageContent = messageContent;
    }
    public MessageType getMessageType() {
        return messageType;
    }
    public void setMessageType(MessageType messageType) {
        this.messageType = messageType;
    }
    public String getMessageContent() {
        return messageContent;
    }
    public void setMessageContent(String messageContent) {
        this.messageContent = messageContent;
    }

    public enum MessageType {
        OPENDOOR(1, "openDoor"),
        CLOSEDOOR(2,"closeDoor");
        private int code;
        private String value;

        MessageType(int code, String value) {
            this.code = code;
            this.value = value;
        }
        public int getCode() {
            return code;
        }
        public void setCode(int code) {
            this.code = code;
        }
        public String getValue() {
            return value;
        }
        public void setValue(String value) {
            this.value = value;
        }
        }
}

TestListener

@Component
abstract class MyApplicationListener implements ApplicationListener<ApplicationPreparedEvent> {
    /**
     *  ApplicationPreparedEvent Context Preparation Event
     * @param applicationPreparedEvent
     */
    @Override
    public void onApplicationEvent(ApplicationPreparedEvent applicationPreparedEvent) {
        ConfigurableApplicationContext applicationContext = applicationPreparedEvent.getApplicationContext();
        MyApplicationListener bean = applicationContext.getBean(this.getClass());
        System.out.println("regist listener to eventBus...."+bean);
        MyEventBus.register(bean);
    }
}

Subscribers (that is, listeners) inherit to MyApplicationListener.

@Component
public class MyListentenerSubscribe extends MyApplicationListener{
    @Subscribe
    public void on(Message message){
        System.out.println("subscribe message->  messgeType: "+message.getMessageType()+"\n messageContent: "+message.getMessageContent());
    }
}

Test:

@RestController
public class EventPublishCtrl extends LogBase {
    @GetMapping("/publish")
    public void publishEvent() {
        log.info("this publish method...");
        MyEventBus.post(new Message(Message.MessageType.OPENDOOR,"Sesame Open!"));
    }
}

Start the project and then call the publishing method:

Subscribers receive specific message types and message content.

3. Essence of the Observer Model

The basic classical structure of the observer mode is mainly described above; introductory demo; two ways to use it; distorted writings of the observer mode; encapsulated usage of the observer mode in java;Do not rely on abstract observer methods, such as reflective delegation, swing using observer, listener observer mode implementation in spring, eventBus observer mode in springboot. Finally, let's talk about the nature of observer mode.

Since then, the observer mode has been finished. In fact, there may be some examples of adding mq in the follow-up, but we haven't studied in depth yet. Let's start with this.

Reference article: https://blog.csdn.net/gdutxiaoxu/article/details/51824769 https://blog.csdn.net/fw19940314/article/details/100010397 https://www.cnblogs.com/wkzhao/p/10229283.html

Personal WeChat Public Number: Search: Be angry every day Push related articles from time to time, and look forward to growing with you!!

finish

This article is distributed by blogs and other operating tool platforms OpenWrite Release

Tags: Spring Java SpringBoot JDK

Posted on Fri, 05 Jun 2020 10:05:18 -0700 by wilku