策略模式
策略模式概述
策略模式的定义:策略模式定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化不会影响到其他客户
策略模式和简单工厂模式配合使用,可以让客户端只知道strategyContext对象,而不需要知道所有的算法实现类对象
策略模式的结构
image.png
抽象策略(Strategy)角色:这是一个抽象角色,通常由一个接口实现。此角色给出所有的具体策略类所需的接口。
具体策略(ConcreteStrategy)角色:包装了相关的算法或行为。
策略上下文(Context)角色:持有一个Strategy的引用,并且在某处调用了算法。模式的实现
策略模式的实现
1.定义一个算法抽象类或者接口
public abstract class CashSupper {
private Double money;
public abstract Double acceptCash(double money);
}
2.定义具体的算法实现类继承抽象类或实现接口
public class CashNormal extends CashSupper {
@Override
public Double acceptCash(double money) {
return money;
}
}
public class CashRebate extends CashSupper {
private Double moneyRebate;
public CashRebate(Double moneyRebate) {
this.moneyRebate = moneyRebate;
}
@Override
public Double acceptCash(double money) {
return moneyRebate * money;
}
}
public class CashReturn extends CashSupper {
private Double returnMoney;
private Double conditionMoney;
public CashReturn(Double returnMoney, Double conditionMoney) {
this.returnMoney = returnMoney;
this.conditionMoney = conditionMoney;
}
@Override
public Double acceptCash(double money) {
double resultMoney = money;
if (money >= conditionMoney) {
//满减
resultMoney = money - Math.floor(money / conditionMoney) * returnMoney;
}
return resultMoney;
}
}
3.定义策略上下文角色(此处配合简单工厂使用)
简单工厂不仅仅是一个工厂类,也可以通过构造器
package org.example.strategy;
/**
* @author
* @date 2021/3/9 10:42
**/
public class CashContext {
private CashSupper cashSupper;
//public CashContext(CashSupper cashSupper) {
//
//
// //重写构造器,让简单工厂模式与策略模式配合使用
//
// //this.cashSupper = cashSupper;
//
//}
public CashContext(String type){
switch (type){
case "正常收费":
cashSupper=new CashNormal();
break;
case "满300减100":
cashSupper=new CashReturn(100D,300D);
break;
case "打8折":
cashSupper=new CashRebate(0.8);
default:
}
}
public double getResult(double money){
return cashSupper.acceptCash(money);
}
}
4.客户端调用
package org.example.strategy;
/**
* @author
* @date 2021/3/9 10:52
**/
public class Test2 {
public static void main(String[] args) {
CashContext context = new CashContext("打8折");
System.out.println("300元打八折后价格为:" + context.getResult(300));
CashContext context1 = new CashContext("满300减100");
System.out.println("700满300减100后价格为:" + context1.getResult(700));
CashContext context2 = new CashContext("正常收费");
System.out.println("300元正常收费价格为:" + context2.getResult(300));
}
}
5.运行结果
image.png
策略模式的优缺点
优点
1.上下文和具体策略是松耦合关系。因此上下文只知道它要使用某一个实现Strategy接口类的实例,但不需要知道具体是哪一个类,连实现对象的父类都不知道,只知道一个上下文对象。
2.策略模式满足“开-闭原则”。当增加新的具体策略时,不需要修改上下文类(不搭配工厂模式的情况下)的代码,上下文就可以引用新的具体策略的实例。
缺点
因为每个具体策略类都会产生一个新类,所以会增加系统需要维护的类的数量。