什么是策略模式
策略模式(Strategy Pattern):定义一系列算法,将每一个算法封装起来,并让它们可以相互替换,是一种对象行为型模式。
策略模式的结构:
◉ Context: 环境类
◉ Strategy: 抽象策略类
◉ ConcreteStrategy: 具体策略类
例如,双十一购物节有各种优惠活动,有满减的、打折的、预售的等等,这些优惠方式其实都是一种算法,算法本身就是一种具体的策略。其中,购物节本身就是 环境类,所有的优惠方式都是抽象为 抽象策略类,每一种优惠方式就是 具体策略类,根据不同的购物情况,使用对应的优惠方式。
为什么要使用策略模式
策略模式很好的体现了 开闭原则、高内聚低耦合,可以在不修改原有业务代码的基础上,通过更换策略,或者添加策略来面对业务逻辑的变动。
通常,策略模式适用于当一个应用程序需要实现一种特定的服务或者功能,而且该程序有多种实现方式时使用。
例如,双十一的过程中,平台为了进一步增加销售额,临时添加了新的优惠方式:充值会员即可享受折上折。我们只需要继承 抽象策略类,是新一个新的 具体策略类,然后在客户端中使用即可。
当然,策略模式也有一些缺点,随着业务的扩展,代码中将会产生非常多策略类,增加了维护难度;而且,客户端必须知道所有的策略类,并自行决定使用哪一个策略类。
怎么实现策略模式
一、定义抽象策略类
//优惠方式类:抽象策略类
interface Discount {
public double calculate(double price);
}
二、定义具体策略类
(1)满减优惠策略类
// 满减优惠策略类
class FullMinusDiscount implements Discount {
// 满减金额
private final double fullMinus = 20;
public double calculate(double price) {
System.out.println("满减优惠:");
return price - fullMinus;
}
}
(2)打折优惠策略类
// 打折优惠策略类
class DiscountDiscount implements Discount {
// 折扣
private final double discount = 0.8;
public double calculate(double price) {
System.out.println("折扣优惠:");
return price * discount;
}
}
(3)预售优惠策略类
// 预售优惠策略类
class PreSellDiscount implements Discount {
// 折扣
private final double preSell = 30;
public double calculate(double price) {
System.out.println("预售优惠:");
return price - preSell;
}
}
三、定义环境类
// 定义购物环境类
class Shopping {
// 价格
private double price;
// 维持一个对抽象优惠方式类的引用
private Discount discount;
public void setPrice(double price) {
this.price = price;
}
//注入一个优惠方式类对象
public void setDiscount(Discount discount) {
this.discount = discount;
}
public double getPrice() {
//调用优惠方式类的折扣价计算方法
return discount.calculate(this.price);
}
}
四、模拟客户端调用
public class Client {
public static void main(String[] args) throws Exception {
// 实现购物环境类
Shopping context = new Shopping ();
// 执行满减优惠
context.setDiscount(new FullMinusDiscount());
context.setPrice(100);
context.getPrice();
// 执行打折优惠
context.setDiscount(new DiscountDiscount());
context.setPrice(100);
context.getPrice();
// 执行预售优惠
context.setDiscount(new PreSellDiscount());
context.setPrice(100);
context.getPrice();
}
}