浅谈JAVA设计模式之观察者模式

观察者模式 也叫做订阅发布模式。
观察者模式定义了对象之间的一对多依赖,让多个观察者对象同时监听一个主体对象,当主体对象发生变化时,它的所有依赖者都会收到通知并更新。

简单理解观察者模式

创建一个餐厅Kitchen.java(被观察类)

public class Kitchen extends Observable {

    private String name="天天中餐厅";
    private static Kitchen kitchen;
    private Kitchen(){}

    public String getName() {return this.name;}
    public static Kitchen getInstance() {
        if(kitchen != null) {
            return kitchen;
        }
        return new Kitchen();
    }

    public void dishOut(Food food) {
        System.out.println();
        System.out.println(name+"出菜了!菜名:"+food.getName()+";价格:"+food.getPrice()+";");
        setChanged();
        notifyObservers(food);
    }
}

创建服务员Waiter.java(观察者类)

public class Waiter implements Observer {

    private String name;
    public Waiter(String name) {
        this.name = name;
    }

    @Override
    public void update(Observable o, Object arg) {
        Food food = (Food) arg;
        if(food.getIsOut() == 0) {
            System.out.println("==================================================================");
            System.out.println("服务员"+this.name+"将"+food.getName()+"端到"+food.getNumber()+"号桌");
            food.setIsOut(1);
        }
    }
}

创建菜品类Food.java

public class Food {
    private String name;
    private double price;
    private int number;
    private int isOut = 0;

    public Food(String name, double price, int number) {
        this.name = name;
        this.price = price;
        this.number = number;
    }

    public int getIsOut() {
        return isOut;
    }

    public void setIsOut(int isOut) {
        this.isOut = isOut;
    }

    public int getNumber() {
        return number;
    }

    public void setNumber(int number) {
        this.number = number;
    }

    public String getName() {
        return name;
    }

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

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }
}

测试类

public static void main(String[] args) {
        Kitchen kitchen = Kitchen.getInstance();
        Food fish = new Food("酸菜鱼", 68.99, 200);
        Food tofu = new Food("麻辣豆腐", 18, 200);

        kitchen.addObserver(new Waiter("小王"));
        kitchen.dishOut(fish);
        kitchen.addObserver(new Waiter("小米"));
        kitchen.dishOut(tofu);
    }

输出结果

使用Guava快速搭建观察者模式

导入依赖

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>28.1-jre</version>
</dependency>

通过**@Subscribe**订阅消息

public class Waiter {

    private String name;
    public Waiter(String name) {
        this.name = name;
    }

    @Subscribe
    public void dishOut(Food food) {
        System.out.println("==================================================================");
        System.out.println("服务员"+this.name+"将"+food.getName()+"端到"+food.getNumber()+"号桌");
    }
}

测试类,通过EventBus消息总线类广播消息

public static void main(String[] args) {
    EventBus bus = new EventBus();
    bus.register(new Waiter("小东"));
    bus.register(new Waiter("小飞"));
    bus.post(new Food("酸菜鱼", 68.99, 200));
}

输出结果与JDK观察者模式类似
在这里插入图片描述

手写JS鼠标事件回调

Callback.java
通过callback接口钩子动态注册具体的事件回调函数。

public interface Callback {

    public void callback();
}

Event.java
事件类,管理回调函数以及事件源等信息。

public class Event {

    private Object source;
    private Object target;
    private Callback callback;
    private String trigger;
    private long time;

    public Event(Object target, Callback 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 this.source;
    }

    public String getTrigger() {
        return this.trigger;
    }

    public long getTime() {
        return this.time;
    }

    public Callback getCallback() {
        return this.callback;
    }
}

EventListener.java
定义监听类,通过events的Map去管理所有注册的监听事件。该类为监听事件管理的类。

public class EventListener {

    private Map<String, Event> events = new HashMap<>();

    public void addListener(Object target, String trigger, Callback callback) {
        addListener(trigger, new Event(target, callback));
    }

    public void addListener(String trigger, Event event) {
        events.put(trigger, event);
    }

    public void trigger(String trigger) {
        if(!events.containsKey(trigger)) throw new RuntimeException("Can't find callback...");
        events.get(trigger).getCallback().callback();
    }
}

MouseEventKey.java
事件监听key --对应-- 事件Event,重复注册监听事件会覆盖之前注册的事件。

public interface MouseEventKey {
    public static final String ON_CLICK = "click";
    public static final String ON_MOVE = "move";
    public static final String ON_BLUR = "blur";
    public static final String ON_DOUBLE_CLICK = "doubleclick";
}

Mouse.java
集成EventListener类,通过addListener方法注册鼠标监听事件。通过拓展方法调用具体的鼠标监听事件。

public class Mouse extends EventListener {

    public void addListener(Object target, String trigger, Callback callback) {
        super.addListener(target, trigger, callback);
    }

    public void click() {
        super.trigger(MouseEventKey.ON_CLICK);
    }

    public void move() {
        super.trigger(MouseEventKey.ON_MOVE);
    }

    public void doubleClick() {
        super.trigger(MouseEventKey.ON_DOUBLE_CLICK);
    }

    public void blur() {
        super.trigger(MouseEventKey.ON_BLUR);
    }
}

测试

public static void main(String[] args) {
        Mouse mouse = new Mouse();
        mouse.addListener(null, MouseEventKey.ON_CLICK, new Callback() {
            @Override
            public void callback() {
                System.out.println("mouse click callback...");
            }
        });

        mouse.addListener(null, MouseEventKey.ON_DOUBLE_CLICK, new Callback() {
            @Override
            public void callback() {
                System.out.println("mouse double click callback...");
            }
        });

        mouse.click();
        mouse.doubleClick();
        mouse.move();
}

输出结果
在这里插入图片描述
因为鼠标移动事件未注册监听事件,所以会报一个RuntimeException的异常错误。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值