【引入】
简单工厂模式只是解决对象的创建问题,每次维护或者扩展都要改动这个工厂,以致代码需要重新编译部署,这不是一种好方法。而且为了创建不同的对象产品使用了switch case(或if else)的形式实现代码,这样违背了开闭原则,即对扩展开放、对修改封闭,维护的成本会随着cese(或else)的增加而增加,而本文的策略模式能较好地解决这个问题。
一、策略模式
策略模式(Strategy)是处理算法不同变体的一种行为型模式。,策略模式通过接口或抽象类提供公共的函数接口,即在抽象类中定义一个抽象方法,实现该接口的派生类将实现该抽象类中的抽象方法。策略模式把针对不同派生类一系列的具体算法分别封装在不同的派生类中,使得各个派生类给出的具体算法可以相互替换。
Strategy类,定义所有支持的算法公共接口
/**
* 抽象算法类
*/
public abstract class Strategy {
//算法方法
public abstract void AlgorithmInternet();
}
?ConcreteStrategy,封装了具体算法,继承于Strategy类
/**
* 具体算法类A
*/
public class ConcreteStrategyA extends Strategy{
//算法A实现方法
@Override
public void AlgorithmInternet() {
System.out.println("算法A实现");
}
}
/**
* 具体算法类B
*/
public class ConcreteStrategyB extends Strategy {
@Override
public void AlgorithmInternet() {
System.out.println("算法B实现");
}
}
/**
* 具体算法C
*/
public class ConcreteStrategyC extends Strategy {
@Override
public void AlgorithmInternet() {
System.out.println("算法C实现");
}
}
Context 类,用一个ConcreteStrategy来配置,维护一个对Strategy对象的引用。?
public class Context {
Strategy strategy;
public Context(Strategy strategy){
this.strategy=strategy;
}
//上下文接口
public void ContextInterface(){
strategy.AlgorithmInternet();
}
}
Client类
public class Client {
public static void main(String[] args) {
Context context;
context=new Context(new ConcreteStrategyA());
context.ContextInterface();
context=new Context(new ConcreteStrategyB());
context.ContextInterface();
context=new Context(new ConcreteStrategyC());
context.ContextInterface();
}
}
?二、策略模式应用实现
????????某商场搞促销活动,有打折活动、满减活动(两个可同时进行),并且打折的力度和满减的程度可能在今后需要进行修正。假设现在商场有三种结算方式:正常结算、打折结算、返利结算。根据策略模式的思想,我们可以设计一个这样的系统:
上下文类Context 先创建一个抽象的上下文类,获取传入的具体优惠策略,调用getPrice()来获取结果。
public class CashContext {
private CashSuper cs;
public CashContext(String type){
switch (type){
case "正常收费":
cs=new CashNormal();
break;
case "满300减100":
cs=new CashReturn("300","100");
break;
case "打8折":
cs=new CashRebate("0.8");
break;
}
}
public double getPrice(double money){
return cs.acceptCash(money);
}
}
三种具体的策略子类 商场活动一共有三种:正常收费(无活动)、打折收费、返利收费,这里只给出返利收费的实现:
父类CashSuper
public abstract class CashSuper {
public abstract double acceptCash(double money);
}
子类?
public class CashNormal extends CashSuper{
@Override
public double acceptCash(double money) {
return money;
}
}
public class CashRebate extends CashSuper {
private double moneyRebate = 1d;
public CashRebate(String moneyRebate){
this.moneyRebate=Double.parseDouble(moneyRebate);
}
@Override
public double acceptCash(double money) {
return money*moneyRebate;
}
}
public class CashReturn extends CashSuper {
private double moneyCondition = 0.0d;
private double moneyReturn = 0.0d;
public CashReturn(String moneyCondition, String moneyReturn) {
this.moneyCondition = Double.parseDouble(moneyCondition);
this.moneyReturn = Double.parseDouble(moneyReturn);
}
@Override
public double acceptCash(double money) {
double result = money;
//正数时,math.floor()为四舍五入
if (money >= moneyCondition)
result = money - Math.floor(money / moneyCondition) * moneyReturn;
return result;
}
}
客户端类
public class Client {
public static void main(String[] args) {
double total=0.0d;
CashContext context=new CashContext("正常收费");
System.out.println(context.getPrice(600));
context=new CashContext("满300减100");
System.out.println(context.getPrice(600));
}
}
优点
- 策略模式的Strategy类曾是为Context定义了一些列的可供重用的算法或行为。集成有助于析取出这些算法中的公共功能。
- 策略模式简化了单元测试,因为每个算法都有自己的类,可以通过自己的接口单独测试,可以灵活的选择需要使用的算法,减少if else语句。
- 策略模式就是用来封装算法的,但在实践中,我们可以用它来封装几乎任何类型的规则,只要在分析过程中听到需要在不同时间应用不同的业务规则,就可以考虑使用策略模式处理这种变化的可能性。
- 策略模式是为了适应不同的需求,只把变化点封装了,这个变化点就是实现不同需求的算法,但是,用户需要知道各种算法的具体情况。
缺点
- 如果具体的策略类较多的话,各个策略类之间不具有复用性。
如果文章对你有用,三连支持一下吧!!!
|