1. Java 策略模式模式
策略模式是一种行为型设计模式,它就像是一个可以随时更换的工具箱。想象一下,您是一名厨师,面对不同的食材需要使用不同的切菜工具:
- 切肉需要用到菜刀
- 切面团需要用到面刀
- 切菜需要用到水果刀
在策略模式中:
- 环境类(Context):相当于厨师本人,可以根据需要拿起不同的刀具
- 策略接口(Strategy):相当于所有刀具的统一规范,都有"切东西"的功能
- 具体策略(ConcreteStrategy):相当于具体的刀具,各自有特定的切东西方式
让我用Java代码来展示这个厨房的例子:
// 策略接口 - 所有刀具的共同规范
interface CuttingStrategy {
void cut(String food);
}
// 具体策略 - 菜刀
class MeatKnife implements CuttingStrategy {
@Override
public void cut(String food) {
System.out.println("用菜刀切" + food + ",力量大,切得断骨头");
}
}
// 具体策略 - 面刀
class DoughKnife implements CuttingStrategy {
@Override
public void cut(String food) {
System.out.println("用面刀切" + food + ",宽大平滑,切面团不粘刀");
}
}
// 具体策略 - 水果刀
class FruitKnife implements CuttingStrategy {
@Override
public void cut(String food) {
System.out.println("用水果刀切" + food + ",小巧灵活,适合精细操作");
}
}
// 环境类 - 厨师
class Chef {
private CuttingStrategy knife;
// 换刀
public void setKnife(CuttingStrategy knife) {
this.knife = knife;
}
// 切食材
public void cutFood(String food) {
if (knife == null) {
System.out.println("请先选择一把刀!");
return;
}
knife.cut(food);
}
}
// 测试
public class StrategyPatternDemo {
public static void main(String[] args) {
Chef chef = new Chef();
// 切肉
chef.setKnife(new MeatKnife());
chef.cutFood("牛肉");
// 切面团
chef.setKnife(new DoughKnife());
chef.cutFood("面团");
// 切水果
chef.setKnife(new FruitKnife());
chef.cutFood("苹果");
}
}
策略模式的优点:
- 厨师(Context)不需要知道每把刀(Strategy)内部是如何工作的,只需要知道这把刀能切东西
- 我们可以随时给厨师添加新的刀具(新的策略),比如添加一把剪刀,而不需要修改厨师类
- 厨师可以根据需要灵活切换不同的刀具(策略)
这就是策略模式的精髓:将变化的部分(各种切东西的方法)封装起来,使它们可以互相替换,同时保持接口的统一,让使用者(厨师)能够根据不同情况选择不同的策略。
2. 策略模式综合案例:电商促销系统
1. 需求分析
背景
某电商平台需要实现一个灵活的促销系统,能够针对不同用户、不同时期应用不同的促销策略:
- 普通折扣:对商品直接打折,如8折、7折等
- 满减优惠:消费满一定金额后减免一定金额,如"满300减50"
- 会员折扣:根据会员等级提供额外折扣,如金卡会员9折,钻石会员8折
- 限时折扣:特定时间内享受更大折扣,如"双11全场5折"
- 第二件半价:购买同商品第二件半价
系统需要能够灵活切换这些促销策略,甚至组合使用,而不需要修改现有代码。
功能需求
- 能够针对订单应用不同的促销策略
- 能够动态切换和更新促销策略
- 支持未来扩展新的促销策略
- 提供清晰的接口供其他系统调用
2. 代码构建思路
我们将使用策略模式来实现这个促销系统:
- 创建一个促销策略接口
PromotionStrategy
,定义计算折扣的方法 - 为每种促销类型实现具体的策略类
- 使用策略工厂
PromotionStrategyFactory
来管理和获取策略实例 - 创建上下文类
PromotionContext
处理策略的应用 - 支持策略组合,实现复合策略
CompositePromotionStrategy
3. 完整代码实现
// 1. 定义促销策略接口
package com.ecommerce.promotion;
import java.math.BigDecimal;
public interface PromotionStrategy {
/**
* 计算促销后的价格
* @param originalPrice 原始价格
* @param order 订单信息
* @return 促销后的价格
*/
BigDecimal calculatePrice(BigDecimal originalPrice, Order order);
/**
* 获取促销描述
* @return 促销活动的描述
*/
String getDescription();
}
// 2. 订单类
package com.ecommerce.promotion;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class Order {
private String orderId;
private Long userId;
private String userLevel; // 普通用户、金卡会员、钻石会员等
private List<OrderItem> items;
private Date createTime;
public Order(String orderId, Long userId, String userLevel) {
this.orderId = orderId;
this.userId = userId;
this.userLevel = userLevel;
this.items = new ArrayList<>();
this.createTime = new Date();
}
public void addItem(OrderItem item) {
items.add(item);
}
public BigDecimal calculateTotalPrice() {
BigDecimal total = BigDecimal.ZERO;
for (OrderItem item : items) {
total = total.add(item.getPrice().multiply(new BigDecimal(item.getQuantity())));
}
return total;
}
// Getters and Setters
public String getOrderId() {
return orderId;
}
public Long getUserId() {
return userId;
}
public String getUserLevel() {
return userLevel;
}
public List<OrderItem> getItems()