This article is excerpted from This is How Design Patterns should Be Learned

1 Implement notification mechanism based on Java API

When a user answers a question in the community, the user will receive an email notification. This is an application scenario of the Observer mode. Some people might think of MQ, asynchronous queues, etc., but the JDK itself provides such apis. To restore such an application scenario in code, we first create a GPer class.


/** * the JDK provides an implementation of the observer, observed */
public class GPer extends Observable{
    private String name = "GPer ecosphere";
    private static GPer gper = null;
    private GPer(a){}

    public static GPer getInstance(a){
        if(null == gper){
            gper = new GPer();
        }
        return gper;
    }
    public String getName(a) {
        return name;
    }
    public void publishQuestion(Question question){
        System.out.println(question.getUserName() + "In" + this.name + "A question was submitted on."); setChanged(); notifyObservers(question); }}Copy the code

Then create the Question class.


public class Question {
    private String userName;
    private String content;

    public String getUserName(a) {
        return userName;
    }

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

    public String getContent(a) {
        return content;
    }

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

Then create the Teacher class.


public class Teacher implements Observer {

    private String name;

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

    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 have received a letter from + gper.getName() + "I hope you will answer the question. The question reads as follows: \n" +
                   question.getContent() + "\n" + "Questioner:"+ question.getUserName()); }}Copy the code

Finally write the client test code.


    public static void main(String[] args) {
        GPer gper = GPer.getInstance();
        Teacher tom = new Teacher("Tom");
        Teacher jerry = new Teacher("Jerry");

        gper.addObserver(tom);
        gper.addObserver(jerry);

        // User behavior
        Question question = new Question();
        question.setUserName("Zhang");
        question.setContent("What scenarios does the observer model apply to?");

        gper.publishQuestion(question);
}

Copy the code

The running result is shown in the figure below.

Easy landing observer mode based on Guava API

I recommend a very useful framework for implementing the Observer pattern with a very simple API, starting with the introduction of Maven dependencies, for example.


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

Copy the code

Then create the listening event GuavaEvent.


/** * Created by Tom */
public class GuavaEvent {
    @Subscribe
    public void subscribe(String str){
        // Business logic
        System.out.println(Execute the subscribe method, passing in the argument:+ str); }}Copy the code

Finally write the client test code.



/** * Created by Tom */
public class GuavaEventTest {
    public static void main(String[] args) {
        EventBus eventbus = new EventBus();
        GuavaEvent guavaEvent = new GuavaEvent();
        eventbus.register(guavaEvent);
        eventbus.post("Tom"); }}Copy the code

Design the mouse event response API using the observer pattern

Then design a business scenario to help your friends better understand the observer model. The observer mode is also used extensively in JDK source code. For example, java.awt.Event is one of the observer patterns, but Java is rarely used to write desktop programs. Let’s use code to implement this, to help you understand more deeply the implementation principle of the observer mode. First, create the EventListener interface.


/** * Created by Tom. */
public interface EventListener {}Copy the code

Create the Event class.



/** * Created by Tom. */
public class Event {
    // The event source, by whom the action was issued
    private Object source;
    // The event is triggered, and who should be notified (the observer)
    private EventListener target;
    // Observer's response
    private Method callback;
    // The event name
    private String trigger;
    // The event that triggered the event
    private long time;

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

    public Object getSource(a) {
        return source;
    }

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

    public String getTrigger(a) {
        return trigger;
    }

    public Event setTrigger(String trigger) {
        this.trigger = trigger;
        return this;
    }

    public long getTime(a) {
        return time;
    }

    public Event setTime(long time) {
        this.time = time;
        return this;
    }

    public Method getCallback(a) {
        return callback;
    }

    public EventListener getTarget(a) {
        return target;
    }

    @Override
    public String toString(a) {
        return "Event{" +
                "source=" + source +
                ", target=" + target +
                ", callback=" + callback +
                ", trigger='" + trigger + '\' ' +
                ", time=" + time +
                '} '; }}Copy the code

Create the EventContext class.


/** * Created by Tom. */
public abstract class EventContext {
    protected Map<String,Event> events = new HashMap<String,Event>();

    public void addListener(String eventType, EventListener target, Method callback){
        events.put(eventType,new Event(target,callback));
    }

    public void addListener(String eventType, EventListener target){
        try {
            this.addListener(eventType, target, 
target.getClass().getMethod("on"+toUpperFirstCase(eventType), Event.class));
        }catch (NoSuchMethodException e){
            return; }}private String toUpperFirstCase(String eventType) {
        char [] chars = eventType.toCharArray();
        chars[0] - =32;
        return String.valueOf(chars);
    }

    private void trigger(Event event){
        event.setSource(this);
        event.setTime(System.currentTimeMillis());

        try {
            if(event.getCallback() ! =null) {
                // Call the callback function with reflectionevent.getCallback().invoke(event.getTarget(), event); }}catch(Exception e){ e.printStackTrace(); }}protected void trigger(String trigger){
        if(!this.events.containsKey(trigger)){return; } trigger(this.events.get(trigger).setTrigger(trigger)); }}Copy the code

Then create the MouseEventType interface.


/** * Created by Tom. */
public interface MouseEventType {
    / / click
    String ON_CLICK = "click";

    / / double
    String ON_DOUBLE_CLICK = "doubleClick";

    / / bounce
    String ON_UP = "up";

    / / press
    String ON_DOWN = "down";

    / / move
    String ON_MOVE = "move";

    / / rolling
    String ON_WHEEL = "wheel";

    / / hover
    String ON_OVER = "over";

    // Lose focus
    String ON_BLUR = "blur";

    // Get focus
    String ON_FOCUS = "focus";
}

Copy the code

Create the Mouse class.


/** * Created by Tom. */
public class Mouse extends EventContext {

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

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

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

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

    public void move(a){
        System.out.println("Call the move method");
        this.trigger(MouseEventType.ON_MOVE);
    }

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

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

    public void blur(a){
        System.out.println("Call the focus method");
        this.trigger(MouseEventType.ON_BLUR);
    }

    public void focus(a){
        System.out.println("Call out-of-focus methods");
        this.trigger(MouseEventType.ON_FOCUS); }}Copy the code

Create the callback method MouseEventLisenter class.


/** * Created by Tom. */
public class MouseEventListener implements EventListener {


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

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

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

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

    public void onMove(Event e){
        System.out.println("=========== trigger mouse movement 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 out-of-focus event ==========" + "\n" + e);
    }

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

Finally write the client test code.


    public static void main(String[] args) {
        EventListener listener = new MouseEventListener();

        Mouse mouse = new Mouse();
        mouse.addListener(MouseEventType.ON_CLICK,listener);
        mouse.addListener(MouseEventType.ON_MOVE,listener);

        mouse.click();
        mouse.move();
    }
		
Copy the code

Pay attention to “Tom play architecture” reply to “design pattern” can obtain the complete source code.

Tom play architecture: 30 real cases of design patterns (attached source code), the challenge of annual salary 60W is not a dream

This article is “Tom play structure” original, reproduced please indicate the source. Technology is to share, I share my happiness! If this article is helpful to you, welcome to follow and like; If you have any suggestions can also leave a comment or private letter, your support is my motivation to adhere to the creation. Pay attention to “Tom bomb architecture” for more technical dry goods!