策略模式
它定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户。
代码示例
需求
实现一个简易收银软件
UML
策略模式机构图
代码
package strategyPattern;
/**
* Created by yutong on 2018/11/6
* 抽象算法类
*/
abstract class CashFee {
public abstract double getResult(double money);
}
package strategyPattern;
/**
* Created by yutong on 2018/11/6
* 正常收费
*/
public class CashNormal extends CashFee{
public CashNormal() {
}
@Override
public double getResult(double money) {
return money;
}
}
package strategyPattern;
package strategyPattern;
/**
* Created by yutong on 2018/11/6
* 打折收费类
*/
public class CashRebate extends CashFee {
private double moneyRebate;
public CashRebate(double moneyRebate) {
this.moneyRebate = moneyRebate;
}
@Override
public double getResult(double money) {
return money*moneyRebate;
}
}
package strategyPattern;
/**
* Created by yutong on 2018/11/6
* 返利收费
*/
public class CashReturn extends CashFee {
private double basePrice;
private double returnPrice;
public CashReturn(double basePrice,double returnPrice) {
this.basePrice = basePrice;
this.returnPrice = returnPrice;
}
@Override
public double getResult(double money) {
double result = 0;
if (money > basePrice){
result = money - Math.floor(money/basePrice)*returnPrice;
}
return result;
}
}
package strategyPattern;
/**
* Created by yutong on 2018/11/6
* 上下文类
*/
public class CashContext {
private CashFee cashFee;
public CashContext(int type,double basePrice,double returnPrice,double rebatePrice) {
switch (type){
case 1://正常收费
this.cashFee = new CashNormal();
break;
case 2:
this.cashFee = new CashReturn(basePrice,returnPrice);
break;
case 3:
this.cashFee = new CashRebate(rebatePrice);
break;
}
}
public double acceptCash(double money){
return cashFee.getResult(money);
}
}
package strategyPattern;
import java.util.Scanner;
/**
* Created by yutong on 2018/11/6
* 结算客户端类
*/
public class CashClient {
public static void main(String[] args){
System.out.println("=======这是一款神奇的收银软件=======");
Scanner scanner = new Scanner(System.in);
System.out.println("请输入您要购买的商品原价:");
String originalPrice = scanner.nextLine();
System.out.println("请选择要优惠的活动:1,正常收费;2,满300减100;3,打8折");
String seletItem = scanner.nextLine();
double result = 0;
if ("1".equals(seletItem)){
CashContext cashContext = new CashContext(1,0,0,0);
result = cashContext.acceptCash(Double.parseDouble(originalPrice));
}
if ("2".equals(seletItem)){
CashContext cashContext = new CashContext(2,300,100,0);
result = cashContext.acceptCash(Double.parseDouble(originalPrice));
}
if ("3".equals(seletItem)){
CashContext cashContext = new CashContext(3,0,0,0.8);
result = cashContext.acceptCash(Double.parseDouble(originalPrice));
}
System.out.println("您需要付款:"+result);
}
}
总结
策略模式是一种定义一系列算法的方法,从概念上来看,所有这些算法完成的都是相同的工作,只是实现不同,他可以以相同的方式调用所有的算法,减少了算法类与使用算法类之间的耦合。
对于客户端而言: 简单工厂设计模式, 客户端需要知道两个类, 而简单工厂+策略设计模式, 客户端只需要知道一个类, 减低了耦合性.
使用场景
策略模式就是用来封装算法的,但在实践中,我们发现可以用它来封装几乎任何类型的规则,只要在分析过程中听到需要在不同时间应用不同的业务规则,就可以考虑使用策略模式处理这种变化的可能性。
多个算法可实现类似功能,若将所有方法写在一个sortUtils里面会导致难以维护,代码复杂。所以策略模式考虑如何让算法和对象分开来,使得算法可以独立于使用它的客户而变化。具体的方案是把一个类中经常改变或者将来可能改变的部分提取出来,作为一个接口,然后在类中包含这个对象的实例,这样类的实例在运行时就可以随意调用实现了这个接口的类的行为。
优点
1、可以动态的改变对象的行为
缺点
1、客户端必须知道所有的策略类,并自行决定使用哪一个策略类
2、策略模式将造成产生很多策略类