zoukankan      html  css  js  c++  java
  • 【设计模式】观察者模式

    观察者模式

    上周公司内部的培训讲到了微服务的注册中心Eureka的部分源码,在实例的注册和注销到Eureka的过程中很多都是用到了观察者模式,监听Spring容器的初始化与销毁事件,来触发Eureka Client更新实例的相关信息到Eureka Server。
    所以决定来复习下观察者模式。

    定义:观察者模式是一种行为设计模式,也称为监听器模式,允许提供一种发布订阅的机制,当发布者的状态发生改变,就会提醒所有的订阅者。

    现实生活中的例子:

    商店 与 顾客
    顾客想要关注某件商品是否到货,需要一直去商店查看
    或者是商家在商品到货之后 就要对关注该商品的顾客进行消息推送。

    思路:
    商店 需要维护 关注商品的顾客信息 以及商品的数量
    并且提供新的顾客进行注册的方法,以及老顾客注销的方法
    在商品到货时对所有进行关注的顾客进行消息推送

    对这个模式进行抽象就得到
    商店 称为 发布者 Publisher,在属性改变时通知订阅者
    顾客 称为 订阅者 Subscribers,监听发布者的某种属性或者状态

    每个订阅者,接受到通知后的行为并不一致,可以定义一个通用的接口,来实现发布者与订阅者的解耦

    所有的订阅者实现Subscriber接口,实现update方法,进行自己的业务处理逻辑

    商店中还有不同的商品,为了维护不同的商品,与不同的订阅者的关系
    可以再抽象出一个事件处理器,用于维护订阅者与事件的关联关系,并进行消息提醒。

    顾客的实现

      //顾客接口
    public interface Customer {
        void update();
    }
    
    //想买苹果的顾客
    public class AppleCustomer implements Customer{
        @Override
        public void update() {
            System.out.println("AppleCustomer:爷要马上去买苹果");
        }
    }
    
    //想买书的顾客
    public class BookCustomer  implements Customer{
        @Override
        public void update() {
            System.out.println("BookCustomer:今天有点懒了 明天再买书吧");
        }
    }
    
    

    事件处理器实现

    public class EventManager {
        public Map<String, ArrayList<Customer>> customers = new HashMap<>();
    
        //初始化 事件与监听器集合
        public EventManager(String... operations) {
            for (String operation : operations) {
                this.customers.put(operation, new ArrayList<>());
            }
        }
    
        //监听者注册
        public void subscribe(String eventType,Customer customer){
            ArrayList<Customer> customerArrayList =  customers.get(eventType);
            if(customerArrayList == null){
                customerArrayList = new ArrayList<>();
                customers.put(eventType,customerArrayList);
            }
            customerArrayList.add(customer);
        }
    
        //监听者取消注册
        public void unsubscribe(String eventType,Customer customer){
            ArrayList<Customer> customerArrayList =  customers.get(eventType);
            if(customerArrayList !=null ){
                customerArrayList.remove(customer);
            }
        }
    
        //消息通知
        public void notify(String eventType){
            ArrayList<Customer> customerArrayList =  customers.get(eventType);
            for(Customer customer:customerArrayList){
                customer.update();
            }
        }
    }
    

    商店的实现

    public class Shop {
        private EventManager eventManager;//事件处理器
        private Integer bookCounts = 0;//书的数量
        private Integer appleCounts = 0;//苹果数量
    
    
        public Shop(EventManager eventManager) {
            this.eventManager = eventManager;
        }
    
        public void applePurchase(Integer appleCounts){
            //苹果进货了
            this.appleCounts += appleCounts;
            System.out.println("商店到了"+appleCounts+"斤苹果");
            eventManager.notify("apples");
        }
    
        public void bookPurchase(Integer bookCounts){
            this.bookCounts += bookCounts;
            System.out.println("商店到了"+bookCounts+"本书");
            eventManager.notify("books");
        }
    
        public static void main(String[] args) {
            //初始化事件处理器
            EventManager eventManager = new EventManager("apples","books");
            //初始化商店
            Shop shop = new Shop(eventManager);
            //初始化顾客
            AppleCustomer appleCustomer = new AppleCustomer();
            BookCustomer bookCustomer = new BookCustomer();
            //事件注册
            eventManager.subscribe("apples",appleCustomer);
            eventManager.subscribe("books",bookCustomer);
            //还就那个进货
            shop.applePurchase(20);
            shop.bookPurchase(1);
        }
    }
    

    后续将会结合部分Eureka源码来学习观察者模式.....

  • 相关阅读:
    MYSQL读写分离
    AIR loadbytes executable code error 解决办法
    文本处理常用命令
    使用awk找出两个大文件的相同部分
    nginx修改php.ini无效的解决办法
    python 正则表达式反向引用的问题
    解决memcached错误:Catastrophic: event fd doesn't match conn fd
    php编译iconv错误解决办法
    grep剔除两个文件中相同部分
    周末闲话
  • 原文地址:https://www.cnblogs.com/shinyrou/p/13211143.html
Copyright © 2011-2022 走看看