观察者模式和Spring的结合

这周给分了一个任务,就是对查询回来的数据进行各种各样的过滤,有七种不同的过滤条件。过滤条件是在数据库中存着的。在我们项目中有一个热发,就是定时的从数据库中把数据取出来进行分类保存到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;
        }
    }
}

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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏我杨某人的青春满是悔恨

走进 RxSwift 之观察者模式

RxSwift 是 ReactiveX 系列的 Swift 版本,如果你之前用过 ReactiveCocoa(RAC) 的话,想必对 Functional Re...

1872
来自专栏社区的朋友们

理解 B+ 树算法

最近有接触到 b+ 树,花了点时间,顺便总结梳理下方便后续翻阅;时间仓促,且文中多是个人的理解,仅供参考。

9790
来自专栏黄Java的地盘

[翻译]WebSocket协议第二章——Conformance Requirements

本文为WebSocket协议的第二章,本文翻译的主要内容为WebSocket协议中相关术语的介绍。

871
来自专栏JAVA高级架构开发

Java 11 正式发布,这 8 个逆天新特性教你写出更牛逼的代码

美国时间 09 月 25 日,Oralce 正式发布了 Java 11,这是据 Java 8 以后支持的首个长期版本。

2150
来自专栏木木玲

ConcurrentHashMap (JDK7) 详解

3719
来自专栏我就是马云飞

LruCache源码解析

 今天我们来聊聊缓存策略相关的内容,LruCache应该说是三级缓存策略会使用到的内存缓存策略。今天我们就来扒一扒这里面的原理,同时也温故温故我们的数据结构方面...

2287
来自专栏Android 研究

OKHttp源码解析(五)--OKIO简介及FileSystem

okio是由square公司开发的,它补充了java.io和java.nio的不足,以便能够更加方便,快速的访问、存储和处理你的数据。OKHttp底层也是用该库...

1862
来自专栏jeremy的技术点滴

Java开发小技巧_02

4224
来自专栏FreeBuf

小白都能看懂的JSON反序列化远程命令执行

前言 Fastjson是一个由阿里巴巴维护的一个json库。它采用一种“假定有序快速匹配”的算法,是号称Java中最快的json库。Fastjson接口简单易...

4484
来自专栏大内老A

[ASP.NET MVC]通过对HtmlHelper扩展简化“列表控件”的绑定

在众多表单元素中,有一类<select>元素用于绑定一组预定义列表。传统的ASP.NET Web Form中,它对应着一组重要的控件类型,即ListContro...

1935

扫码关注云+社区

领取腾讯云代金券