观察者模式和Spring的结合

简介:     这周给分了一个任务,就是对查询回来的数据进行各种各样的过滤,有七种不同的过滤条件。过滤条件是在数据库中存着的。在我们项目中有一个热发,就是定时的从数据库中把数据取出来进行分类保存到Property中或者Map中。

    这周给分了一个任务,就是对查询回来的数据进行各种各样的过滤,有七种不同的过滤条件。过滤条件是在数据库中存着的。在我们项目中有一个热发,就是定时的从数据库中把数据取出来进行分类保存到Property中或者Map中。所以一开始想的一个笨的方法就是把七种不同的过滤条件热发到七个不同的Map中去。然后再定义一个过滤的类,所有的查询回来的数据都要经过这个类的处理。
    后来想了想,这样做的话,不利于扩展,要是后期还有其他的过滤的话,耦合性太强了。所以这个时候就想到了设计模式中的观察者模式。应用在这个场景下再合适不过了。定义了七个Filter,当热发执行之后,通知所有的观察者来我这拿最新的数据。而且当新添一个新的过滤的过滤条件的话,只需要新加一个过滤的类,并在spring的监听器中配置上该类就可以了,其实这就实现了对内修改关闭,对外扩展。 下面试具体的代码实现。先贴一张图,很经典。

这里写图片描述

被观察者


package com.flight.inter.otaadapter.filters;

import java.util.ArrayList;
import java.util.List;

/**
 * 观察者模式抽象通知者类--报价拦截
 * Created by ling.zhang on 2016/12/2.
 */
public abstract class AbstractPriceFilter {
    private List<IPriceFilterListener> listeners=new ArrayList<IPriceFilterListener>();

    public void registerListener(List<IPriceFilterListener> listener){
        this.listeners=listener;
    }

    public void notifyListenner(){
        for(int i=0;i<listeners.size();i++){
            IPriceFilterListener priceFilterListener=listeners.get(i);
            priceFilterListener.actionPerformed();
        }
    }
}

    在这个地方需要注意的是,registerListener是需要有注册者的,你总不用说有通知者但是没有被通知者,那时间长了通知者不得倒闭啦,哈哈。在这是通过spring来注册的,就不用在代码中写了,要不然每来一个观察者都写注册方法。我是注册了多个,所以用的是List,如果只有一个的话,不用List,具体看你怎么注册了。当在来一个新的观察者的时候,只需要在list下在新加一个ref就可以注册进去了。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
  http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
  http://www.springframework.org/schema/context
  http://www.springframework.org/schema/context/spring-context-3.2.xsd">


    <bean id="divCabinFilter" class="com.flight.inter.otaadapter.filters.DivCabinFilter"/>
    <bean id="divFilter" class="com.flight.inter.otaadapter.filters.DivFilter"/>
    <bean id="flightFilter" class="com.flight.inter.otaadapter.filters.FlightFilter"/>
    <bean id="flightGroupFilter" class="com.flight.inter.otaadapter.filters.FlightGroupFilter"/>
    <bean id="operatingCarrierFilter" class="com.flight.inter.otaadapter.filters.OperatingCarrierFilter"/>
    <bean id="shareCarriersFilter" class="com.flight.inter.otaadapter.filters.ShareCarriersFilter"/>
    <bean id="validatingCarrierFilter" class="com.flight.inter.otaadapter.filters.ValidatingCarrierFilter"/>

    <bean id="hotDeployManager" class="com.flight.inter.otaadapter.manage.HotDeployManager"/>

    <bean id="priceFilterListener" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
        <property name="targetObject">
            <ref local="hotDeployManager"/>
        </property>
        <property name="targetMethod">
            <value>registerListener</value>
        </property>

        <property name="arguments">
            <list>
                <ref bean="divCabinFilter"/>
                <ref bean="divFilter"/>
                <ref bean="flightFilter"/>
                <ref bean="flightGroupFilter"/>
                <ref bean="operatingCarrierFilter"/>
                <ref bean="shareCarriersFilter"/>
                <ref bean="validatingCarrierFilter"/>
            </list>

        </property>
    </bean>
</beans>

    上边的是抽象通知者,具体的可以看下子类。子类会去调用通知的方法。下面是个样例。

