设计模式-07 观察者模式

1.什么是观察者模式

在对象之间定义了一对多的依赖,这样一来,当一个对象改变状态,依赖它的对象会收到通知并自动更新。
其实就是发布订阅模式,发布者发布信息,订阅者获取信息,订阅了就能收到信息,没订阅就收不到信息。

2.观察者模式应用场景

  • Zookeeper事件通知节点
  • 消息订阅通知
  • 安卓开发事件注册
  • 分布式配置中心

3.观察者模式原理类图

观察者类图

  • 抽象被观察者角色:也就是一个抽象主题,它把所有对观察者对象的引用保存在一个集合中,每个主题都可以有任意数量的观察者。抽象主题提供一个接口,可以增加和删除观察者角色。一般用一个抽象类和接口来实现。
  • 抽象观察者角色:为所有的具体观察者定义一个接口,在得到主题通知时更新自己。
  • 具体被观察者角色:也就是一个具体的主题,在集体主题的内部状态改变时,所有登记过的观察者发出通知。
  • 具体观察者角色:实现抽象观察者角色所需要的更新接口,一边使本身的状态与制图的状态相协调。

4.观察者模式简单的实现

4.1 抽象主题

public interface AbstractSubject {
    /**
     * 添加观察者  注册观察者
     */
    void addObServer(ObServer obServer);
    /**
     * 移除观察者
     *
     * @param obServer
     */
    void removeServer(ObServer obServer);
    /**
     * 通知消息
     */
    void notifyObServer(String message);
}

4.2 抽象观察者

public interface ObServer {
    /**
     * 通知观察者消息
     *
     * @param message
     */
    void update(String message);
}

4.3 具体主题

public class WeChatSubject implements AbstractSubject {
    /**
     * 如何存放这些主题
     * @param obServer
     */
    private List<ObServer> obServerList = new ArrayList<ObServer>();
    public void addObServer(ObServer obServer) {
        // 注册或者添加观察者
        obServerList.add(obServer);
    }

    public void removeServer(ObServer obServer) {
        obServerList.remove(obServer);
    }
    public void notifyObServer(String message) {
        System.out.println("开始设置微信群发消息:" + message);
        // 调用观察者通知方案
        for (int i = 0; i < obServerList.size(); i++) {
            ObServer obServer = obServerList.get(i);
            // 调用该方法通知 获取具体的消息  群发
            obServer.update(message);
        }
    }
}

4.4 具体观察者

public class UserObServer implements ObServer {
    private String name;

    public UserObServer(String name) {
        this.name = name;
    }

    public void update(String message) {
        System.out.println(name + ",收到微信服务通知的消息:" + message);
    }
}

4.5 测试方法

public class SimpleTest {
    public static void main(String[] args) {
        // 1.创建具体的在主题
        AbstractSubject abstractSubject = new WeChatSubject();
        // 2.开始注册或者添加观察者
        abstractSubject.addObServer(new UserObServer("aric"));
        abstractSubject.addObServer(new UserObServer("ann"));
        // 3.群发消息
        abstractSubject.notifyObServer("沐宇熙设计模式");
    }
}

5.JDK自带观察实现消息发送

  • Observable类追踪所有的观察者,并通知他们。
  • Observer这个接口看起来很熟悉,它和我们之前写的类几乎一样。

5.1 案例

用户下单成功后会发送短信、发送邮件、发送微信

5.1.1 具体主题

public class MessageObServable extends Observable {
    @Override
    public void notifyObservers(Object arg) {
        // 1.修改状态为可以群发
        setChanged();
        // 2.调用父类的notifyObservers 群发消息
        super.notifyObservers(arg);
    }
}

5.1.2 具体观察者

public class EmailObServer implements Observer {
    public void update(Observable o, Object arg) {
        System.out.println("用户下单成功,发送邮件提醒内容:" + arg);
    }
}
public class SmsObServer implements Observer {
    public void update(Observable o, Object arg) {
        System.out.println("用户下单成功,发送短信提醒内容:" + arg);
    }
}
public class WechatObServer implements Observer {
    public void update(Observable o, Object arg) {
        System.out.println("用户下单成功,发送微信体醒内容:" + arg);
    }
}

5.1.3 测试方法

public class TestJdkObServer {
    public static void main(String[] args) {
        // 1.创建具体的主题
        Observable observable = new MessageObServable();
        // 2. 注册观察者
        observable.addObserver(new SmsObServer());
        observable.addObserver(new WechatObServer());
        observable.addObserver(new EmailObServer());
        // 3.群发消息
        observable.notifyObservers("沐宇熙设计模式");
    }
}

6.Spring封装事件监听

Spring实现事件通知,底层才观察者模式封装的

6.1 添加依赖

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>
</dependencies>

6.2 主题类

@Data
public class OrderMessageEvent extends ApplicationEvent {
    /**
     * 群发消息的内容
     */
    private JSONObject jsonObject;

    /**
     * Create a new ApplicationEvent.
     * @param source the object on which the event initially occurred (never {@code null})
     */
    public OrderMessageEvent(Object source, JSONObject jsonObject) {
        super(source);
        this.jsonObject = jsonObject;
    }
}

6.3 具体监听类

@Component
public class EmailListener implements ApplicationListener<OrderMessageEvent> {
    @Override
    @Async
    public void onApplicationEvent(OrderMessageEvent event) {
        //如何获取到当前容器下面所有的观察者呢?反射机制获取ApplicationListener 接口下面子类
        System.out.println(Thread.currentThread().getName()+"开始发送邮件消息内容:" + JSONUtil.toJsonStr(event.getJsonObject()));
    }
@Component
public class SmsListener implements ApplicationListener<OrderMessageEvent> {
    @Override
    @Async
    public void onApplicationEvent(OrderMessageEvent event) {
        System.out.println(Thread.currentThread().getName() + "开始短信消息内容:" + JSONUtil.toJsonStr(event.getJsonObject()));
    }
}

6.4 控制类

@RestController
public class OrderController {
    @Autowired
    private ApplicationContext applicationContext;

    @RequestMapping("/sendMsg")
    public String sendMsg() {
        //1.定义发送消息内容
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("email", "599982811@qq.com");
        jsonObject.put("phone", "18888888888");
        jsonObject.put("text", "设计模式");
        OrderMessageEvent orderMessageEvent = new OrderMessageEvent(this, jsonObject);
        applicationContext.publishEvent(orderMessageEvent);
        return "success";
    }
}

6.5 启动类

@SpringBootApplication
@EnableAsync
public class AppObServer {
    public static void main(String[] args) {
        SpringApplication.run(AppObServer.class);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值