关于模板方法和策略模式的一点思考

  该随笔的思想原点,应该算是在两三年前了。当时和一前同事聊天、不知怎得就聊到了Http访问。

  一、我记得他和我说过的第一句话,大概是:有没有已经封装好的、比较强大的HttpUtil。也可能是受业务的影响(接口对内)、我当时接触到的Http访问,大多比较“规范”,至少有一个接口约束在约定着某些东西,不至于一会传递json,返回json, 一会又要传递xml,返回xml,甚至更奇葩的是,上传个文件、返回0或者1。如果真出现这样的状态,HttpUtil依然能够方便、灵活的适应着各种情况、我想这个Util已经绝对强大了。而不巧的是,我同事那里恰恰就是要满足这样奇葩的需求(和多个第三方进行系统对接)。

  记得当时,面对这个问题时、我的第一意识:模板方法,并且似乎还在哪里见过这样的使用方式。因为:整个Http访问的流程无外乎:

  1、根据Url创建请求对象,

  2、设置请求参数,比如:不使用缓存、设置Header、Cookie、超时时间 等等。

  3、发送数据,比如:Post方法。

  4、创建响应对象

  5、接收数据。

  6、获取响应参数

  7、初上述流程之外,无论是作为Util、还是作为一个强大的框架、很有可能还进行异常处理、日志记录等附加流程。

  定义一个算法主干、将步骤的细节实现延迟到子类,使得。在基类中复用代码,形成一个继承体系,最终,只需要在最底层的类中、重写函数处理三件事,一个是提供请求地址,第二个是提供请求数据,第三个是处理响应数据,当然这样处理、默认认为请求方法已经被封装了。这么一想,这个方案似乎不错啊?

  但是,如果系统中有成百上千个需要对接的接口,结果会咋样?成百上千个类? 似乎也可以接受?

  再复杂一点,如果请求的数据可能是表单、Json、Xml、文件,而响应的数据也有可能是这些、甚至更多,那么面对这样的需求,如果继续使用模板方法会咋样?仔细想想,继承可以实现代码复用、但面对上述的需求,如果只是使用继承、能实现高效复用吗(尤其是面对单继承的情况下)?请注意在这里处理请求数据 和 处理响应数据是两个变化点、并且是两个变化点独立变化,即请求数据可能是模拟的一个表单,而响应数据可能是一段Json、一段Xml、一张Image(验证码), 甚至可能是一个文件 或者一个压缩包(多个文件)。而如果请求数据是Json、Xml 等等格式,响应数据依然有可能是如上的情况。也就说一旦遇到多个变化点独立变化时,单继承瞬间就被打回原形了。

  再多浪费一点思考的精力,如果将大量的可复用代码放入基类(访问权限是受保护的),然后在子类中选择性进行调用,似乎也可以解决上文提到的“多个变化点独立变化”的问题,但是那样一来,基类会极其臃肿,灵活性会大大降低,并且多种数据处理方式之间的耦合性会成指数级上升【这算是一种更失败的设计】。  

  

  回头瞅一眼,刚开始、模板方法也不错啊、即便一个对接接口对应一个类,在某种程度上也是可以接受的啊。毕竟每个接口都具有独立性、单个类进行对应,符合单一职责原则。如果多个接口具有相似性(指的是业务上的相似性),也可以很方便的借助模板方法的继承体系、只需新建一个Method,便可以搭建成一个简单工厂模式,以便隐藏掉更多的实现类、达到简化使用的目的。只是后来由于“多个变化点独立变化”,才引发了一些问题,如若不然,前者的设计依然可以很好地工作。那么“多个变化点独立变化”的问题,该怎么解决呢?答:策略,对每一个变化点,单独使用策略模式。至此、这个比较强大的HttpUtil,算是暂告一段落。至少,在实际应用中,以 模板方法 + 策略模式 这样的组织方式,构建出来的代码已经满足了现有需求,如有其它问题,欢迎留言。

  二、当我提出了模板方法之后,我问同事,有什么想法?他的回答是,似乎觉得使用了策略模式之后,模板方法就不需要了,或者说模板方法可以完全被策略模式所替代。并且我当时也有一个错误认知,模板方法 = 一组策略模式。在代码效果上来看,模板方法 和 一组策略模式 确实是可以划等号的,但两者真的“相等”吗? 如果相等,那么模板方法似乎没必要存在了?我们先看一下两者的意图吧:

  模板方法的意图:定义一个算法流程,将一些特定步骤的具体实现、延迟到子类。使得可以在不改变算法流程的情况下,通过不同的子类、来实现“定制”流程中的特定的步骤。

  策略模式的意图:使不同的算法可以被相互替换,而不影响客户端的使用。

  在意图上看,模板方法更加强调:

  1)定义一条线(算法流程),线上的多个点是可以变化的(具体实现在子类中完成),线上的多个点一定是会被执行的,并且一定是按照特定流程被执行的。

  2)算法流程只有唯一的入口,对于点的访问是受限的【通常用受保护的虚函数来定义可变点】。

  策略模式更注重于: 一个“策略”是一个整体的(完整的)算法,算法是可以被整体替换的。而模板方法只能被替换其中的特定点,算法流程是固定不可变的。

  

  在这样的细节上看来,模板方法 和 一组策略模式 是不可以划等号的。

  三、在这个“古老”的模式——模板方法面前,似乎 “优先使用对象组合,而不是继承” 的策略模式 很是趾高气昂?我个人还是觉得、各有优缺,只是各自适应的场景不一样而已。当遇到“多个变化点独立变化”时,这时就需要策略模式来救场了,如若不然,原有架构可以很好地进行维护和扩展,那还有必要去大动干戈、非要去找到那个暂时最完美的答案吗?似乎没有吧。

  四、附参考资料《设计模式精解》:

