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) 每个算法独立封装在一个类中,便于单独测试
说在后面:
本文主要是小猫看《大话设计模式》的笔记式的记录,方便以后查阅。