【转】Java策略消除if else
策略(Strategy)模式:又名Policy,它的用意是定义一组算法,把它们一个个封装起来,并且使他们可以相互替换。策略模式可以独立于使用他们的客户端而变化。GOF策略模式静态结构类图如下:
通过上图可以看出策略模式有以下角色构成:
1、抽象策略(Strategy)角色:抽象策略角色由抽象类或接口来承担,它给出具体策略角色需要实现的接口;
2、具体策略(ConcreteStrategy)角色:实现封装了具体的算法或行为;
3、场景(Context)角色:持有抽象策略类的引用。
策略模式重点是封装不同的算法和行为,不同的场景下可以相互替换。策略模式是开闭原则的体现,开闭原则讲的是一个软件实体应该对扩展开放对修改关闭。策略模式在新的策略增加时,不会影响其他类的修改,增加了扩展性,也就是对扩展是开放的;对于场景来说,只依赖于抽象,而不依赖于具体实现,所以对修改是关闭的。策略模式的认识可以借助《java与模式》一书中写到诸葛亮的锦囊妙计来学习,在不同的场景下赵云打开不同的锦囊,便化险为夷,锦囊便是抽象策略,具体的锦囊里面的计策便是具体的策略角色,场景就是赵云,变化的处境
选择具体策略的条件。
策略模式在程序设计中也很常用,在板桥(banq)的博客里有篇文章叫 “你还在用if else吗?”
“http://www.jdon.com/artichect/ifelse.htm”讲的很好,策略模式不但是继承的代替方案而且能很好地解决if else问题,下面举个实例来说明,怎么使用策略模式。
需求如下:
某支付系统接入以下几种商户进行充值:易宝网易,快线网银,19pay手机支付,支付宝支付,骏网一卡通,由于每家充值系统的结算比例不一样,而且同一家商户的不同充值方式也有所不同,具体系统情况比较复杂,像支付宝既有支付宝账号支付和支付宝网银支付等这些暂时不考虑,为了讲述策略模式这里简单描述,假如分为四种,手机支付,网银支付,商户账号支付和点卡支付。因为没个支付结算比例不同,所以对手续费低的做一些优惠活动,尽可能让用户使用手续费低的支付方式来充值,这样降低渠道费用,增加收入,具体优惠政策如下:
①网银充值,8.5折;
②商户充值,9折;
③手机充值,没有优惠;
④点卡充值,收取1%的渠道费;
对于一个新手的代码如下:
package strategy;
public class Example {
/**
*
*作者:alaric
*时间:2013-8-5上午11:00:06
*描述:计算用户所付金额
*/
public Double calRecharge(Double charge ,RechargeTypeEnum type ){
if(type.equals(RechargeTypeEnum.E_BANK)){
return charge*0.85;
}else if(type.equals(RechargeTypeEnum.BUSI_ACCOUNTS)){
return charge*0.90;
}else if(type.equals(RechargeTypeEnum.MOBILE)){
return charge;
}else if(type.equals(RechargeTypeEnum.CARD_RECHARGE)){
return charge+charge*0.01;
}else{
return null;
}
}
}
package strategy;
public enum RechargeTypeEnum {
E_BANK(1, "网银"),
BUSI_ACCOUNTS(2, "商户账号"),
MOBILE(3,"手机卡充值"),
CARD_RECHARGE(4,"充值卡")
;
/**
* 状态值
*/
private int value;
/**
* 类型描述
*/
private String description;
private RechargeTypeEnum(int value, String description) {
this.value = value;
this.description = description;
}
public int value() {
return value;
}
public String description() {
return description;
}
public static RechargeTypeEnum valueOf(int value) {
for(RechargeTypeEnum type : RechargeTypeEnum.values()) {
if(type.value() == value) {
return type;
}
}
return null;
}
}
可以看出上面四种不同的计算方式在一个方法内部,不利于扩展和维护,当然也不符合面向对象设计原则。对以上的代码利用策略模式进行修改,类图如下:

