程序设计模式之策略模式课程设计.doc_第1页
程序设计模式之策略模式课程设计.doc_第2页
程序设计模式之策略模式课程设计.doc_第3页
程序设计模式之策略模式课程设计.doc_第4页
程序设计模式之策略模式课程设计.doc_第5页
已阅读5页,还剩11页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

河南理工大学程序设计模式结课论文2012 20013学年 第 2 学期论文题目 策略模式 学生姓名 学 号 专业班级 指导教师 年 月 日题目1. Strategy模式概述 摘要:设计模式是一种高级软件重用技术,即在软件开发过程中,在特定环境下解决问题的方法。使用设计模式可以更加简便的重用成功的设计和已有的体系结构。本文以一个简单的例子介绍了策略模式,并给出了策略模式的java实现。 在生活中,我们经常需要就执行某项任务或解决某个问题的一般方法做出抉择,这种情况在软件开发中也屡见不鲜,我们大多数人都已经了解到,短期的抄近路,可能会在长期导致问题严重复杂化, 在软件开发中也常常遇到类似的情况,实现某一个功能有多种算法或者策略,我们可以根据环境或者条件的不同选择不同的算法或者策略来完成该功能。如查找、排序等,一种常用的方法是硬编码(Hard Coding)在一个类中,如需要提供多种查找算法,可以将这些算法写到一个类中,在该类中提供多个方法,每一个方法对应一个具体的查找算法;当然也可以将这些查找算法封装在一个统一的方法中,通过ifelse或者case等条件判断语句来进行选择。这两种实现方法我们都可以称之为硬编码,如果需要增加一种新的查找算法,需要修改封装算法类的源代码;更换查找算法,也需要修改客户端调用代码。在这个算法类中封装了大量查找算法,该类代码将较复杂,维护较为困难。如果我们将这些策略包含在客户端,这种做法更不可取,将导致客户端程序庞大而且难以维护,如果存在大量可供选择的算法时问题将变得更加严重。2. Strategy模式的定义 策略模式是一种行为模式。定义一系列的算法,把他们一个个封装起来,并且使他们可以相互替换,并对用户提供统一的接口,策略模式使算法可独立于使用它的客户而变化。(Define a family of algorithms,encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it. ) 策略模式把对象本身和运算规则区分开来,其功能非常强大,因为这个设计模式本身的核心思想就是面向对象编程的多形性的思想。 策略模式的功能:把具体的算法实现从具体的业务处理中独立出来来,把它们实现成单独的算法类,从而形成一系列的算法,并让这些算法可以相互替换。 策略模式的重心不是如何实现算法,而是如何组织、调用这些算法,从而让程序结构更灵活,具有更好的可维护性和可扩展性策略算法在实现上也是相互独立的,相互之间相互没有依赖的。3. Strategy模式的结构和使用 3.1 策略模式的结构ClientStrategyAlgorthminterface()ContextContextinterfaceStrategyConcreteStrategy CAlgorthminterface()ConcreteStrategy BAlgorthminterface()ConcreteStrategy AAlgorthminterface() 图:模式的通用结构图 策略模式的结构图如上所示:Context定义了一个面向应用的接口。它维护对一个Strategy对象的引用,并使用一个ConcreteStrategy 对象来配置本身。Strategy定义所有的的算法的公共接口,Context使用此接口来调用具体的算法(策略)。具体算法在ConcreteStrategy中实现。这里每一种算法即为一个策略。 当客户调用Context 时,它将客户的请求转发给它的Strategy 。Context将该算法所需的所有数据传递给Strategy,或者将自身作为参数传递给Strategy ,使 Strategy可以回调Context 。 ConcreteStrategy实现具体算法。 3.2 Strategy模式以以下几条原则为基础:(1)对象都具有职责,这些职责不同的具体实现是通过多态的使用完成的。(2)概念上相同的算法具有多个不同的实现,需要进行管理。 将问题域中的各个行为互相分离开来-也就是说将他们解耦,是一个好的设计实践,这使得我们可以修改负责某一行为的类,不会对其它的类产生不良影响 3.3 Strategy模式关键特征 A.意图:可以根据所处的上下文,使用不同的的业务规则或算法;问题:对所需算法的选择取决于发出请求的客户或者要处理的数据,如果只有一些不会变化的算法,就不需要 Strategy 模式;B.解决方案:将对算法的选择和算法的实现相分离。允许根据上下文进行选择;C.参与者与写作者:Strategy 模式制定了如何使用不同的算法,各ConcreteStrategy实现了这些不同个算法,Context 通过类型Strategy的引用时用具体的ConcreteStrategy,Strategy与Contextx相互作用以实现所选的算法,Context将均来自Context的请求转发给Strategy。D.效果:Strategy 模式定义了一些列的算法;可以不使用Switch语句或条件语句;必须以相同的方法调用所有的算法,(他们之间必须拥有相同的接口),各ConcreteStrategy与Context中加入获取状态的方法.E.实现:让使用算法的类(Context)包含一个抽象类(Strategy),该抽象类由一个抽象方法制定如何让调用算法,每个派生类按需要实现算法。 注意:在原型Strategy模式中,选择所有具体实现的职责由Context对象承担,并转给Strategy模式的Context对象 3.4 Strategy模式的组成 环境类(Context):用一个ConcreteStrategy对象来配置。维护一个对Strategy对象的引用。可定义一个接口来让Strategy访问它的数据。 抽象策略类(Strategy):定义所有支持的算法的公共接口。 Context使用这个接口来调用某ConcreteStrategy定义的算法。 具体策略类 (ConcreteStrategy ):Strategy接口实现某具体算法。4. Strategy模式的优点1) 相关算法系列 Strategy类层次为Context定义了一系列的可供重用的算法或行为。 继承有助于析取出这些算法中的公共功能。2) 提供了可以替换继承关系的办法: 继承提供了另一种支持多种算法或行为的方法。你可以直接生成一个Context类的子类,从而给它以不同的行为。但这会将行为硬行编制到 Context中,而将算法的实现与Context的实现混合起来,从而使Context难以理解、难以维护和难以扩展,而且还不能动态地改变算法。最后你得到一堆相关的类 , 它们之间的唯一差别是它们所使用的算法或行为。 将算法封装在独立的Strategy类中使得你可以独立于其Context改变它,使它易于切换、易于理解、易于扩展。3) 消除了一些if else条件语句 :Strategy模式提供了用条件语句选择所需的行为以外的另一种选择。当不同的行为堆砌在一个类中时 ,很难避免使用条件语句来选择合适的行为。将行为封装在一个个独立的Strategy类中消除了这些条件语句。含有许多条件语句的代码通常意味着需要使用Strategy模式。4) 实现的选择 Strategy模式可以提供相同行为的不同实现。客户可以根据不同时间 /空间权衡取舍要求从不同策略中进行选择。5. 适合使用策略模式的情景 在下述情况下可以使用策略模式。(1) 许多相关的类仅仅是行为有异。“策略”提供了一种用多个行为中的一个行为来配置一个类的方法。(2) 需要使用一个算法的不同变体。当这些变体实现为一个算法的类层次时,可以使用策略模式。(3) 算法使用客户不应该知道的数据。可使用策略模式以避免暴露复杂的,与算法相关的数据结构。(4) 一个类定义了多种行为,并且这些行为在这个类的操作中以多个条件语句的形式出现。将相关的条件分支一如它们各自的Strategy类中以代替这些条件语句。6. Strategy模式在Java中的应用 在我们的日常生活中,经常遇到这样的事情:同一件事情在不同的情况下或针对不同的对象会有不同的做法。用程序设计术语来说就是:同样的接口,在不同的情况下需要使用不同的算法。而我们现在所要说的策略模式就是能够实现这一功能的一种设计模式,它可以在不影响客户端的情况下进行多个算法的替换。 例如,我们在一家餐厅吃饭,针对套餐,不同年龄的人可能收费不一样,大人如父母40元每份,老人20元每份,小孩子10元每份。如果要设计个软件来做这件事,那么通常首先考虑的是使用ifelse或switch之类的结构来解决这个问题,例如如下代码:(代码不能运行,仅仅说明问题)javaview plaincopyprint?1. publicclassClient2. 3. publicstaticvoidmain(Stringarg)4. showPrice(persontypeType);5. 6. 7. 8. publicstaticvoidshowPrice(persontypepersontypeType)9. if(persontypeType.equals(daren)/大人10. System.out.println(每份40);11. else12. if(persontypeType.equals(laoren)/老人13. System.out.println(每份20);14. else15. if(persontypeType.equals(xiaihai)/小孩子System.out.println(每份10);16. 17. 18. 19. 仔细分析一下就会知道,这个程序的可变性代码就是3个算法,因此可以先把这3个算法分别用3个类封装起来。由于算法就放在客户端,所以一旦某个计算方法发生变化,显然它违背了开-闭原则,没有把可变性代码进行封装,所以这不是个好程序。ChargeType是抽象类,客户面对的是抽象角色,而真正算法的实现是抽象角色的子类。也就是说,可变的算法已经与客户实现了隔离,从而提高了程序的可维护性。程序源代码:(异常简单,仅仅说明问题)javaview plaincopyprint?1. publicabstractclassChargeType2. publicabstractvoidchargeInfo();3. 4. 5. 6. 7. publicclassdarenChargeextendsChargeType8. 9. Override10. publicvoidchargeInfo()11. System.out.println(每份40元);/算法代码12. 13. 14. 15. 16. 17. 18. 19. publicclasslaorenChargeextendsChargeType20. 21. Override22. publicvoidchargeInfo()23. System.out.println(每份20元);24. 25. 26. 27. 28. 29. 30. 31. publicclassxiaohaiChargeextendsChargeType32. 33. Override34. publicvoidchargeInfo()35. System.out.println(每份10元);36. 37. 38. 39. 40. 7.综合应用举例 在新的案例研究中,我们来考虑一个美国某国际电子商务公司的订单处理系统,这个系统必须能够处理许多不同个国家的订单,这个系统构架中有一个控制器对象,用于处理销售请求,它能够确认何时有人请求销售订单,并将该请求转发给Salesorder对象进行订单处理,订单体系结构系统大致如图:TaskController-SalesOrder其中:SalesOrder对象的功能包括:允许客户通过GUI填写订单:处理税额的计算;处理订单,打印销售收据; 有些功能可能需要借助其他对象实现,比如,SalesOrder对象没有必要自己打印,它的作用是充当一个存放销售订单信息的容器,具体的SalesOrder对象可以调用SalesTicket对象来打印。 根据这种方法,应该这样做:寻找变化,并将它封装在一个单独的类中;将这个类包含在另一个类中; 在本例中,已经确定缴税规则是变化的,“将它封装”就意味着创建一个抽象类定义如何在概念上完成税额计算,然后每种变化派生具体的类,也就是说可以创建一个CalcTax对象,为完成税额计算这一任务定义接口,然后由他派生所需的特定版本。CalcTax+taxAmount(in itemSold:Salable,in qty:double, in price :double):doubleCanTaxUSTax 接下来,应该使用组合取代继承,这意味着用不着在创建不同版本的销售订单,(使用继承),可以用组合来包含变化,也就是说,只有一个SalasOrder类,让它包含处理变化的CalcTax类,如图TskControllerSalesOrdeer+calcTax()CalcTax+taxAmount(in itemSold:Salable,in qty:double, in price :double):doubleCanTaxUSTax Java代码片段:实现Strategy模式 模式Public class TaskController Public void process() /这里的代码模拟了处理任务控制器/、/取得所在国的信息CalcTax myTax;myTax = getTaxRulesForCountry();SalasOrder mySO = new SalesOrder();mySO.process (myTax);Private CalcTax getTaxRulesForCountry()/在实际开发中,要去的所在国的计税规则/相应逻辑可以写在这里,也可以放到配置文件中/这里返回USTax就可以编译了Return new USTax();Public calss SalesOrder Public void process (CalcTax taxToUse)Long itemNumber = 0;Double price = 0;/创建计税对象/、/计算税额Double tax = taxToUse.taxAmount( itemNumber,price);Public abstract calss CalcTaxAbstract public double taxAmount(Long itemSold,double price);P

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论