设计模式--策略模式

策略(Strategy)模式

本质:分离算法,选择实现。

策略模式:针对一组算法,将每一个算法封装到具有共同接口的独立的类中,使得它们可以互换。

使用策略模式可以把行为和环境分割开来。环境类Context负责查询要做什么,各种算法则在具体策略类(ConcreteStrategy)中提供。

当出现新的促销折扣或现有的折扣政策出现变化时,只需要实现新的策略类,并在客户端登记即可。

在这里插入图片描述

环境(Context):有一个Strategy类的引用,和具体的策略类交互。
抽象策略(Strategy)角色:一个接口或抽象类,给出规范。
具体策略(ConcreteStrategy)角色:具体算法或行为。

上下文使用具体策略对象,具体策略对象也可以从上下文获取所需要的数据,因此,可以将上下文当做参数传递给具体策略对象。

上下文封装着具体策略对象需要的数据,具体策略对象通过回调上下文的方法来获取这些数据。

这里为了方便理解,我们就拿刚学习Java的时候使用计算方法来说吧。
在使用计算器进行计算的时候,会经常用到加减乘除方法。如果我们想得到两个数字相加的和,我们需要用到“+”符号,得到相减的差,需要用到“-”符号等等。虽然我们可以通过字符串比较使用if/else写成通用方法,但是计算的符号每次增加,我们就不得不加在原先的方法中进行增加相应的代码,如果后续计算方法增加、修改或删除,那么会使后续的维护变得困难。
但是在这些方法中,我们发现其基本方法是固定的,这时我们就可以通过策略模式来进行开发,可以有效避免通过if/else来进行判断,即使后续增加其他的计算规则也可灵活进行调整。

策略模式的收银软件

抽象类CashStrategy:定义收银的计算方法

CashContext角色:引用CashStrategy的一个实例

CashNormal是正常收费,CashRebate是打折收费,CashReturn是返利收费,是三个具体策略,客户端判断决定选择使用哪一个。

public abstract class CashStrategy {
	
	public abstract double acceptCash(double money);

}
public class CashContext {
	private CashStrategy cs;

	public CashContext(CashStrategy cs) {
		this.cs = cs;
	}
	
	public double getResult(double money) {
		return cs.acceptCash(money);
	}

}

public class CashNormal extends CashStrategy{

	@Override
	public double acceptCash(double money) {
		// TODO Auto-generated method stub
		return money;
	}
	
}
public class CashRebate extends CashStrategy{
	private double moneyRebate=0;
	
	public CashRebate(double moneyRebate) {
		this.moneyRebate = moneyRebate;
	}

	@Override
	public double acceptCash(double money) {
		return money*moneyRebate;
	}
	
}
public class CashRetrun extends CashStrategy{

	private double moneyCondition=0.0;
	private double moneyReturn=0.0;
	
	
	public CashRetrun(double moneyCondition, double moneyReturn) {
		this.moneyCondition = moneyCondition;
		this.moneyReturn = moneyReturn;
	}

	@Override
	public double acceptCash(double money) {
		double result=money;
		if(money>moneyCondition)
			result=money-Math.floor(money/moneyCondition)*moneyReturn;
			//floor():向下取整
		return result;
	}

}
import java.util.Scanner;

public class Test {
	
	static double total=0.0;
	public static void main(String[] args) {
		Scanner cin=new Scanner(System.in);
		System.out.println("请输入优惠方案:");
		String str=cin.next();
		CashContext cc=null;
		
		switch(str) {
		case "正常收费":
			cc=new CashContext(new CashNormal());
			break;
		case "满300返100":
			cc=new CashContext(new CashRetrun(300,100));
			break;
		case "打8折":
			cc=new CashContext(new CashRebate(0.8));
			break;
		}
		
		System.out.println("请输入消费金额:");
		double price=cin.nextInt();
		total=cc.getResult(price);
		
		System.out.println("最后共消费:"+total);
		cin.close();
	}

}

策略模式的特点

  • 功能:具体算法从具体业务处理中独立
  • 多个if-else出现考虑使用策略模式
  • 策略算法是形同行为的不同实现(多态)
  • 客户端选择,上下文来具体实现策略算法

使用场景

同一个算法,有很多不同的实现情况。

一个定义了很多行为的类,通过多个if-else语句来选择这些行为的情况

优缺点

优点:

  • 避免让客户端涉及到重要算法和数据
  • 避免使用难以维护的多重条件选择语句
  • 易扩展

缺点:

  • 判断逻辑在客户端,需求改变时,要更改客户端的程序。
  • 客户端必须知道所有的策略类,并自行决定使用哪一个策略类。这就意味着客户端必须理解这些算法的区别,以便适时选择恰当的算法类。
  • 增加了对象的数目
  • 只适合扁平的算法结构

策略模式和工厂模式的结合

把分支判断从客户端移动到到环境CashContext类中,此时CashContext相当于一个工厂,选择实例化不同的具体策略类

public class CashContext {
	private CashStrategy cs=null;
	
	//简单工厂:将实例化具体策略从客户端放入Context类中
	public CashContext(String type) {
		switch(type) {
		case "正常收费":
			CashNormal cs0=new CashNormal();
			cs=cs0;
			break;
		case "满300返100":
			CashRetrun cr1=new CashRetrun(300,100);
			cs=cr1;
			break;
		case "打8折":
			CashRebate cr2=new CashRebate(0.8);
			cs=cr2;
			break;
		}
		
	}
	
	public double getResult(double money) {
		return cs.acceptCash(money);
	}

}

import java.util.Scanner;

public class Test {

	public static void main(String[] args) {
		Scanner cin=new Scanner(System.in);
		
		System.out.println("请输入优惠方案:");
		String str=cin.next();
		CashContext cc=new CashContext(str);
		
		System.out.println("请输入消费金额:");
		double price=cin.nextInt();
		double total=cc.getResult(price);
		
		System.out.println("最终消费:"+total);
		cin.close();
	}

}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值