实例代码如下:
- package strategy.strategy;
- import strategy.RechargeTypeEnum;
- /**
- *
- *作者:alaric
- *时间:2013-8-5上午11:03:17
- *描述:策略抽象类
- */
- public interface Strategy {
- /**
- *
- *作者:alaric
- *时间:2013-8-5上午11:05:11
- *描述:策略行为方法
- */
- public Double calRecharge(Double charge ,RechargeTypeEnum type );
- }
- package strategy.strategy;
- import strategy.RechargeTypeEnum;
- /**
- *
- *作者:alaric
- *时间:2013-8-5上午11:14:23
- *描述:网银充值
- */
- public class EBankStrategy implements Strategy{
- @Override
- public Double calRecharge(Double charge, RechargeTypeEnum type) {
- return charge*0.85;
- }
- }
- package strategy.strategy;
- import strategy.RechargeTypeEnum;
- /**
- *
- *作者:alaric
- *时间:2013-8-5上午11:14:08
- *描述:商户账号充值
- */
- public class BusiAcctStrategy implements Strategy{
- @Override
- public Double calRecharge(Double charge, RechargeTypeEnum type) {
- // TODO Auto-generated method stub
- return charge*0.90;
- }
- }
- package strategy.strategy;
- import strategy.RechargeTypeEnum;
- /**
- *
- *作者:alaric
- *时间:2013-8-5上午11:14:43
- *描述:手机充值
- */
- public class MobileStrategy implements Strategy {
- @Override
- public Double calRecharge(Double charge, RechargeTypeEnum type) {
- // TODO Auto-generated method stub
- return charge;
- }
- }
- package strategy.strategy;
- import strategy.RechargeTypeEnum;
- /**
- *
- *作者:alaric
- *时间:2013-8-5上午11:13:46
- *描述:充值卡充值
- */
- public class CardStrategy implements Strategy{
- @Override
- public Double calRecharge(Double charge, RechargeTypeEnum type) {
- return charge+charge*0.01;
- }
- }
- package strategy.strategy;
- import strategy.RechargeTypeEnum;
- /**
- *
- *作者:alaric
- *时间:2013-8-5上午11:03:38
- *描述:场景类
- */
- public class Context {
- private Strategy strategy;
- public Double calRecharge(Double charge, Integer type) {
- strategy = StrategyFactory.getInstance().creator(type);
- return strategy.calRecharge(charge, RechargeTypeEnum.valueOf(type));
- }
- public Strategy getStrategy() {
- return strategy;
- }
- public void setStrategy(Strategy strategy) {
- this.strategy = strategy;
- }
- }
- package strategy.strategy;
- import java.util.HashMap;
- import java.util.Map;
- import strategy.RechargeTypeEnum;
- /**
- *
- *作者:alaric
- *时间:2013-8-5上午11:31:12
- *描述:策略工厂 使用单例模式
- */
- public class StrategyFactory {
- private static StrategyFactory factory = new StrategyFactory();
- private StrategyFactory(){
- }
- private static Map<Integer ,Strategy> strategyMap = new HashMap<>();
- static{
- strategyMap.put(RechargeTypeEnum.E_BANK.value(), new EBankStrategy());
- strategyMap.put(RechargeTypeEnum.BUSI_ACCOUNTS.value(), new BusiAcctStrategy());
- strategyMap.put(RechargeTypeEnum.MOBILE.value(), new MobileStrategy());
- strategyMap.put(RechargeTypeEnum.CARD_RECHARGE.value(), new CardStrategy());
- }
- public Strategy creator(Integer type){
- return strategyMap.get(type);
- }
- public static StrategyFactory getInstance(){
- return factory;
- }
- }
- package strategy.strategy;
- import strategy.RechargeTypeEnum;
- public class Client {
- /**
- * 作者:alaric 时间:2013-8-5上午11:33:52 描述:
- */
- public static void main(String[] args) {
- Context context = new Context();
- // 网银充值100 需要付多少
- Double money = context.calRecharge(100D,
- RechargeTypeEnum.E_BANK.value());
- System.out.println(money);
- // 商户账户充值100 需要付多少
- Double money2 = context.calRecharge(100D,
- RechargeTypeEnum.BUSI_ACCOUNTS.value());
- System.out.println(money2);
- // 手机充值100 需要付多少
- Double money3 = context.calRecharge(100D,
- RechargeTypeEnum.MOBILE.value());
- System.out.println(money3);
- // 充值卡充值100 需要付多少
- Double money4 = context.calRecharge(100D,
- RechargeTypeEnum.CARD_RECHARGE.value());
- System.out.println(money4);
- }
- }
运行结果:
85.0
90.0
100.0
101.0
【转】Java策略消除if else的更多相关文章
- 【转载】Java策略消除if else
策略(Strategy)模式:又名Policy,它的用意是定义一组算法,把它们一个个封装起来,并且使他们可以相互替换.策略模式可以独立于使用他们的客户端而变化.GOF策略模式静态结构类图如下: 通过上 ...
- Java策略模式以及来自lambda的优化
前言 设计模式是软件工程中一些问题的统一解决方案的模型,它的出现是为了解决一些普遍存在的,却不能被语言特性直接解决的问题,随着软件工程的发展,设计模式也会不断的进行更新,本文介绍的是经典设计模式 ...
- JAVA策略模式
<JAVA与模式>之策略模式 在阎宏博士的<JAVA与模式>一书中开头是这样描述策略(Strategy)模式的: 策略模式属于对象的行为模式.其用意是针对一组算法,将每一个算法 ...
- Java策略模式(Strategy模式) 之体验
<JAVA与模式>之策略模式 在阎宏博士的<JAVA与模式>一书中开头是这样描述策略(Strategy)模式的: 策略模式属于对象的行为模式.其用意是针对一组算法,将每一个算法 ...
- java策略设计模式
1.概述 策略模式定义了一系列的算法,并将每一个算法封装起来,而且使他们可以相互替换,让算法独立于使用它的客户而独立变化. 其实不要被晦涩难懂的定义所迷惑,策略设计模式实际上就是定义一个接口,只要实现 ...
- java 策略设计模式
在软件开发中也常常遇到类似的情况,实现某一个功能有多种算法或者策略,我们可以根据环境或者条件的不同选择不同的算法或者策略来完成该功能.如查找.排序等,一种常用的方法是硬编码(Hard Coding)在 ...
- java策略模式(及与工厂模式的区别)
按一般教程中出现的例子理解: 简单工厂模式:客户端传一个条件进工厂类,工厂类根据条件创建相应的产品类对象,并return给客户端,供客户端使用.即客户端使用的是工厂类生产的产品对象. 策略模式:客户端 ...
- Java策略模式(Strategy)
一.定义 定义一组算法,将每个算法都封装起来,并且使它们之间可以互换.策略模式使这些算法在客户端调用它们的时候能够互不影响地变化.(Java的TreeSet集合中,构造方法可传入具体的比较器对象以实现 ...
- java策略模式拙见
面向对象的两个基本准则: 单一职责:一个类只有一个发生变化的原因 开闭原则:对拓展开放,对修改关闭 <Java开发手册>中,有这样的规则:超过3层的 if-else 的逻辑判断代码可以使用 ...
随机推荐
- Java按位取反运算符“~”的工作原理
说明:本文参考了文章<Java按位取反运算符“~”>,链接:https://blog.csdn.net/smilecall/article/details/4245447 补充:位运算符( ...
- “全栈2019”Java多线程第四章:设置和获取线程名称
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...
- [VB6.0-->VB.NET]关于VB6.0升级到VB.NET的微软官方文档
升级流程大体是这样的: 1.用VS2008打开Vb6.0的工程(此时针对语言层面自动升级). 注: VS更新多版了(当前最新VS2017),用最新版再打开2008升级后的工程的时候还是会有自动升级,相 ...
- spring中scope的prototype与singleton区别
最近在研究单例模式,突然想起项目中以下配置,scope="singleton" 和 scope="prototype"到底有何区别呢?以下做下简要分析. < ...
- hibernate与Oracle
今天在用hibernate连接Oracle数据库进行查询时,出现一点小状况 数据库中是有数据的,而且程序本身也没有问题,可就是查不出数据,在经过几个小时的查找下,中遇找到了问题所在,那就是我Oracl ...
- Linux磁盘分区、挂在
分区基础知识分区的方式:1) mbr分区:1.最多支持四个主分区2.系统只能安装在主分区3.扩展分区要占一个主分区4.MBR最大只支持2TB,但拥有最好的兼容性2) gtp分区:1.支持无限多个主分区 ...
- LINUX云服务器 安装 nginx
什么是nginx? 是一个高性能的 HTTP 和反向代理服务器,也是一个IMAP/POP3/SMTP 代理服, 是一个asynchronousservers异步服务器 为什么使用nginx? 因为它的 ...
- 我最近用Python写了一个算法,不需要写任何规则就能自动识别一个网页的内容
我最近用Python写了一个算法,不需要写任何规则就能自动识别一个网页的内容,目前测试了300多个新闻网站的新闻页,都能准确识别
- Linux网络编程服务器模型选择之IO复用循环并发服务器
在前面我们介绍了循环服务器,并发服务器模型.简单的循环服务器每次只能处理一个请求,即处理的请求是串行的,效率过低:并发服务器可以通过创建多个进程或者是线程来并发的处理多个请求.但是当客户端增加时,就需 ...
- android studio2.3.3 模拟器 Jni函数调用C++对象,lldb调试this指针和相关变量显示无效的原因
android studio2.3.3 的版本中 Jni函数调用C++对象,对象调用相关的成员函数, lldb调试,变量跟踪窗口,this指针和相关变量显示无效的原因,但这些参数实际是有效的,只是de ...