Java中的策略模式实例教程
策略模式是一种行为模式。用于某一个具体的项目有多个可供选择的算法策略,客户端在其运行时根据不同需求决定使用某一具体算法策略。
策略模式也被称作政策模式。实现过程为,首先定义不同的算法策略,然后客户端把算法策略作为它的一个参数。使用这种模式最好的例子是Collection.sort()方法了,它使用Comparator对象作为参数。根据Comparator接口不同实现,对象会被不同的方法排序。详细介绍请看java中的排序对象。
本文例子是,完成一个简单地购物车,两种付款策略可供选择,一为信用卡,另外一种为Paypal。
首先创建策略接口,在本文例子中,付款金额作为参数。
1 | package com.journaldev.design.strategy; |
2 |
3 | public interface PaymentStrategy { |
4 |
5 | public void pay( int amount); |
6 | } |
现在实现使用信用卡及Paypal两种算法策略的实体类。
01 | package com.journaldev.design.strategy; |
02 |
03 | public class CreditCardStrategy implements PaymentStrategy { |
04 |
05 | private String name; |
06 | private String cardNumber; |
07 | private String cvv; |
08 | private String dateOfExpiry; |
09 |
10 | public CreditCardStrategy(String nm, String ccNum, String cvv, String expiryDate){ |
11 | this .name=nm; |
12 | this .cardNumber=ccNum; |
13 | this .cvv=cvv; |
14 | this .dateOfExpiry=expiryDate; |
15 | } |
16 | @Override |
17 | public void pay( int amount) { |
18 | System.out.println(amount + " paid with credit/debit card" ); |
19 | } |
20 |
21 | } |
01 | package com.journaldev.design.strategy; |
02 |
03 | public class PaypalStrategy implements PaymentStrategy { |
04 |
05 | private String emailId; |
06 | private String password; |
07 |
08 | public PaypalStrategy(String email, String pwd){ |
09 | this .emailId=email; |
10 | this .password=pwd; |
11 | } |
12 |
13 | @Override |
14 | public void pay( int amount) { |
15 | System.out.println(amount + " paid using Paypal." ); |
16 | } |
17 |
18 | } |
此时,算法策略已经准备就绪,现在需要实现购物车以及能够运用付款策略的支付方法。
01 | package com.journaldev.design.strategy; |
02 |
03 | public class Item { |
04 |
05 | private String upcCode; |
06 | private int price; |
07 |
08 | public Item(String upc, int cost){ |
09 | this .upcCode=upc; |
10 | this .price=cost; |
11 | } |
12 |
13 | public String getUpcCode() { |
14 | return upcCode; |
15 | } |
16 |
17 | public int getPrice() { |
18 | return price; |
19 | } |
20 |
21 | } |
01 | package com.journaldev.design.strategy; |
02 |
03 | import java.text.DecimalFormat; |
04 | import java.util.ArrayList; |
05 | import java.util.List; |
06 |
07 | public class ShoppingCart { |
08 |
09 | //List of items |
10 | List<Item> items; |
11 |
12 | public ShoppingCart(){ |
13 | this .items= new ArrayList<Item>(); |
14 | } |
15 |
16 | public void addItem(Item item){ |
17 | this .items.add(item); |
18 | } |
19 |
20 | public void removeItem(Item item){ |
21 | this .items.remove(item); |
22 | } |
23 |
24 | public int calculateTotal(){ |
25 | int sum = 0 ; |
26 | for (Item item : items){ |
27 | sum += item.getPrice(); |
28 | } |
29 | return sum; |
30 | } |
31 |
32 | public void pay(PaymentStrategy paymentMethod){ |
33 | int amount = calculateTotal(); |
34 | paymentMethod.pay(amount); |
35 | } |
36 | } |
注意,购物车的支付方法接受支付策略作为参数,但是不在其内部保存任何实例变量。
一个简单地测试程序。
01 | package com.journaldev.design.strategy; |
02 |
03 | public class ShoppingCartTest { |
04 |
05 | public static void main(String[] args) { |
06 | ShoppingCart cart = new ShoppingCart(); |
07 |
08 | Item item1 = new Item( "1234" , 10 ); |
09 | Item item2 = new Item( "5678" , 40 ); |
10 |
11 | cart.addItem(item1); |
12 | cart.addItem(item2); |
13 |
14 | //pay by paypal |
15 | cart.pay( new PaypalStrategy( "myemail@example.com" , "mypwd" )); |
16 |
17 | //pay by credit card |
18 | cart.pay( new CreditCardStrategy( "Pankaj Kumar" , "1234567890123456" , "786" , "12/15" )); |
19 | } |
20 |
21 | } |
输出如下:
1 | 50 paid using Paypal. |
2 | 50 paid with credit/debit card |
策略模式UML图
重要点:
* 此处可以构建策略的实体变量,但是应该尽量避免这种情况。因为需要保证对于特定的任务能够对应某个具体的算法策略,与Collection.sort()和Array.sort()方法使用comparator作为参数道理类似。
* 策略模式类似与状态模式。两者之间的不同,状态模式中的Context(环境对象)包含了状态的实例变量,并且不同的任务依赖同一个状态。相反,在策略模式中策略是作为一个参数传递进方法中,context(环境对象)不需要也不能存储任何变量。
* 当一组算法对应一个任务,并且程序可以在运行时灵活的选择其中一个算法,策略模式是很好的选择。
这就是全部的Java策略模式,希望你喜欢上它了。
- 转载自 并发编程网 - ifeve.com
相关文章:

