论坛首页 Java企业应用论坛

也谈设计模式(Strategy)

浏览 5641 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2008-01-02  

  今天主要想谈谈Strategy(策略)模式。

  先从一个例子开始吧,公司的系统中有一个功能,就是当我们的系统和别系统做接口(收发消息)的时候,由于我们的系统可能和多个外系统做这个动作,而对于两个系统做通信来说,虽然我们现在是异步的实现,使用的IBM的消息中间件(MQ),但是两个系统必须首先在一起互相决定一下我们的消息格式和规范,这是系统之间能不能通信成功的一个关键所在,所以不管是从指定的Queue里收消息,还是往指定的Queue里发送消息,在数据准备好之前,我们必须还要进行一步数据格式的转换,我们使用的都是XML格式的数据,这里的转换不是指跨数据格式的转换,而是就XML而言,进行的转换,比如:对方需要一个什么样格式的XML它才可以去解析到正确的信息,我们需要对方是个什么样的格式过来,我们的系统才能够正常的去工作。

  针对于上面的这个情况,相信,大家的第一个反应是接口,具体实现类,然后根据不同的系统调用不同的具体实现类,然后执行下面的流程,收-->转-->处理||转-->发。

 

  现在我们系统的实现方式也是这样,定义了一个filter的接口,里面封装的转换格式的业务方法,然后呢再根据不同的系统交互定义不同的class来实现这个接口并重写这些转换的业务方法,而至于客户端程序是怎么知道要具体调用哪个具体实现的class,是根据我们在参数里配置的class名称来决定的,所以系统会拿这个参数中写的具体实现类名来造型,并得到一个实现此接口的对象实例,然后调用接口中定义的业务方法,进行处理。我想我对以上的这一套流程的描述,大家应该能够清楚,不是很复杂的东西。继续往下吧!

  我们系统的这个设计是它本身的优点的,在一定程度上解耦合,基本上客户程序不用关系具体我要走哪个实现类,参数配置了,而且我统一调接口的方法就可以完成我想要的工作了,灵活性也很高。

 

  我认为,我们这个设计就是个典型的策略模式,我个人认为是一种更好的Strategy(策略)模式。

 

  那么什么是策略模式,我认为,还是要顾名思义,对于一个问题,就如我上面谈到的消息格式转换问题,可能会有很多个策略,或者说通俗点,就是会有多个实现方法,那么对于客户程序而言,我和你定了一个接口,至于接口背后要怎么做我不知道,但是我知道你那个接口背后会有什么人在帮我做,对于接口而言,你,客户程序必须告诉我你要我的哪个实现来做这个事,要不我没办法帮你做事。接口其实不做事,相当于通信员,呵呵,是个规范而已,好了,于是策略模式一般的做法是在接口前再来个类,就是所谓的环境类,这个类里有个接口的实例,是个数据成员,然后客户成员用这个类,new的时候呢给我个具体的实现类,然后调用的这个环境类中的具体业务方法,就OK了,这个类我认为是把接口再封装了一层,有点那个意思,其实这个环境类中的业务方法无非就是调用接口中定义的那些方法罢了。不想写代码,所以就口述了,不知道能不能说清楚,大家见谅!

  好了,典型的策略模式应该就是这样了,那么用了有什么好处?

  因为使用这种模式的原因是我们的系统对于同一个类型的业务可能有很多个方法去实现,变化很多很快,不稳定,但是业务是一样的,业务的流程也是相似的,就是具体实现方法不一样,这样我们使用策略模式就可以大大减少我们这些实现和客户程序的耦合程度,如果我们添加新的实现策略就不需要改动客户程序。非常灵活,方便。

  但是最大的问题,我认为是最不好的地方是,客户程序必须要知道我是用的哪个策略,这无疑又把具体实现和客户程序耦合起来了,如果我的具体实现名称改了,那么客户程序可能就傻眼了。

  第二个缺点,随着策略的增多,类也会增多。

  我们公司的设计我认为是解决了我所认为这个模式的最大的一个问题,如果说再做一层隔离,我客户程序也不知道是要用哪个具体的策略去做事,而是由第三方来告诉我,那么客户程序就真正的和我们的策略实现解耦了,当代码运行到我需要使用策略的时候我才知道是要用具体的哪个,这种方法就非常的灵活了,这样一来,客户程序也变的非常通用,复用程度会大大提高。根本就不需要那个环境类来根据你给的具体实现类来通过接口调度到具体的实现类中的方法。

以上是我个人的一点点想法,可能还有想得不周到的地方,一点心得吧,没写什么代码,很不好意思,希望能看得懂!

   发表时间:2008-01-02  
如果是按照你所说的在加上一层 需要怎么加呢?????
0 请登录后投票
   发表时间:2008-01-02  
引用
songyu499 1 小时前 如果是按照你所说的在加上一层 需要怎么加呢?????
我的意思是这样的,如果我们在一般使用Stategy模式的时候必然要有个环境抽象类,一般如下:
    public class Context{
        private 策略接口类型 strategy;
        public Context(策略接口类型 strategy){
            this.strategy = strategy;
        }
        
        public ... method(){
            this.strategy do something;
        }
    }

上面的这个class就是环境类的基本构造,客户程序可以调用这个类中的方法去实现不同的策略,但是前提是客户程序必须给个构造函数中的具体实现了策略接口的类的实例过来,我才能去做具体的事情。
而我讲的方法是,我们完全可以不需要这个类,完全可以在配置文件(这里的配置文件可以自己定义)中去读取和配置你要的具体实现策略方法的类,也就是实现策略接口的类,然后通过class.forName("").newInstance()来构造一个类,这样再执行具体的业务方法。更加直观,并且灵活,解耦充分,这样对于客户程序的复用很有帮助。
0 请登录后投票
   发表时间:2008-01-02  
恍然大悟 多谢多谢~~!~
0 请登录后投票
   发表时间:2008-01-02  
不客气 互相交流 互相学习
0 请登录后投票
   发表时间:2008-01-02  
如果是按照你所说的话 就是有点向Spring的方向去靠拢了
0 请登录后投票
   发表时间:2008-01-02  
恩 我想你的意思是依赖注入这个概念吧,有那么点意思 呵呵
0 请登录后投票
   发表时间:2008-01-03  
不错,这正是OCP要达到的目标,被你应用的实际中去了!
0 请登录后投票
   发表时间:2008-01-18  
让我想起了servlet filter接口,
java.util.File.list()方法
...
..
0 请登录后投票
   发表时间:2008-01-19  
很多设计模式不是单独用的。

很多地方factory模式之类的可以被DI替换。
而strategy刚好跟factory有点关系。

spring是粘合剂……
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics