美文网首页
观察者模式

观察者模式

作者: 奋斗的韭菜汪 | 来源:发表于2020-06-23 17:23 被阅读0次

生活中的场景:微信红点通知,手机起床闹钟
使用场景:1、当一个抽象模型包含两个方面内容,其中一个方面依赖于另一个方面;
2、其他一个或多个对象的变化依赖于另一个对象的变化
3、实现类似广播机制的功能,无需知道具体收听者,只需分发广播,系统中感兴趣的对象会自动接收该广播;
4、多层嵌套使用,形成一种链式触发机制,使得事件具备跨域(跨越两种观察者类型)通知
标准代码结构:抽象主题,具体主题,抽象观察者,具体观察者
具体主题(被观察者)会存储所有观察者,一旦主题发生变化,会逐一通知被观察者

jdk实现观察者模式:被观察者 extends Observable,观察者implements Observer

image.png
这里实现了Observer jdk会自动将观察者加入Vector<Observer>集合
例子:用户给社区老师提问的例子
public class Community extends Observable {
    private String name = "社区";
    private static final Community instance = new Community();
    private Community(){}
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public static Community getInstance(){
        return instance;
    }
    public void publishQuestion(Question question){
        System.out.println(question.getUsername() + "在" + this.name + "提交了一个问题!");
        setChanged();
        notifyObservers(question);
    }
}
public class Question {
    private String username;
    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;
    }
}
public class Teacher implements Observer {
    private String name;
    public Teacher(String name){
        this.name = name;
    }
    public void update(Observable o, Object arg) {
            Community community = (Community)o;
            Question question = (Question)arg;
        System.out.println("===============");
        System.out.println(name + "老师,你好\n" +
                "您收到了一个来自" + community.getName() +
                "的提问,希望您解答。问题内容为:" +
                question.getContent() +"\n" +
                "提问者:" + question.getUsername());
    }
}
public class Test {

    public static void main(String[] args) {
        Community community = Community.getInstance();
        Teacher tom = new Teacher("tom");
        Teacher lily = new Teacher("lily");
        community.addObserver(tom);
        community.addObserver(lily);
        Question question = new Question();
        question.setUsername("zhangsan");
        question.setContent("观察者模式使用场景是那些?");
        community.publishQuestion(question);
    }
}

运行结果

zhangsan在社区提交了一个问题!
===============
lily老师,你好
您收到了一个来自社区的提问,希望您解答。问题内容为:观察者模式使用场景是那些?
提问者:zhangsan
===============
tom老师,你好
您收到了一个来自社区的提问,希望您解答。问题内容为:观察者模式使用场景是那些?
提问者:zhangsan

Process finished with exit code 0

谷歌guava实现观察者模式(常用):

    <dependencies>
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>18.0</version>
        </dependency>
    </dependencies>
public class GuavaEvent {
    @Subscribe
    public  void observer1(Object o){
        System.out.println("执行observer1方法,传参为:" + o.toString());
    }
    @Subscribe
    public void observer2(Object o){
        System.out.println("执行observer2方法,传参为:" + o.toString());
    }
}
public class Test {
    public static void main(String[] args) {
        //消息总线
        EventBus eventBus = new EventBus();
        GuavaEvent guavaEvent = new GuavaEvent();
        eventBus.register(guavaEvent);

        eventBus.post("nihao ");
    }
}

结果

执行observer2方法,传参为:nihao 
执行observer1方法,传参为:nihao 

Process finished with exit code 0

手写一个观察者模式,并模拟鼠标点击事件
被观察者抽象

public class EventListener {
    //存储被观察者map
    protected Map<String, Event> events = new HashMap<String, Event>(16);
    public void addListener(String eventType, Object target, Method callback){
        events.put(eventType, new Event(target,callback));
    }
    //如果没有回调
    public void addListener(String eventType, Object target){
        try {
            //约定Event方法名已on开头
            this.addListener(eventType, target, target.getClass().getMethod("on" + toUpperFirstCase(eventType), Event.class));
            //events.put(eventType, new Event(target,callback));
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    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));

    }
}

具体被观察者

public class Mouse extends EventListener{

    public void click(){
        System.out.println("调用单机方法");
        this.trigger(MouseEventType.ON_CLICK);
    }
}
public class MouseEventCallback {
    //update
    public void onClick(Event e){
        System.out.println("触发鼠标单击事件");
    }
}
public class Event {
    //事件源,动作是由谁发出的
    private Object source;
    //事件触发,要通知谁(观察者)
    private Object target;
    //观察者给的回应
    private Method callback;
    //事件的名称
    private String trigger;
    //事件的时间
    private long time;

    public Event(Object 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 Object getTarget() {
        return target;
    }

    public Event setTarget(Object 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 +
                '}';
    }
}
public interface MouseEventType {
    String ON_CLICK = "click";
}
public class Test {
    public static void main(String[] args) {
        //具体观察者
        MouseEventCallback callback = new MouseEventCallback();
        //被观察者
        Mouse mouse = new Mouse();
        mouse.addListener(MouseEventType.ON_CLICK, callback);
        mouse.click();
    }
}

运行结果:

调用单机方法
触发鼠标单击事件

Process finished with exit code 0

相关文章

  • 11.9设计模式-观察者模式-详解

    设计模式-观察者模式 观察者模式详解 观察者模式在android中的实际运用 1.观察者模式详解 2.观察者模式在...

  • RxJava基础—观察者模式

    设计模式-观察者模式 观察者模式:观察者模式(有时又被称为发布(publish )-订阅(Subscribe)模式...

  • 前端面试考点之手写系列

    1、观察者模式 观察者模式(基于发布订阅模式) 有观察者,也有被观察者。 观察者需要放到被观察者列表中,被观察者的...

  • RxJava 原理篇

    一、框架思想 观察者模式观察者自下而上注入被观察者被观察者自上而下发射事件观察者模式 装饰器模式自上而下,被观察者...

  • 观察者模式

    观察者模式概念 观察者模式是对象的行为模式,又叫作发布-订阅(publish/subscrible)模式。 观察者...

  • 设计模式-观察者模式

    观察者模式介绍 观察者模式定义 观察者模式(又被称为发布-订阅(Publish/Subscribe)模式,属于行为...

  • 观察者模式

    观察者模式 观察者模式的定义 观察者模式(Observer Pattern)也叫做发布订阅模式(Publish/s...

  • iOS设计模式之观察者模式

    观察者模式 1、什么是观察者模式 观察者模式有时又被称为发布(publish)-订阅(Subscribe)模式、模...

  • 观察者模式和发布订阅模式区别

    观察者模式 所谓观察者模式,其实就是为了实现松耦合(loosely coupled)。 在观察者模式中,观察者需要...

  • RxJava(二)

    一、观察者模式 1.1、传统的观察者模式 1.2、RxJava 的观察者模式 区别传统的观察者模式是一个 Obse...

网友评论

      本文标题:观察者模式

      本文链接:https://www.haomeiwen.com/subject/nhkhfktx.html