如果某个系统需要不同的算法(如超市收银的优惠算法),那么可以把这些算法独立出来,使之之间可以相互替换,这种模式叫做策略模式
策略模式
如果某个系统需要不同的算法(如超市收银的优惠算法),那么可以把这些算法独立出来,使之之间可以相互替换,这种模式叫做策略模式,它同样具有三个角色:
- 环境角色:使用策略的类
- 抽象策略角色:策略共有的抽象类或接口
- 具体策略角色:具体的策略的实现
策略模式的优缺点
优点:
- 需要新的算法时,只需要拓展策略,而不需要修改原有代码,符合开闭原则。
- 避免出现过多判断分支,提高代码可读性。
- 算法间可方便的进行继承,替换。
缺点:
- 客户端必须熟悉所有算法,并自行决定使用哪个策略
- 策略模式将造成产生很多策略类,可以通过使用享元模式在一定程度上减少对象的数量。
适用场景
一个系统中有很多类,这些类之间只有行为表现不同时,可以使用策略模式,策略模式在实例化策略时可以配合使用简单工厂。
例:
比如一个收银系统,结算时有不同的优惠策略,如 九折, 五折,满100减10等,这些不同的优惠策略便是”具体策略角色“,而收银系统就是 ”环境角色“,还需要定义一个 ”抽象策略角色“:
package pers.junebao.strategy_mode.discount; | |
// 抽象策略角色 | |
public interface BaseDiscountStrategy { | |
double preferentialAlgorithm(double money); | |
} | |
package pers.junebao.strategy_mode.discount; | |
// 折扣优惠(具体策略角色) | |
public class Discount implements BaseDiscountStrategy { | |
private double discount; | |
public Discount(double discount) { | |
// Discount(double discount) { | |
if(discount > 1) | |
discount = 1; | |
else if(discount < 0) | |
discount = 0.1; | |
this.discount = discount; | |
} | |
public double preferentialAlgorithm(double money) { | |
return money * this.discount; | |
} | |
} | |
package pers.junebao.strategy_mode.discount; | |
// 满减优惠(具体策略角色) | |
public class FullReduction implements BaseDiscountStrategy { | |
private double discountPrice; //优惠金额 | |
private double baseline; // 满减条件 | |
FullReduction(double baseline, double price) { | |
this.baseline = baseline; | |
this.discountPrice = price; | |
} | |
public double preferentialAlgorithm(double money) { | |
if(money >= this.baseline) | |
money -= this.discountPrice; | |
return money; | |
} | |
} |
这样,环境角色就可以自己决定使用哪种策略而不用修改代码了
package pers.junebao.strategy_mode; | |
import pers.junebao.strategy_mode.discount.BaseDiscountStrategy; | |
import pers.junebao.strategy_mode.discount.Discount; | |
public class CashRegisterSystem { | |
public static void main(String[] args) { | |
BaseDiscountStrategy ds = new Discount(0.9); | |
double purchasingPrice = 1500; | |
double amountsPayable = ds.preferentialAlgorithm(purchasingPrice); | |
System.out.println(amountsPayable); | |
} | |
} |
对于这些具体策略,可以使用简单工厂,进一步屏蔽策略的具体细节
package pers.junebao.strategy_mode.discount; | |
public class StrategyFactory { | |
public static BaseDiscountStrategy getDiscountStrategy(String name) { | |
BaseDiscountStrategy result = null; | |
switch (name){ | |
case "九折":{ | |
result = new Discount(0.9); | |
break; | |
} | |
case "五折": { | |
result = new Discount(0.5); | |
break; | |
} | |
case "满100减10": { | |
result = new FullReduction(100, 10); | |
break; | |
} | |
case "满1000减200": { | |
result = new FullReduction(1000, 200); | |
break; | |
} | |
default: | |
result = new OriginalPrice(); | |
} | |
return result; | |
} | |
} | |
BaseDiscountStrategy ds = StrategyFactory.getDiscountStrategy("满1000减200"); |