struts 2 结合json
struts 2 结合json 在struts 2中,要结合json的话,其实是不错的选择,最近做一个登陆系统时,可以考虑选择用struts 2结合json,下面是要点register页面<s:form action"Regist.action"> <s:textfield id"u…
什么是遗传算法?
本文从遗传算法的生物学基础讲起,详细介绍了遗传算法的原理、步骤和简单应用。

使用FileItem获取文件名时注意事项
获取文件名的时候,要注意对不同浏览器的处理,下面给出方法参考 FileItem类的常用方法: 1. boolean isFormField() isFormField方法用于判断FileItem类对象封装的数据是一个普通文本表单字段,还是一个文件表单字段,如果…

Winson.SqlPager 2.5 发布!
Winson.SqlPager 分页控件 版本: 2.5 此控件必须与Winson.Framework框架一起使用安装方法:只需将解压出来的 SqlPage.cs文件复盖了Winson.WControls\SqlPager\ 目录里的同名文件即可.由于之前的控件存在着一些比较严重的BUG,这次对SqlPager做了比较大的改动,修复了一些BUG和改进…

laravel中查看执行的SQL语句
今天想查看laravel框架中执行的SQL语句,百度了一圈,才找到,这文档真心看着不爽,下面上查看方法 DB::connection()->enableQueryLog();$navObj new NavModel();$data $navObj->where($where)->select($this->field)->orderBy(id, desc)->get();$log DB::ge…
Matlab与线性代数 -- 向量的范数
Matlab与线性代数 – 向量的范数

