ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

一起走进观察者模式

2022-01-09 16:03:09  阅读:156  来源: 互联网

标签:走进 void 观察者 模式 class baby new public


目录

一.介绍

观察者模式(Observer Pattern)属于行为型模式。定义了对象之间的一对多依赖,让多个观察者同时监听某一个主题对象,类似于广播机制,只需要分发广播,感兴趣的对象自动接收该广播。我们平常所说的Observer、Listener、Hook、Callback都和这个模式有关

二.场景约束

小孩(Baby)哭的时候会通知到爸爸(Dad)和妈妈(Mum),爸爸妈妈会对此采取不同的行为

三.UML类图

版本一
在这里插入图片描述
版本二
新增事件类将观察者与主题解耦,观察者可以根据不同的事件执行不同的操作,也可以直接对事件源进行操作
在这里插入图片描述

四.示意代码(版本一)

业务代码

//抽象观察者
public interface Observer {
    void action();
}

//抽象主题
abstract class Subject{
    protected List<Observer> observers = new ArrayList<>();

    public void addObserver(Observer observer) {
        observers.add(observer);
    }

    public void removeObserver(Observer observer) {
        observers.remove(observer);
    }

    public abstract void notifyObserver();
}

//具体主题-被观察者
class Baby extends Subject{
    @Override
    public void notifyObserver() {
        System.out.println("baby cry");
        observers.forEach(Observer::action);
    }
}

//具体观察者
class Dad implements Observer {
    @Override
    public void action() {
        System.out.println("dad feed baby");
    }
}

//具体观察者
class Mum implements Observer {
    @Override
    public void action() {
        System.out.println("mum hug baby");
    }
}

客户端

public class Client {
    public static void main(String[] args) {
        Baby baby = new Baby();
        baby.addObserver(new Mum());
        baby.addObserver(new Dad());
        baby.notifyObserver();
    }
}

五.示意代码(版本二)

//抽象观察者
public interface Observer {
    void action(Event event);
}

//抽象主题
abstract class Subject {
    protected List<Observer> observers = new ArrayList<>();

    public void addObserver(Observer observer) {
        observers.add(observer);
    }

    public void removeObserver(Observer observer) {
        observers.remove(observer);
    }

    public abstract void notifyObserver();
}

//具体主题-被观察者
class Baby extends Subject {
    @Override
    public void notifyObserver() {
        System.out.println("baby cry");
        CryEvent cryEvent = new CryEvent(new Date().getTime(), this);
        observers.forEach(observer -> observer.action(cryEvent));
    }
}

//抽象事件
abstract class Event {
    public abstract Object getSource();
}

//具体事件
class CryEvent extends Event {
    public long when;
    Baby source;

    public CryEvent(long when, Baby source) {
        this.when = when;
        this.source = source;
    }

    @Override
    public Baby getSource() {
        return source;
    }
}

//具体观察者
class Dad implements Observer {
    @Override
    public void action(Event event) {
        System.out.println("dad feed baby");
        if(event.getSource() instanceof Baby){
            System.out.println("dad对事件源进行处理");
        }
    }
}

//具体观察者
class Mum implements Observer {
    @Override
    public void action(Event event) {
        System.out.println("mum hug baby");
        if(event.getSource() instanceof Baby){
            System.out.println("mum对事件源进行处理");
        }
    }
}

客户端

public class Client {
    public static void main(String[] args) {
       Baby baby = new Baby();
       baby.addObserver(new Dad());
       baby.addObserver(new Mum());
       baby.notifyObserver();
    }
}

六.观察者模式与发布订阅模式

在这里插入图片描述
发布订阅模式

  • 发布者不会直接通知订阅者
  • 发布者与订阅者完全解耦

观察者模式

  • 主题要自己通知(notify)观察者
  • 主题与观察者松耦合

七.优点

  • 符合依赖倒置原则(观察者与主题都依赖于抽象)
  • 降低耦合(主题与观察者之间的耦合关系)

八.在JDK中的典型应用

在java.awt包下有很多观察者模式的身影,先来看下简单的UML类图
主题角色:java提供的组件类(以Button为例)
观察者角色:java提供的事件监听(各种Listener)
事件角色:鼠标事件、键盘事件等等
在这里插入图片描述
再来看看一个小demo
在窗口中添加一个按钮,给按钮添加上鼠标与键盘的相关事件,当点击按钮或者按下键盘的时候在控制台打印相应的语句

public class MainFrame extends JFrame {
    public MainFrame() throws HeadlessException {
        //定义一个具体主题
        Button button = new Button("click");

        //给主题添加观察者(鼠标监听)
        button.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                //MouseEvent就是具体事件
                System.out.println("按钮被点击");
            }
        });

        //给主题添加观察者(键盘监听)
        button.addKeyListener(new KeyAdapter() {
            @Override
            public void keyTyped(KeyEvent e) {
                //KeyEvent就是具体事件
                System.out.println("按下" + e.getKeyChar());
            }
        });

        add(button);
        setSize(100,100);
        this.setLocationRelativeTo(null);
        this.setVisible(true);
    }

    public static void main(String[] args) {
        new MainFrame();
    }
}

这里的KeyAdapter与MouseAdapter使用的是适配器模式

标签:走进,void,观察者,模式,class,baby,new,public
来源: https://blog.csdn.net/a347635191/article/details/122393104

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有