职业IT人-IT人生活圈

 找回密码
 成为会员
搜索
查看: 754|回复: 6

(原创)Spring IOC和工厂模式联合使用简化工厂模式

[复制链接]
hxy 发表于 2011-9-2 11:34 | 显示全部楼层 |阅读模式
内容来源于本人博客园博客http://www.cnblogs.com/mypm/archive/2011/02/09/1950130.html
目录:
1:应用场景
2:传统工厂模式
3:传统工厂模式实现1中应用场景的弊端
4:IOC和工厂模式连合使用实现1中描述的场景


1:应用场景

    在MYPM的工作流业务中,有三种业务对像可以走工作流,分别为:文档,项目和工作任务;这三种业务对像在走工作流时,具体处理业务是有差别的,工作流引擎要根据不同的业务对像(文档,项目和工作任务),调用不同的处理器.

2:传统工厂模式
(1)简单工厂模式

用法:客户端利用SimpleFactory产生一个具体产品(用AbstractProduct引用),当然这需要客户端传参,但判断逻辑位于SimpleFactory中(如switch语句)。
扩展:若需要增加具体产品E,则须添加ConcreteProductE类,同时修改SimpleFactory。
修改:若需要修改具体产品A,则只需修改ConcreteProductA类。
(2)工厂方法模式

用法:客户端根据需要的产品选择工厂(实例化具体工厂A,用AbstractFactory引用),再用该工厂制造产品(用AbstractProduct引用)。
扩展:若需要增加具体产品E,则须添加ConcreteProductE类和ConcreteFactoryE。
修改:直接修改相应产品。
(3)抽象方法模式

用法:客户端根据需要的产品选择工厂(实例化具体工厂A,用AbstractFactory引用),再用该工厂制造产品(用AbstractProduct引用)。相比而言,抽象工厂模式的好处是易于转换产品的系列(如由A系列转换为B系列)。
扩展:若需要增加产品3A和3B,则除了要增加3个类外还要修改FactoryA和FactoryB。若需要增加产品系列C,除了增加相应的类外,还要增加FactoryC类。
修改:直接修改相应的类。
3:传统工厂模式实现1中应用场景的弊端
应用场景
  在MYPM的工作流业务中,有三种业务对像可以走工作流,分别为:文档,项目和工作任务;这三种业务对像在走工作流时,具体处理业务是有差别的,工作流引擎要根据不同的业务对像(文档,项目和工作任务),调用不同的处理器.


    在1中所描述场景,用简单工厂模式实现代码中会有很多if else 或是switch语句;用工厂方法模式或抽象方法模式实现时,会增加类。且看下面IOC和工厂模式连合使用后三种工厂模式(简单工厂模式、工厂方法模式、抽象方法模式)合并成简单工厂模式使用且代码中无任何if else 或是switch语句
4:IOC和工厂模式连合使用业实现1中描述的场景
     思路其实很简单:
    在工厂中持有一map(通过IOC注入),key 为简单工厂中要传入的参数(KEY本身就作为表示业务对像类型的值),value为实现了处理器接口   WorkFlowTaskHandler的具体实现。取出具体的“产品”,即场景中的处理器
  在工作流引擎中中调用方式如下
//getHanerByTask 方法中传入要处理的工作流任务类型
WorkFlowTaskHandler handler = taskHandlerFactory.getHanerByTask(dto.getTask().getTaskType());
//handleWfTask为处理器接口WorkFlowTaskHandler中定义的接口
handler.handleWfTask(dto);
下面请看具体实现
4.1 先看IOC配置,如下图所示taskHandlerFactory中持有workFlowHanderHold,workFlowHanderHold就是一个map
workFlowHanderHold中注入了 三个处理器,如有必要还可以继续注入实现了WorkFlowTaskHandler接口的任意类

    4.2 工厂类,所下两图所示,TaskHandlerFactoryImpl的实现中,代码少之又少



郁闷小男人 发表于 2011-9-2 11:34 | 显示全部楼层
感觉你使问题复杂化了,既然已经使用spring了,handler的命名也符合一定的规范,为什么不直接通过一种规范简化掉这些东西,我觉得使用0,1,2再封装到一个map里面去不太靠谱,因为你在代码里面取的时候还要判断0,1,2分别代表那种类型。

Jethro 发表于 2011-9-2 11:34 | 显示全部楼层
你看最后一个图,我在代码中根本没有else if 或是swich 来判断了,getHanerByTask方法中,根本不用在判断 因为dto.getTask().getTaskType() 的值一定是map中某个key,因为有这个约定:
map 的key 0,1,2, KEY本身就作为表示业务对像类型的值 如果再加入一个业务对像,其类型值为5 那map中再注放一个key为5 value 为实现处理器接口的bean
下面是从工厂中取handler
WorkFlowTaskHandler handler = taskHandlerFactory.getHanerByTask(dto.getTask().getTaskType());




gz-vps 发表于 2011-9-2 11:35 | 显示全部楼层
其实这样做是把if else或switch的判断逻辑用Map来取代了。 事先在Map中约定好类型和对应的工厂类。运行时通过类型码(0,1,2)来找到相应的Handler。
你这里把Spring搬上来,最主要的作用就是在Map中定义了这个约定关系。一定程度上,还是达到了简化的目的。

江南枫 发表于 2011-9-2 11:35 | 显示全部楼层
楼主贴的都是图片,我按照思路实现了一遍,发现楼主做了很多重复工作,Spring本身就是一个工厂,配置文件已经是MAP的形式了。能根据bean id 拿到对应的实例

天上智喜 发表于 2011-9-2 11:35 | 显示全部楼层
zq3062211015 写道
楼主贴的都是图片,我按照思路实现了一遍,发现楼主做了很多重复工作,Spring本身就是一个工厂,配置文件已经是MAP的形式了。能根据bean id 拿到对应的实例

好学生。

yoyo 发表于 2011-9-2 11:35 | 显示全部楼层
过度设计了
您需要登录后才可以回帖 登录 | 成为会员

本版积分规则

QQ|手机版|小黑屋|网站帮助|职业IT人-IT人生活圈 ( 粤ICP备12053935号-1 )|网站地图
本站文章版权归原发布者及原出处所有。内容为作者个人观点,并不代表本站赞同其观点和对其真实性负责,本站只提供参考并不构成任何投资及应用建议。本站是信息平台,网站上部分文章为转载,并不用于任何商业目的,我们已经尽可能的对作者和来源进行了通告,但是能力有限或疏忽造成漏登,请及时联系我们,我们将根据著作权人的要求立即更正或者删除有关内容。

GMT+8, 2024-5-5 22:06 , Processed in 0.128374 second(s), 20 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表