Java设计模式之策略模式(Strategy)

1. 策略模式

策略模式,它定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户。(引自《大话设计模式》)

如果一个项目中,需要用到大量的算法就可以考虑使用策略模式。

举例说明:商场收银软件,客户购买商品,计算价格,要考虑到打折促销的情况。

上类图

抽象策略类,定义了所有支持的算法的公共接口

package main.mode.clms;

/**
 * 抽象策略类:抽象类或接口均可
 */
public interface CashStrategy {
	
	public double acceptCash(double money);
}

具体策略类,封装了具体的算法或行为

package main.mode.clms;

/**
 * 具体抽象类
 * 正常收费
 */
public class CashNormal implements CashStrategy {

	@Override
	public double acceptCash(double money) {
		return money;
	}

}
package main.mode.clms;

/**
 * 具体抽象类
 * 打折收费
 */
public class CashRebate implements CashStrategy {
	//折扣,如八五折,就是0.85
	private double rate;
	
	public CashRebate(double rate) {
		this.rate = rate;
	}
	
	@Override
	public double acceptCash(double money) {
		return money * rate;
	}

}
package main.mode.clms;

/**
 * 具体抽象类
 * 返利收费
 */
public class CashReturn implements CashStrategy {

	//如满300返20
	private double fullMoney; // 300
	private double returnMoney; // 20
	
	public CashReturn(double fullMoney, double returnMoney) {
		this.fullMoney = fullMoney;
		this.returnMoney = returnMoney;
	}
	
	@Override
	public double acceptCash(double money) {
		double result = money;
		if(money > fullMoney) {
			result = money - Math.floor(money/fullMoney) * returnMoney;
		}
		return result;
	}

}

上下文

package main.mode.clms;

/**
 * 上下文
 */
public class CashContext {

	// 引用抽象类或抽象接口
	private CashStrategy strategy;
	
	//构造器,初始化时传入策略对象
	public CashContext(CashStrategy strategy) {
		this.strategy = strategy;
	}
	
	//根据具体的策略调用具体算法的方法
	public double getResult(double money) {
		return strategy.acceptCash(money);
	}
}

测试类

package main.mode.clms;

public class StrategyTest {

	public static void main(String[] args) {
		String type = "打8折收费";
		double money = 500.0;
		double result = 0.0;
		CashStrategy strategy = null;
		switch(type) {
			case "正常收费":
				strategy = new CashNormal();
				result = strategy.acceptCash(money);
				break;
			case "打8折收费":
				strategy = new CashRebate(0.8);
				result = strategy.acceptCash(money);
				break;
			case "满200返20":
				strategy = new CashReturn(200, 20);
				result = strategy.acceptCash(money);
				break;
		}
		System.out.println(result);
	}

}

结果

可以看出在客户端测试类中需要进行判断进而选择相应的算法实现,这样不太好,可以结合简单工厂进行改进一下。

2. 简单工厂+策略模式

将客户端的判断移到上下文文件里,修改后的CashContext如下

package main.mode.clms2;

/**
 * 上下文
 */
public class CashContext {

	// 引用抽象类或抽象接口
	private CashStrategy strategy;
	
	//构造器,初始化时传入策略对象
	public CashContext(String type) {
		switch(type) {
		case "正常收费":
			this.strategy = new CashNormal();
			break;
		case "打8折收费":
			this.strategy = new CashRebate(0.8);
			break;
		case "满200返20":
			this.strategy = new CashReturn(200, 20);
			break;
		default:
			System.out.println("类型输入错误!");
			break;
		}
	}
	
	//根据具体的策略调用具体算法的方法
	public double getResult(double money) {
		return strategy.acceptCash(money);
	}
}

测试类

package main.mode.clms2;

public class StrategyTest {

	public static void main(String[] args) {
		String type = "打8折收费";
		double money = 500.0;
		CashContext cashContext = new CashContext(type);
		double result = cashContext.getResult(money);
		System.out.println(result);
	}

}

对比两种方式的客户端方法,可以看出,用简单工厂改进后的策略模式中,客户端只需要认识一个类--CashContext即可。而策略模式需要认识两个类--CashStrategy和CashRebate(打8折时),这就降低了耦合性,让具体算法彻底与客户端分离。

总结:

策略模式是一种定义一系列算法的方法,从概念上来看,所有这些算法那完成的都是相同的工作,只是实现不同,它可以以相同的方式调用所有的算法,减少了各种算法类与使用算法类之间的耦合。(引自《大话设计模式》)

(1) 策略模式封装了算法

(2) 每个算法独立封装在一个类中,便于单独测试

 

说在后面:

本文主要是小猫看《大话设计模式》的笔记式的记录,方便以后查阅。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值