1.1概述
方法是类中最重要的组成部分,一个方法的方法体由一系列语句构成,也就是说一个方法的方法体是一个算法。在某些设计中,一个类的设计人员经常可能涉及这样的问题:由于用户需求的变化,导致经常需要修改类中某个方法的方法体,即需要不断地变化算法。在这样的情况下可以考虑使用策略模式。
策略模式是处理算法不同变体的一种成熟模式,策略模式通过接口或抽象类封装算法的标识,即在接口中定义一个抽象方法,实现该接口的类将实现接口中的抽象方法。策略模式把针对一个算法标识的一系列具体算法分别封装在不同的类中,使得各个类给出的具体算法可以相互替换。
在策略模式中,封装算法标识的接口称作策略,实现该接口的类称作具体策略。
1.2模式的结构
策略模式的结构包括三种角色:
(1)策略(Strategy):策略是一个接口,该接口定义若干个算法标识,即定义了若干个抽象方法。
(2)具体策略(ConcreteStrategy):具体策略是实现策略接口的类。具体策略实现策略接口所定义的抽象方法,即给出算法标识的具体算法。
(3)上下文(Context):上下文是依赖于策略接口的类,即上下文包含有策略声明的变量。上下文中提供了一个方法,该方法委托策略变量调用具体策略所实现的策略接口中的方法。
策略模式接口的类图如下所示:
1.3策略模式的优点
(1)上下文和具体策略是松耦合关系。因此上下文只知道它要使用某一个实现Strategy接口类的实例,但不需要知道具体是哪一个类。
(2)策略模式满足“开-闭原则”。当增加新的具体策略时,不需要修改上下文类的代码,上下文就可以引用新的具体策略的实例。
1.4适合使用策略模式的情景
(1)一个类定义了多种行为,并且这些行为在这个类的方法中以多个条件语句的形式出现,那么可以使用策略模式在类中使用大量的条件语句。
(2)程序不希望暴露复杂的、与算法有关的数据结构,那么可以使用策略模式来封装算法。
(3)需要使用一个算法的不同变体。
1.5策略模式的使用
下面通过一个简单的实例,实现1.1概述中简单例子:在某种比赛中有若干个裁判,每位裁判给选手一个得分。选手的最后得分是根据全体裁判的得分计算出来的。请给出几种计算选手得分的评分方案(策略),对于某次 比赛,可以从你的方案中选择一种方案作为本次比赛的评分方案。
针对上述问题,使用策略模式设计若干个类。具体如下:
首先看一下本实例构建框架具体类和1.2模式的结构中类图的对应关系,如下图所示:
(1)策略(Strategy)
本问题中,策略接口的名字是ComputableStrategy,该接口规定的算法标识即抽象方法是double computeScore(double []a),ComputableStrategy接口的代码如下:
package com.liuzhen.four_strategy; public interface ComputableStrategy { public abstract double computeScore(double[] a); }
(2)具体策略
对于本问题,有三个具体策略StrategyOne,StrategyTwo和StrategyTree。其中StrategyOne类实现为计算数组a的元素代数平均值;StrategyTwo类实现计算数组a的元素的几何平均值;StrategyThree类实现为去掉数组a中最大元素和最小元素 ,然后计算剩余元素的代数平均值。
StrategyOne类代码如下:
package com.liuzhen.four_strategy; public class StrategyOne implements ComputableStrategy{ public double computeScore(double[] a){ double score = 0 , sum = 0; for(int i = 0;i < a.length;i++){ sum += a[i]; } score = sum/a.length; return score; } }
StrategyTwo类代码如下:
package com.liuzhen.four_strategy; public class StrategyTwo implements ComputableStrategy { public double computeScore(double[] a) { double score = 0 , multi = 1; int n = a.length; for(int i = 0;i < a.length;i++){ multi = multi*a[i]; } score = Math.pow(multi,1.0/n); return score; } }
StrategyThree类代码如下:
package com.liuzhen.four_strategy; import java.util.Arrays; public class StrategyThree implements ComputableStrategy{ public double computeScore(double[] a){ if(a.length <= 2) return 0; double score = 0,sum = 0; Arrays.sort(a); for(int i = 1;i < a.length-1;i++){ sum += a[i]; } score = sum/(a.length-2); return score; } }
(3)上下文
上下文是GymnasticsGame类,该类包含策略声明的变量,此变量可用于保存具体策略的引用。另外,GymnasticsGame类中包含一个double型数组a,a的元素代表各个裁判给选手的评分。该类中的getPersonScore(double a[])方法将委托具体策略的实例计算选手的最后得分。GymnasticsGame类的代码如下:
package com.liuzhen.four_strategy; public class GymnasticsGame { ComputableStrategy strategy; public void setStrategy(ComputableStrategy strategy){ this.strategy = strategy; } public double getPersonScore(double[] a){ if(strategy != null) return strategy.computeScore(a); else return 0; } }
(4)具体使用
package com.liuzhen.four_strategy; public class FourApplication { public static void main(String args[]){ GymnasticsGame game = new GymnasticsGame(); //上下文对象 game.setStrategy(new StrategyOne()); //上下文对象使用策略一 Person zhang = new Person(); zhang.setName("张三"); double[] a = {9.12,9.25,8.87,9.99,6.99,7.88}; Person li = new Person(); li.setName("李四"); double[] b = {9.15,9.26,8.97,9.89,6.97,7.89}; zhang.setScore(game.getPersonScore(a)); li.setScore(game.getPersonScore(b)); System.out.printf("%s最后得分:%5.3f%n",zhang.getName(),zhang.getScore()); System.out.printf("%s最后得分:%5.3f%n",li.getName(),li.getScore()); game.setStrategy(new StrategyTwo()); //上下文对象使用策略二 zhang.setScore(game.getPersonScore(a)); li.setScore(game.getPersonScore(b)); System.out.println("使用几何平均值方案:"); System.out.printf("%s最后得分:%5.3f%n",zhang.getName(),zhang.getScore()); System.out.printf("%s最后得分:%5.3f%n",li.getName(),li.getScore()); game.setStrategy(new StrategyThree()); //上下文对象使用策略三 zhang.setScore(game.getPersonScore(a)); li.setScore(game.getPersonScore(b)); System.out.println("使用(去掉最大值和最小值)算术平均值方案:"); System.out.printf("%s最后得分:%5.3f%n",zhang.getName(),zhang.getScore()); System.out.printf("%s最后得分:%5.3f%n",li.getName(),li.getScore()); } }
其中,Person类代码如下:
package com.liuzhen.four_strategy; public class Person { String name; double score; public void setScore(double score){ this.score = score; } public void setName(String name){ this.name = name; } public double getScore(){ return score; } public String getName(){ return name; } }
运行结果如下:
张三最后得分:8.683 李四最后得分:8.688 使用几何平均值方案: 张三最后得分:8.625 李四最后得分:8.631 使用(去掉最大值和最小值)算术平均值方案: 张三最后得分:8.780 李四最后得分:8.817
相关推荐
http://blog.csdn.net/laszloyu/archive/2010/05/11/5579765.aspx 示例代码
javascript设计模式之策略模式学习笔记.docx
行为型模式:模版方法模式、命令模式、访问者模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式(Interpreter模式)、状态模式、策略模式、职责链模式(责任链模式) 2) 学习目标:通过学习,学员...
工厂模式,策略模式,装饰模式,代理模式,工厂方法模式,原型模式等23个设计模式
3. 行为型模式:行为型模式关注对象之间的通信和协作,包括责任链模式、命令模式、解释器模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、策略模式、模板方法模式和访问者模式。这些模式可以帮助...
主要介绍了javascript设计模式之策略模式学习笔记,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
Java Design PatternsJava 设计模式学习笔记,简单易懂,每个模式都有相应的代码示列,帮助学习理解。在线阅读地址:设计原则创建型模式作用:将创建与使用代码解耦结构型模式作用:将不同的功能代码解耦桥接模式...
本文实例讲述了Javascript面向对象程序设计对象成员的定义。分享给大家供大家参考,具体如下: 序: 刚接触javascript的时候,觉得这语言有点儿摸不着门道,感觉这玩意儿太难学了,没什么规范,没什么像样的手册,...
设计模式学习笔记,此项目参考《大话设计模式》,只能作为入门级设计模式学习 设计原则 职责单一原则 开放-封闭原则 依赖倒转原则 高层模块不依赖底层模块,两个模块都应该依赖抽象。抽象不依赖细节,细节依赖抽象。...
javascript 设计模式与开发实践 作者 曾探 本书字体清晰,学习起来舒服。和张容铭的javascript设计模式相比,个人觉得有以下不同之处: 1、需要对原型链和闭包有一定的基础 2、案例比较经典并且通熟易懂,讲解特别...
主要为大家详细介绍了javascript设计模式之中介者模式学习笔记,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
* 软件设计模式和架构 * 数据库管理和设计 * 软件测试和质量保证 * 软件项目管理和协调 软件设计师的职业发展 软件设计师是一个高薪职业,职业发展空间广阔。软件设计师可以晋升为高级软件设计师、软件架构师、...
describe:设计模式学习笔记 逻辑结构图 代码结构图 设计模式简述 创建型模式,共五种:工厂方法模式,抽象工厂模式,单例模式,建造者模式,原型模式。 结构型模式,共七种:适配器模式,装饰器模式,代理模式,...
第一部分:设计模式 & UML 简单工厂 工厂方法模式 抽象工厂模式 策略模式 责任链模式 命令模式 模板方法模式 适配器模式 代理模式 外观模式 组合模式 装饰模式 享元模式 桥接模式 Builder模式 状态模式 解释器模式 ...
避坑笔记2021CICDCI/CD流程以及原理说明设计模式:策略模式单例模式工厂模式装饰器模式观察者模式适配器模式模板方法模式SpringBoot:SpringBoot(1):公共配置SpringBoot(2):generatorSpringBoot(3):docker部署...
JS-design-pattern根据曾探所著《JavaScript设计模式与开发实践》整理的学习笔记基础知识创建模式结构模式行为模式状态模式策略模式发布订阅模式
设计模式共23种(大部分文献也有24种的说法,增加了空对象模式),常用一定要掌握的设计模式:单例模式、工厂模式、抽象工厂模式、策略模式、装饰模式、适配器模式、桥接模式、观察者模式 codetips :closed_book: ...
VS2005 ASP.NET本地化学习笔记&感受 在自定义Server Control中捆绑JS文件 Step by Step 深度解析Asp.Net2.0中的Callback机制 使用 Web 标准生成 ASP.NET 2.0 Web 站点 ASP.NET 2.0基于SQLSERVER 2005的aspnetdb.mdf...