设计模式-观察者模式

观察者模式观察者模式( Observer Pattern),又叫发布-订阅( Publish/ Subscribe)模式、模型-视图( Model/View)模式、源/监听器( Source/ ( Listener)模式或从属者( Dependents)模式。定义种一对多的依赖关系,一个主题对象可被多个观察者对象同时监听,使得每当主题对象状态变化时,所有依赖于它的对象都会得到通知并被自动更新。属于行为型模式。

观察者模式的核心是将观察者与被观察者解耦,以类似于消息/∫广播发送的机制联动两者,使被观察者的变动能通知到感兴趣的观察者们,从而做出相应的响应。

使用观察者模式设计鼠标事件响应API:

package com.lx.designPattern.observerpattern.mouseevent.core;

import java.lang.reflect.Method;

/**
 * @program: People
 * @description: 被观察者事件
 * @author: liu wei ping
 * @create: 2022-05-22 10:59
 */
public class Event {

    //事件源,动作是由谁发出的
    private Object source;
    //事件出发,要通知谁(观察者)
    private EventListener target;
    //观察者给的回应
    private Method callback;
    //事件的名称
    private String trigger;
    //事件的出发时间
    private long  time;

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

    public Object getSource() {
        return source;
    }

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

    public EventListener getTarget() {
        return target;
    }

    public Event setTarget(EventListener target) {
        this.target = target;
        return this;
    }

    public Method getCallback() {
        return callback;
    }

    public Event setCallback(Method callback) {
        this.callback = callback;
        return this;
    }

    public String getTrigger() {
        return trigger;
    }

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

    public long getTime() {
        return time;
    }

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

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


package com.lx.designPattern.observerpattern.mouseevent.core;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * @program: People
 * @description: 事件内容 被观察者的抽象
 * @author: liu wei ping
 * @create: 2022-05-22 11:00
 */
public 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) {
                //用反射调用回调函数
                event.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));
    }


}


package com.lx.designPattern.observerpattern.mouseevent.core;

/**
 * @program: People
 * @description: 观察者
 * @author: liu wei ping
 * @create: 2022-05-22 11:00
 */
public interface EventListener {

}
package com.lx.designPattern.observerpattern.mouseevent.handler;

import com.lx.designPattern.observerpattern.mouseevent.core.EventContext;

/**
 * @program: People
 * @description: 鼠标单击
 * @author: liu wei ping
 * @create: 2022-05-22 11:01
 */
public class Mouse extends EventContext {

    public void click(){
        System.out.println("调用单击方法");
        this.trigger(MouseEventType.ON_CLICK);
    }

    public void doubleClick(){
        System.out.println("调用双击方法");
        this.trigger(MouseEventType.ON_DOUBLE_CLICK);
    }

    public void up(){
        System.out.println("调用弹起方法");
        this.trigger(MouseEventType.ON_UP);
    }

    public void down(){
        System.out.println("调用按下方法");
        this.trigger(MouseEventType.ON_DOWN);
    }

    public void move(){
        System.out.println("调用移动方法");
        this.trigger(MouseEventType.ON_MOVE);
    }

    public void wheel(){
        System.out.println("调用滚动方法");
        this.trigger(MouseEventType.ON_WHEEL);
    }

    public void over(){
        System.out.println("调用悬停方法");
        this.trigger(MouseEventType.ON_OVER);
    }

    public void blur(){
        System.out.println("调用获焦方法");
        this.trigger(MouseEventType.ON_BLUR);
    }

    public void focus(){
        System.out.println("调用失焦方法");
        this.trigger(MouseEventType.ON_FOCUS);
    }

}

package com.lx.designPattern.observerpattern.mouseevent.handler;

import com.lx.designPattern.observerpattern.mouseevent.core.Event;
import com.lx.designPattern.observerpattern.mouseevent.core.EventListener;

/**
 * @program: People
 * @description: 鼠标事件观察者
 * @author: liu wei ping
 * @create: 2022-05-22 11:02
 */
public class MouseEventListener implements EventListener {

    public void onClick(Event e){
        System.out.println("===========触发鼠标单击事件==========" + "\n" + e);
    }

    public void onDoubleClick(Event e){
        System.out.println("===========触发鼠标双击事件==========" + "\n" + e);
    }

    public void onUp(Event e){
        System.out.println("===========触发鼠标弹起事件==========" + "\n" + e);
    }

    public void onDown(Event e){
        System.out.println("===========触发鼠标按下事件==========" + "\n" + e);
    }

    public void onMove(Event e){
        System.out.println("===========触发鼠标移动事件==========" + "\n" + e);
    }

    public void onWheel(Event e){
        System.out.println("===========触发鼠标滚动事件==========" + "\n" + e);
    }

    public void onOver(Event e){
        System.out.println("===========触发鼠标悬停事件==========" + "\n" + e);
    }

    public void onBlur(Event e){
        System.out.println("===========触发鼠标失焦事件==========" + "\n" + e);
    }

    public void onFocus(Event e){
        System.out.println("===========触发鼠标获焦事件==========" + "\n" + e);
    }
}
package com.lx.designPattern.observerpattern.mouseevent.handler;

/**
 * @program: People
 * @description: 鼠标事件类型
 * @author: liu wei ping
 * @create: 2022-05-22 11:02
 */
public interface MouseEventType {
    //单击
    String ON_CLICK = "click";

    //双击
    String ON_DOUBLE_CLICK = "doubleClick";

    //弹起
    String  ON_UP = "up";

    //按下
    String  ON_DOWN = "down";

    //移动
    String  ON_MOVE = "move";

    //滚动
    String ON_WHEEL = "wheel";

    //悬停
    String ON_OVER = "over";

    //失焦
    String ON_BLUR = "blur";

    //获焦
    String ON_FOCUS = "focus";

}
package com.lx.designPattern.observerpattern.mouseevent;

import com.lx.designPattern.observerpattern.mouseevent.core.EventListener;
import com.lx.designPattern.observerpattern.mouseevent.handler.Mouse;
import com.lx.designPattern.observerpattern.mouseevent.handler.MouseEventListener;
import com.lx.designPattern.observerpattern.mouseevent.handler.MouseEventType;

/**
 * @program: People
 * @description: 观察者测试类
 * @author: liu wei ping
 * @create: 2022-05-22 11:30
 */
public class Test {
    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();
    }

}

观察者测试类测试效果如下图:

观察者模式的优缺点

优点:

1、观察者和被观察者是松耦合(抽象耦合)的,符合依赖倒置原则

2、分离了表示层(观家者)和数据逻辑层(被观察者),并月建立了一套触发机制,使得数据的变化可以响应到多个表示层上;

3、实现了一对多的通讯机制,支持事件注册机制,支持兴趣分发机制,当被观察者触发事件时,只有感兴趣的观察者可以接收到通知

缺点:

1、如果观察者数量过多,则事件通知会耗时较长

2、事件通知呈线性关系,如果其中一个观察者处理事件卡壳,会影响后续的观察者接收该事件

3、如果观察者和被观察者之间存在循环依赖,则可能造成两者之间的循环调用,导致系统崩溃。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值