时间: 2024-10-15 04:05:45

关于模板方法和策略模式的一点思考的相关文章

关于互联网商业模式的一点思考

传统互联网的商业模式,说白了就是通过流量获得收益.这里面有两个问题,一个是怎么获得流量,另外一个是怎么获得收益? 先来说说怎么获得流量.互联网企业一般通过提供平台,服务,或内容来吸引用户.这里面有一个基本原则就是,一般提供的基础平台基础服务或基本内容都是免费的.比如门户网站提供信息的整理和分类,搜索引擎提供信息的快速获取,电子商务提供交易平台来连接买家和卖家,社交网络提供人们互相通信和交流的渠道,游戏平台提供人们打发碎片时间的娱乐活动,安全服务提供人们上网的安全需要,以及对本地系统和数据的归档整

设计模式6(组合模式,模板方法,策略模式)

组合模式 将对象组合为"部分-整体"的层次结构,组合模式使得用户对单个对象和组合对象的使用统一的接口 关键在于抽象类的定义,为leaf 和composite提供了统一的接口 操作接口 添加leaf 删除leaf 获取特定leaf 装饰者模式 可以将装饰者支持组合模式需要的一些功能       享元模式   当组合模式中出现大量相似的组件对象并且状态可以从组件对象分离     迭代模式         访问者 在不修改原有对象结构的基础上为基添加新功能       职责链模式 其实现请求

命令模式 & 策略模式 & 模板方法

一.策略模式 策略模式:封装易变化的算法,可互相替换. GoF<设计模式>中说道:定义一系列算法,把它们一个个封装起来,并且使它们可以相互替换.该模式使得算法可独立于它们的客户变化. 比如:一个推送服务类,推送的方式,可以分为:QQ推送.邮箱推送.App推送.PC插件推送. 这里讲两个点: 1.推送方式可以互相替换: 2.这些推送方式只是单纯的属于推送服务这个类本身. 好好琢磨关键词:相互替换 二.命令模式 命令模式:解决“行为请求者”与“行为实现者”通常呈现一种“紧耦合”的问题. GoF&l

