鬼谷子的魔方

导航

设计模式-实践-工厂模式

前言

这篇博客的目的是对项目中偶尔碰到的应用设计模式的代码积累一下。

 

我认为针对于设计模式的学习,通过看书、看例子只能了解概念,而重要的是如何把概念应用到实际的项目开发中。

而且我想提醒大家的是,学习设计模式时,千万不要拘泥于书上的内容,形成定式思维,这样对于其他源码理解会出现一层自然屏障,理解起来很困难。

大家在看JDK源码和Spring源码时会发现,很少照搬书上的内容,都是灵活运用。

 

这也是我计划写这类博客的原因,希望通过项目中的实际需求去理解,并应用设计模式!

 

开篇之作--简单工厂模式的应用

 

需求:我们项目中有个消费记录解析上传的功能,我们需要给客户端开发一个接口。客户端调用接口,将多条消费记录以参数传入接口,然后接口

解析参数中的数据,并将数据存储到数据库中。项目中存在多种业务,一种业务对应一种解析规则,以后还可能会新加业务类型。

 

分析:针对于这个需求,如果没有学习过设计模式,可能这样实现。第一种,项目当前有4种业务,那么就写4个接口,一个接口实现一种解析规则,

客户端根据不同的规则调用不同的接口;第二种,改进些,那么就给客户端暴漏一个接口,客户端将类型传入接口,方法中根据类型调用不同的解析规则。

那么第一种方法的问题是什么呢?项目有4种业务写4个接口,如果有10个业务就写10个接口,这些接口实现的业务功能又是一样的,那么这是很明显

的代码重复,接口冗余,成功的给项目重构挖了一个坑。

第二种方法呢,确实解决了上面说的问题,但是实现上又导致了接口对规则的依赖,所以也是不可取的。

那么我们项目中是如何实现的呢?请往下看…

 

项目实现:

注:代码主要表达思想,大家不要抠具体的类名、标签名等等,主要理解实现思路,本人以前就经常犯钻牛角尖的毛病!

1、首先是暴漏给客户端的接口

public class ConsumeHistoryAction extends BaseExecutableAction{

    private Logger logger = LoggerFactory.getLogger(this.getClass());
    
    @Autowired
    private ConsumeHistoryService consumeHistoryService;
    
    @Autowired
    private TransDetailResolverFactory transDetailResolverFactory;
    
    public void upload(Map map) throws CoreException{
        //  获取业务类型
        String type = map.get(“type”);

        // 获取要解析的数据
        String data = map.get(“data”);

        // 根据业务类型获取解析规则类(一个业务类型对应一个解析类)
        TransDetailResolver resolver = transDetailResolverFactory.getResolver(type);

        if(resolver==null){
            logger.error("No TransDetailResolver defined for {}", type);
            return;
        }

        // 解析数据,将数据放到一个实体类中
        ConsumeHistory consumeRecord = resolver.resolver(data);

        // 保存数据到数据库
        consumeHistoryService.upload(consumeRecords);
    }
}

 

2、解析工厂类的实现

public class TransDetailResolverFactory {

    // 通过spring配置,将具体的业务类型与解析规则类的对应关系注入进来
    // 这样就有效避免了工厂类和规则类之间的依赖
    private Map<String,TransDetailResolver> resolvers = new HashMap<String,TransDetailResolver>();
    
    public interface TransDetailResolver {
        
        public ConsumeHistory resolver(String str);
    }
    
    public void setResolvers(Map<String, TransDetailResolver> resolvers) {
        this.resolvers = resolvers;
    }

    public TransDetailResolver getResolver(String aid){
        // 其实这块依赖的处理,也可以通过反射来实现
         TransDetailResolver resolver = resolvers.get(aid);
        return resolver;
    }
    
}

 

 

3、依赖关系的配置

<x:bean class="com.xxx.TransDetailResolverFactory">
    <x:property name="resolvers">
        <x:map>
            // 本项目的业务类型其实是一串CODE码
            <x:entry key="1001">
                <x:bean class="com.xxx.consumehistory.aaaResolver">
                </x:bean>
            </x:entry>
            <x:entry key="1002">
                <x:bean class="com.xxx.consumehistory.bbbResolver">
                </x:bean>
            </x:entry>
            <x:entry key="1003">
                <x:bean class="com.xxx.consumehistory.cccResolver">
                </x:bean>
            </x:entry>
        </x:map>
    </x:property>
</x:bean>

 

4、解析规则类的实现

这个我就不具体上代码了,就是根据具体的业务规则实现代码的解析规则就可以了。

特别注意的是,这个类一定要实现工厂类中的接口,为什么要实现?这个问题留给阅读的同学思考吧!嘿嘿嘿!

 

总结:以上就是具体的实现思路了,虽然简单,但是代码结构很清晰,如果未来要加一种业务类型,只需要创建对应的解析规则类,再修改下配置

文件就搞定了,其他的代码都不需要改动。

首篇博客,废话较多,以后会直接上干货!!!

有哪些不足,请大家多多指点!!!

posted on 2016-05-04 14:48  鬼谷子的魔方  阅读(344)  评论(0)    收藏  举报