【设计模式】观察者模式

观察者模式

上周公司内部的培训讲到了微服务的注册中心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源码来学习观察者模式.....

posted @ 2020-06-29 23:35  ShinyRou  阅读(126)  评论(0编辑  收藏  举报