public class HotDeployManager extends AbstractPriceFilter
{
    //满足你的条件时,去通知观察者们
    notifyListenner();
}

    

观察者


    定义了一个接口先。

public interface IPriceFilterListener {
    void actionPerformed();
}

    然后是具体的实现类。用一个来做个示范。通知者通知到该类的时候,这个类就回去得到自己想要的数据。

public class DivCabinFilter implements IPriceFilterListener{
    private static final Logger logger = LoggerFactory.getLogger(DivCabinFilter.class);

    static Map<String,Map<String,String>> divCabinMap=new HashMap<>();

    @Override
    public void actionPerformed(){
        Map<String,String> map=HotDeployManager.getPriceFilter("divCabin");

        if (map!=null){
            Set set=map.entrySet();
            Map<String,Map<String,String>> divCabinGetMap=new HashMap<>();
            for (Iterator iterator=set.iterator();iterator.hasNext();){
                Map.Entry entry=(Map.Entry)iterator.next();
                String configKey=(String)entry.getKey();
                String divCabin=(String)entry.getValue();
                Map<String,String> forbidresult=forbidDivCabin(divCabin);
                divCabinGetMap.put(configKey,forbidresult);
            }
            divCabinMap=divCabinGetMap;
        }
    }
}

    很多的知识不是会了就会了,在自己的脑子里存着是一回事,能在特定的业务场景下能用上是另一回事。有些知识没用时觉得难,但是用过了之后就觉得真的不是很难。多实践。

相关文章
|
前端开发 Java Spring
异步事务?关于异步@Async + 事务@Transactional的结合使用问题分析【享学Spring MVC】(下)
异步事务?关于异步@Async + 事务@Transactional的结合使用问题分析【享学Spring MVC】(下)
|
9月前
|
设计模式 Java Spring
Spring 观察者模式详解以及自定义监听器扩展实现(下)
Spring 观察者模式详解以及自定义监听器扩展实现(下)
78 0
|
9月前
|
存储 Java Spring
Spring 观察者模式详解以及自定义监听器扩展实现(上)
Spring 观察者模式详解以及自定义监听器扩展实现
97 0
|
消息中间件 安全 JavaScript
小家Spring】从Spring中的(ApplicationEvent)事件驱动机制出发,聊聊【观察者模式】【监听者模式】【发布订阅模式】【消息队列MQ】【EventSourcing】...(中)
小家Spring】从Spring中的(ApplicationEvent)事件驱动机制出发,聊聊【观察者模式】【监听者模式】【发布订阅模式】【消息队列MQ】【EventSourcing】...(中)
|
NoSQL Java Redis
如何结合spring和redis进行优雅的轮询
如何结合spring和redis进行优雅的轮询
|
消息中间件 网络协议 Java
ActiveMQ系列:结合Spring,基于配置文件的使用ActiveMQ
从activemq脚本可以看出启动ActiveMQ实际是启动,bin文件夹下的其实activemq.jar 包中有一个类为Main,这就是active的启动入口,Main主要是加载lib目录和ClassPath,初始化 类加载器,委托给ShellCommand,由ShellCommand根据命令描述去执行,如果是Version和HELP, 则打印信息,若是启动命令,则通过XBeanBrokerFactory创建BrokerService
123 0
ActiveMQ系列:结合Spring,基于配置文件的使用ActiveMQ
|
XML 安全 Java
jasypt与Spring结合使用解决配置文件中数据库密码加密问题
jasypt与Spring结合使用解决配置文件中数据库密码加密问题
407 0
jasypt与Spring结合使用解决配置文件中数据库密码加密问题
|
设计模式 Java Spring
Spring Boot Event 观察者模式,轻松带你实现业务解耦!
Spring Boot Event 观察者模式,轻松带你实现业务解耦!
168 0
Spring Boot Event 观察者模式,轻松带你实现业务解耦!
|
Java 数据库连接 Spring
java面试题:如何通过HibernateDaoSupport将Spring和Hibernate结合起来?
java面试题:如何通过HibernateDaoSupport将Spring和Hibernate结合起来?
java面试题:如何通过HibernateDaoSupport将Spring和Hibernate结合起来?
|
Java Spring
结合CompletableFuture与Spring的Sleuth结合工具类与allOf
结合CompletableFuture与Spring的Sleuth结合工具类与allOf