Mac下sublime text2 解决中文乱码
1.control ~ 调出console 2.粘贴以下代码并回车 import urllib2,os;pfPackage Control.sublime-package;ippsublime.installed_packages_path();os.makedirs(ipp) if not os.path.exists(ipp) else None;open(os.path.join(ipp,pf),wb).write(urllib2.urlopen(http://sublim…

封装DateTimePicker并使用绑定时遇到的问题
请教各位高手: 我想把一个控件封装起来.DateTimePicker 因为他的value的类型为DateTime所以不可以为Null 但是数据库里有一些日期是为空的.如离职日期 现在我写了一个类继承至DateTimePicker 使用public object Value覆盖了基类的Value方法 这样它就可以为NULL了. 在使用…

php入门01
关于变量 注意点: 在php中,变量是通过$符号定义的在php中,变量名是区分大小写的数据类型 布尔类型 布尔类型有两个值,true和false,它不区分大小写当我们用”echo”指令输出布尔类型时,如果是“true”则输出的是“1”&a…
遗传算法主程序
遗传算法主程序 本图文已经更新,详细地址如下: http://blog.csdn.net/lsgo_myp/article/details/54584840

jquery日历插件FullCalendar使用技巧
原文链接:http://blog.csdn.net/u013493957/article/details/44920341FullCalendar是一款基于jquery的日历控件,它有着很强大的功能,下面我来给大家介绍一下FullCalendar使用技巧吧,希望此方法对各位有帮助呀。简介 官方网站:http…

列表CheckBox全选 结合DataGrid 进行删除操作
//CheckBox全选function CA(){ var frmdocument.Form1; alert(frm) for (var i0;i<frm.elements.length;i) { var efrm.elements[i]; alert(e.type) alert(e.name) if ((e.name ! allbox) && (e.typecheckbox)) { …
遗传算法主程序(辅助)
遗传算法主程序(辅助) 本图文已经更新,详细地址如下: http://blog.csdn.net/lsgo_myp/article/details/54584840

互联网产品mysql数据库设计总结
mysql数据库性能不比oracle数据库,所以设计上,和oracle有一些不同。下面总结一些互联网产品的数据库设计。 1.主键 主键可以使用bigint(20) unsigned也可以使用varchar,使用bigint,可以设置为自增主键auto_increment。使用varch…

【跟我一起学Unity3D】做一个2D的90坦克大战之AI系统
对于AI,我的初始想法非常easy,首先他要能动,而且是在地图里面动。 懂得撞墙后转弯,然后懂得射击,其它的没有了,基于这个想法,我首先创建了一个MyTank类,用于管理玩家的坦克的活动&am…
如何利用C#开发“扫雷”小游戏
本文详细说明了利用C#语言开发“扫雷”小游戏的开发过程。
spring ioc原理分析
spring ioc原理分析 spring ioc 的概念简单工厂方法spirng ioc实现原理 spring ioc的概念 ioc: 控制反转 将对象的创建由spring管理。比如,我们以前用new一个对象的方式自己创建一个对象,现在使用spring,不必自己new一个对象了,…

PL/SQL集合类型的整理学习
http://log-cd.iteye.com/blog/521177 PL/SQL集合类型是类似于高级语言数组的一种复合数据类型,集合类型包括索引表(PL/SQL表)、嵌套表(Nested Table)和变长数组(VARRAY)三种类型。<一>、…

多条件组合查询+分页
比较麻烦,把他记录下来。前台UI:实现的类代码:程序代码/// <summary>/// 多条件组合查询/// </summary>/// <param name"suppliercode">供应商代码</param>/// <param name"materialcode">物料代码&l…
Matlab与线性代数 -- 矩阵的重组1
本图文介绍了矩阵重组的第一种情况用新的行或列取代原有矩阵的行或列。

工作中感受到的消息中间件在分布式系统中的使用场景
经历 以前在qunar实习,第一次接触消息中间件,那时候概念还不清楚,朦朦胧胧有个初步认识,现在正式工作了,又一次接触了消息中间件,初步总结几种场景。 场景 1.分布式系统中,不同系统之间传递消…

sql server 2005分页存储过程和sql server 2000分页存储过程(摘)
USE[svnhost]GO/****** 对象: StoredProcedure [dbo].[up_Page2005] 脚本日期: 05/21/2008 11:27:05 ******/SETANSI_NULLS ONGOSETQUOTED_IDENTIFIER ONGOCREATEproc[dbo].[up_Page2005]TableNamevarchar(50), --表名Fieldsvarchar(5000) *, --字段名(全部字段为…

topcoder srm 691 div1 -3
1、给定一个$n$个顶点$n$个边的图,边是$(i,a_{i})$,顶点编号$[0,n-1]$。增加一个顶点$n$,现在选出一个顶点集$M$,对于任意的在$M$中 的顶点$x$,去掉边$(x,a_{x})$,增加边$(x,n)$。最后使得顶点0和1相连。有多少种$M$? 思路&#…
Matlab与线性代数 -- 矩阵的重组2
本图文详细介绍了矩阵重组的第二种情况任意两行或两列进行对换。

mac通过tree源码编译安装tree
通过tree源码编译安装 下载源码:curl -O ftp://mama.indstate.edu/linux/tree/tree-1.6.0.tgz 解压源码:tar xzvf tree-1.6.0.tgz 修改Makefile文件: tree默认的是linux的编译环境,因此移植到mac里面需要注释掉linux的编译选项&am…

java IO流文件的读写具体实例
IO流的分类:1、根据流的数据对象来分:高端流:所有的内存中的流都是高端流,比如:InputStreamReader 低端流:所有的外界设备中的流都是低端流,比如InputStream,OutputStream 如何区分…
Matlab与线性代数 -- 矩阵的重组3
本图文详细介绍了矩阵重组的第三种情况,从矩阵中选取子矩阵。

ASP.NET小收集:IFrame使用
使用Iframe制作一个固定框架,很方便与象后台网站之类的页面1<html xmlns"http://www.w3.org/1999/xhtml">2<head runat"server">3<title>后台</title>4</head>5<frameset cols"170,*"framespacing&…

linux mac中实现类似secureCRT的clone session
在你的登录账户下的.ssh文件夹新建一个文件:config. cd ~/.ssh vi config config的文件中,内容为: host * ControlMaster auto ControlPath ~/.ssh/master-%r%h:%p 重新打开终端,第一次,你还是需要输入密码,…

C#动态加载DLL(转)
利用反射进行动态加载和调用.Assembly assAssembly.LoadFrom(DllPath); //利用dll的路径加载加载dll后,需要使用dll中某类.Type typeass.GetType(“TypeName”);//利用类型的命名空间和名称获得类型需要实例化类型,才可以使用,参数可以人为的指定,也可以无参数,静态实例可以省略…