模板方法模式、策略模式 的 联系、区别和应用场景

介绍和实现: 策略模式的结构其实非常简单,比模板方法模式简单多了,它实质上就是一个原则的体现,往低里说就是里式替换原则,往高里说是依赖倒置原则,具体实现过程是这样: 有一个接口(抽象类)A中有一个抽象算法方法a 有一组接口(抽象类)A的实现类(子类)A-? 用不同具体算法实现了抽象算法方法a 然后有一个业务类B中有业务方法b和类型为A的对象成员c,其中方法b中通过调用c的算法方法a来干一些活 最后在使用时,实例化业务类B时传入不同的A的子类A-?以实例化出使用不同算法的业务类B的对象 而模板方法

行为型设计模式之模板方法(TEMPLATE METHOD)模式 ,策略(Strategy )模式

1 模板方法(TEMPLATE METHOD)模式: 模板方法模式把我们不知道具体实现的步聚封装成抽象方法,提供一些按正确顺序调用它们的具体方法(这些具体方法统称为模板方法),这样构成一个抽象基类.子类通过继承这个抽象基类去实现各个步聚的抽象方法,而工作流程却由父类来控制. 2 模板方法应用于下列情况: 1) 一次性实现一个算法的不变的部分,并将可变的行为留给子类来实现. 2)各子类中公共的行为应被提取出来并集中到一个公共父类中以避免代码重复.首先识别现有代码中的不同之处,并且将不同之处分离为新

java 策略模式 模板方法 (Template method) 示例

<pre name="code" class="cpp">package org.rui.pattern; import junit.framework.TestCase; /** * 分解共同性(Factoring Commonality ) * 应用"一次且只能有一次" 原则产生最基本的模式,将变化的那部分代码放到方 法里. 这可以用两种方法来表达: 策略模式(Strategy * ):运行时刻选择算法 另外,Strategy 模

Android设计模式之命令模式、策略模式、模板方法模式

命令模式是其它很多行为型模式的基础模式.策略模式是命令模式的一个特例,而策略模式又和模板方法模式都是算法替换的实现,只不过替换的方式不同.下面来谈谈这三个模式. 命令模式 将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化:对请求排队或记录请求日志,以及支持可撤消的操作. java中传递(注入)对象很容易,但是却不支持直接传递行为(即传递函数或者说传递方法),只能间接的通过传递(注入)一个对象,再调用它的行为来实现.如果把这样的行为抽取出来为一个类,称作命令类,它的具体实现都是命令

java设计模式7.策略模式、模板方法模式、观察者模式

策略模式 策略模式的用意,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换.策略模式使得算法可以在不影响到客户端的情况下发生变化. 环境角色:持有一个抽象策略角色的引用. 抽象策略角色:给出所有的具体策略类所要实现的接口. 具体策略角色:包装相关的算法或行为. 模板方法模式 模板方法的用意,使用一个抽象类,将部分逻辑以具体方法以及具体构造子的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑.不同的子类可以用不同的方式来实现这些抽象方法. 抽象模板角色:1. 定义一个或多

研磨设计模式之策略模式

策略模式(Strategy) 1  场景问题 1.1  报价管理 向客户报价,对于销售部门的人来讲,这是一个非常重大.非常复杂的问题,对不同的客户要报不同的价格,比如: (1)对普通客户或者是新客户报的是全价 (2)对老客户报的价格,根据客户年限,给予一定的折扣 (3)对大客户报的价格,根据大客户的累计消费金额,给予一定的折扣 (4)还要考虑客户购买的数量和金额,比如:虽然是新用户,但是一次购买的数量非常大,或者是总金额非常高,也会有一定的折扣 (5)还有,报价人员的职务高低,也决定了他是否有权