软件编程
位置:首页>> 软件编程>> java编程>> Java设计模式中的观察者模式

Java设计模式中的观察者模式

作者:非凡的小笨鱼  发布时间:2021-08-22 01:27:20 

标签:Java,观察者模式,设计模式

一.介绍

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

二.场景约束

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

三.UML类图

版本一

Java设计模式中的观察者模式

版本二

新增事件类将观察者与主题解耦,观察者可以根据不同的事件执行不同的操作,也可以直接对事件源进行操作

Java设计模式中的观察者模式

四.示意代码(版本一)

业务代码

//抽象观察者
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();
   }
}

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

Java设计模式中的观察者模式

发布订阅模式

  • 发布者不会直接通知订阅者

  • 发布者与订阅者完全解耦

观察者模式

  • 主题要自己通知(notify)观察者

  • 主题与观察者松耦合

七.优点

  • 符合依赖倒置原则(观察者与主题都依赖于抽象)

  • 降低耦合(主题与观察者之间的耦合关系)

八.在JDK中的典型应用

在java.awt包下有很多观察者模式的身影,先来看下简单的UML类图

主题角色:java提供的组件类(以Button为例) 观察者角色:java提供的事件监听(各种Listener) 事件角色:鼠标事件、键盘事件等等

Java设计模式中的观察者模式

再来看看一个小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使用的是适配器模式

来源:https://blog.csdn.net/a347635191/article/details/122393104

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com