设计模式之观察者模式

观察者模式是我现在公司用的很广泛的一种设计模式,同时也十分好用,下面我推荐给大家

首先我们要明白为什么需要观察者模式,我们举个例子分析。比如我们电商系统有一个商品改名了,那么如果会触发下面逻辑

我们用代码实现如下

public class ObserverDemo {
    public static void main(String[] args) {
        ObserverDemo o = new ObserverDemo();
        o.itemChangeName();
    }

    public void itemChangeName() {
        System.out.println("商品改名成功");
        changeOrderItemName();
        log();
    }

    public void changeOrderItemName() {
        System.out.println("订单相关商品改名成功");
    }

    public void log() {
        System.out.println("记录操作日志");
    }
}

执行结果如下

在这里插入图片描述

这样写看似没什么问题,某一天产品经理突然说,商品改名需要把采购单据的相关商品名称也要同步修改,那么我们在itemChangeName 方法里又要进行修改,添加修改采购单相关方法。这样就违反了设计原则中的开闭原则。

public class ObserverDemo {
    public static void main(String[] args) {
        ObserverDemo o = new ObserverDemo();
        o.itemChangeName();
    }

    public void itemChangeName() {
        System.out.println("商品改名成功");
        changeOrderItemName();
        changePurchaseOrderItemName();
        log();
    }

    public void changeOrderItemName() {
        System.out.println("订单相关商品改名成功");
    }

    public void changePurchaseOrderItemName() {
        System.out.println("采购相关商品改名成功");
    }

    public void log() {
        System.out.println("记录操作日志");
    }
}

有没有什么办法可以不修改这个方法呢,我们引入本期主题–观察者模式
我先画个图让大家看下观察者模式是怎么实现的

看着是不是跟消息队列有点像,其实消息队列也是用了观察者模式的思想。
我们用代码实现下定义事件接口及实现类

/**
 * @program: DesignPatternsDemo
 * @description: 事件接口
 * @author: chunri
 * @create: 2022-08-16 17:49
 **/
public interface EventListener {
    
    void doEvent();

    String getEventName();
}

/**
 * @program: DesignPatternsDemo
 * @description: 订单商品名称修改事件监听
 * @author: chunri
 * @create: 2022-08-16 17:49
 **/
public class OrderChangeItemNameListener implements EventListener {
   @Override
    public void doEvent() {
        changeOrderItemName();
    }

    @Override
    public String getEventName() {
        return "item.change.name";
    }

    public void changeOrderItemName() {
        System.out.println("订单相关商品改名成功");
    }
}

/**
 * @program: DesignPatternsDemo
 * @description: 采购商品名称修改事件监听
 * @author: chunri
 * @create: 2022-08-16 17:51
 **/
public class PurchaseChangeItemNameListener implements EventListener{

    @Override
    public void doEvent() {
        changePurchaseOrderItemName();
    }

    @Override
    public String getEventName() {
        return "item.change.name";
    }

    public void changePurchaseOrderItemName() {
        System.out.println("采购相关商品改名成功");
    }

}

/**
 * @program: DesignPatternsDemo
 * @description: 记录日志
 * @author: chunri
 * @create: 2022-08-16 17:52
 **/
public class LogListener implements EventListener{
     @Override
    public void doEvent() {
        log();
    }

    @Override
    public String getEventName() {
        return "item.change.name";
    }

    public void log() {
        System.out.println("记录操作日志");
    }
}

事件核心处理

/**
 * @program: DesignPatternsDemo
 * @description: 事件处理
 * @author: chunri
 * @create: 2022-08-16 20:30
 **/
public class EventHandler {

     Map<String, List<EventListener>> listeners = new HashMap<>();

    /**
     * 订阅
     * @param listener  监听
     */
    public void subscribe(EventListener
            listener) {
        List<EventListener> users = listeners.computeIfAbsent(listener.getEventName(), k -> new ArrayList<>());
        users.add(listener);
    }

    /**
     * 通知
     * @param eventType 事件类型
     */
    public void notify(String eventType) {
        List<EventListener> users = listeners.get(eventType);
        for (EventListener listener : users) {
            listener.doEvent();
        }
    }
}

我们执行main方法执行结果跟老方法相同。这样如果后续商品改名需要同步修改采购单的商品名称,我们只需要再增加一个事件实现类添加进去就ok了,无需修改代码,这样遵从了开闭原则

/**
 * @program: DesignPatternsDemo
 * @description: 观察者模式
 * @author: chunri
 * @create: 2022-08-16 17:47
 **/
public class ObserverDemo2 {
    
     private static final String ITEM_CHANGE_NAME = "item.change.name";
    private EventHandler eventManager;

    public ObserverDemo2() {
        eventManager = new EventHandler();
        eventManager.subscribe(new OrderChangeItemNameListener());
        eventManager.subscribe(new PurchaseChangeItemNameListener());
        eventManager.subscribe(new LogListener());
    }
    
    public static void main(String[] args) {
        ObserverDemo2 o = new ObserverDemo2();
        o.itemChangeName();
    }

    public void itemChangeName() {
        System.out.println("商品改名成功");
        eventManager.notify(ITEM_CHANGE_NAME);
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值