概述
策略模式属于行为型设计模式,主要关注对象之间的交互和职责分配,用于解决对象之间的通信、协作和行为控制等问题。
普通策略模式
在普通的策略模式中,通常包含抽象策略接口、具体策略类和环境类这三个核心部分。以之前计算会员折扣价格的场景为例,普通策略模式的实现可能是这样的:
// 抽象策略接口
interface DiscountStrategy {
double calculateDiscount(double price);
}
// 具体策略类:普通会员折扣策略
class NormalMemberDiscount implements DiscountStrategy {
@Override
public double calculateDiscount(double price) {
return price;
}
}
// 具体策略类:高级会员折扣策略
class PremiumMemberDiscount implements DiscountStrategy {
@Override
public double calculateDiscount(double price) {
return price * 0.9;
}
}
// 环境类
class ShoppingCart {
private DiscountStrategy discountStrategy;
public void setDiscountStrategy(DiscountStrategy discountStrategy) {
this.discountStrategy = discountStrategy;
}
public double calculateFinalPrice(double price) {
if (discountStrategy == null) {
return price;
}
return discountStrategy.calculateDiscount(price);
}
}
// 客户端代码
public class NormalStrategyExample {
public static void main(String[] args) {
ShoppingCart cart = new ShoppingCart();
double originalPrice = 100.0;
// 普通会员
cart.setDiscountStrategy(new NormalMemberDiscount());
double normalPrice = cart.calculateFinalPrice(originalPrice);
System.out.println("普通会员最终价格: " + normalPrice);
// 高级会员
cart.setDiscountStrategy(new PremiumMemberDiscount());
double premiumPrice = cart.calculateFinalPrice(originalPrice);
System.out.println("高级会员最终价格: " + premiumPrice);
}
}
在策略模式里,客户端需要直接创建具体策略类的实例,然后将其传递给环境类来使用。这就要求客户端必须了解所有具体策略类的细节,包括类名和构造方式等。
增加工厂类后的策略模式
当增加了工厂类(DiscountStrategyFactory)后,代码结构发生了变化:
// 抽象策略接口
interface DiscountStrategy {
double calculateDiscount(double price);
}
// 具体策略类:普通会员折扣策略
class NormalMemberDiscount implements DiscountStrategy {
@Override
public double calculateDiscount(double price) {
return price;
}
}
// 具体策略类:高级会员折扣策略
class PremiumMemberDiscount implements DiscountStrategy {
@Override
public double calculateDiscount(double price) {
return price * 0.9;
}
}
// 策略工厂类
class DiscountStrategyFactory {
private static final java.util.Map<String, DiscountStrategy> strategyMap = new java.util.HashMap<>();
static {
strategyMap.put("Normal", new NormalMemberDiscount());
strategyMap.put("Premium", new PremiumMemberDiscount());
}
public static DiscountStrategy getStrategy(String memberLevel) {
return strategyMap.getOrDefault(memberLevel, new NormalMemberDiscount());
}
}
// 环境类
class ShoppingCart {
public double calculateFinalPrice(double price, DiscountStrategy strategy) {
if (strategy == null) {
return price;
}
return strategy.calculateDiscount(price);
}
}
// 客户端代码
public class StrategyWithFactoryExample {
public static void main(String[] args) {
ShoppingCart cart = new ShoppingCart();
double originalPrice = 100.0;
// 普通会员
DiscountStrategy normalStrategy = DiscountStrategyFactory.getStrategy("Normal");
double normalPrice = cart.calculateFinalPrice(originalPrice, normalStrategy);
System.out.println("普通会员最终价格: " + normalPrice);
// 高级会员
DiscountStrategy premiumStrategy = DiscountStrategyFactory.getStrategy("Premium");
double premiumPrice = cart.calculateFinalPrice(originalPrice, premiumStrategy);
System.out.println("高级会员最终价格: " + premiumPrice);
}
}
封装策略创建逻辑:工厂类(DiscountStrategyFactory)将具体策略类的创建和管理逻辑封装起来。客户端不再需要直接创建具体策略类的实例,而是通过工厂类提供的静态方法 getStrategy 来获取所需的策略。这样客户端只需要知道代表策略的键(如 “Normal”、“Premium”),而不需要了解具体策略类的实现细节。
提高可维护性和可扩展性:当需要新增一种会员折扣策略时,只需要在工厂类的 strategyMap 中添加新的键值对,同时创建对应的具体策略类即可,不需要修改客户端代码和环境类代码。这符合开闭原则,对扩展开放,对修改关闭。
集中管理策略:使用 Map 来存储策略,方便对所有策略进行集中管理和查找。可以通过简单的键值对操作快速定位到所需的策略,提高了代码的可读性和可维护性。
综上所述,增加工厂类是在普通策略模式基础上的一种优化,它让策略模式的实现更加灵活、可维护和可扩展。