设计模式之策略模式

发布于:2025-02-10 ⋅ 阅读:(20) ⋅ 点赞:(0)


策略模式

策略模式(Strategy Pattern)是一种行为设计模式,它定义了一系列算法,将每一个算法封装起来,使它们可以互相替换。策略模式使得算法可以独立于使用它的客户端变化。策略模式的主要目的是分离算法,使得算法独立于客户端而变化。

原理

策略模式包含以下几个角色:

  • 策略接口(Strategy):定义所有支持的算法的公共接口。通常使用一个抽象类或接口来定义。
  • 具体策略类(ConcreteStrategy):实现 Strategy 接口的具体算法。
  • 上下文类(Context):持有一个策略类的引用,并用于调用具体策略类中定义的算法。
  • 客户端代码(Client):使用 Context 来执行策略,并根据需求选择不同的策略实现。

实现

1、定义策略接口(Strategy):

public interface PricingStrategy {
    double calculatePrice(double price);
}

2、实现具体策略类(ConcreteStrategy):

public class RegularPricingStrategy implements PricingStrategy {
    @Override
    public double calculatePrice(double price) {
        return price;
    }
}


public class DiscountPricingStrategy implements PricingStrategy {
    private double discount;

    public DiscountPricingStrategy(double discount) {
        this.discount = discount;
    }

    @Override
    public double calculatePrice(double price) {
        return price * (1 - discount);
    }
}

public class PremiumPricingStrategy implements PricingStrategy {
    private double premium;

    public PremiumPricingStrategy(double premium) {
        this.premium = premium;
    }

    @Override
    public double calculatePrice(double price) {
        return price + premium;
    }
}

3、定义上下文类(Context):

public class PriceCalculator {
    private PricingStrategy strategy;

    public void setStrategy(PricingStrategy strategy) {
        this.strategy = strategy;
    }

    public double calculate(double price) {
        if (strategy == null) {
            throw new IllegalStateException("Pricing strategy not set");
        }
        return strategy.calculatePrice(price);
    }
}

4、测试

public class StrategyPatternDemo {
    public static void main(String[] args) {
        PriceCalculator priceCalculator = new PriceCalculator();

        // 使用 RegularPricingStrategy
        priceCalculator.setStrategy(new RegularPricingStrategy());
        double regularPrice = priceCalculator.calculate(100);
        System.out.println("Regular Price: " + regularPrice);

        // 使用 DiscountPricingStrategy
        priceCalculator.setStrategy(new DiscountPricingStrategy(0.2));
        double discountPrice = priceCalculator.calculate(100);
        System.out.println("Discount Price: " + discountPrice);

        // 使用 PremiumPricingStrategy
        priceCalculator.setStrategy(new PremiumPricingStrategy(30));
        double premiumPrice = priceCalculator.calculate(100);
        System.out.println("Premium Price: " + premiumPrice);
    }
}

5、结果

Regular Price: 100.0
Discount Price: 80.0
Premium Price: 130.0

分析

  • PricingStrategy接口:定义一个算法接口 calculatePrice,其不同实现代表不同的价格计算方式。
  • 具体策略类:RegularPricingStrategy、DiscountPricingStrategy、PremiumPricingStrategy 实现了 PricingStrategy 接口,分别执行常规价格、折扣价格和溢价价格的计算。
  • 上下文类:PriceCalculator 维护一个 PricingStrategy 类型的引用,通过 setStrategy 方法动态设置所需的策略,并通过 calculate 方法使用当前策略计算价格。
  • 客户端代码:在 main 方法中,通过设置不同的策略,使用 PriceCalculator 对象来计算价格。这样,如果要添加或者更改计算策略,只需要创建新的 ConcreteStrategy 并在上下文中设置即可,符合开闭原则。

业务实现

实际的业务场景很难让我们提前预知要用哪种策略
简单来写的话往往是这样的
1、实现

public class StrategyPatternFactory {
    public static PriceCalculator getPriceCalculator(String pct) {
        PriceCalculator priceCalculator = new PriceCalculator();

        switch (pct){
            case "Regular":
                priceCalculator.setStrategy(new RegularPricingStrategy());
                break;
            case "Discount":
                priceCalculator.setStrategy(new DiscountPricingStrategy(0.2));
                break;
            case "Premium":
                priceCalculator.setStrategy(new PremiumPricingStrategy(30));
                break;
            default:
                throw new RuntimeException("不存在策略"+pct);
        }
        return priceCalculator;
    }
}

2、测试

public class StrategyPatternDemo {
    public static void main(String[] args) {
        PriceCalculator priceCalculator = StrategyPatternFactory.getPriceCalculator("Regular");
        double regularPrice = priceCalculator.calculate(100);
        System.out.println("Price: " + regularPrice);
    }
}

3、结果

Regular Price: 100.0

这样子可以满足业务的需求了,但是每次新来一种策略,就要在原有代码上新增

public class StrategyPatternFactory {
    public static PriceCalculator getPriceCalculator(String pct) {
        PriceCalculator priceCalculator = new PriceCalculator();

        switch (pct) {
            case "Regular":
                priceCalculator.setStrategy(new RegularPricingStrategy());
                break;
            case "Discount":
                priceCalculator.setStrategy(new DiscountPricingStrategy(0.2));
                break;
            case "Premium":
                priceCalculator.setStrategy(new PremiumPricingStrategy(30));
                break;
            case "新增":
                priceCalculator.setStrategy(new AddPricingStrategy());
                break;
            default:
                throw new RuntimeException("不存在策略" + pct);
        }
        return priceCalculator;
    }
}

在运行稳定的代码进行改动是不明智的 ,可以进一步进行增强

增强

可以利用spring的特性结合工程模式,实现解耦
1、定义策略接口(Strategy):

public interface PricingStrategy {
    double calculatePrice(double price);
}

2、定义抽象策略类(AbstractStrategy):

public abstract class AbstractPricingStrategy implements PricingStrategy, InitializingBean {

    @Override
    public void afterPropertiesSet() throws Exception {
        PricingStrategyFactory.setPricingStrategy(getType(), this);
    }

    public abstract String getType();

}

3、实现具体策略

@Service
public class RegularPricingStrategy extends AbstractPricingStrategy {
    @Override
    public double calculatePrice(double price) {
        return price;
    }

    @Override
    public String getType() {
        return "Regular";
    }
}

@Service
public class DiscountPricingStrategy extends AbstractPricingStrategy {
    private double discount = 0.2;

    @Override
    public double calculatePrice(double price) {
        return price * (1 - discount);
    }

    @Override
    public String getType() {
        return "Discount";
    }
}

public class PremiumPricingStrategy extends AbstractPricingStrategy {
    private double premium = 30;

    @Override
    public double calculatePrice(double price) {
        return price + premium;
    }

    @Override
    public String getType() {
        return "Premium";
    }
}

4、定义工厂类(factory):

public class StrategyPatternFactory {

    private static Map<String, PriceCalculator> map = new HashMap<>();

    public static PriceCalculator getPriceCalculator(String pct) {
        PriceCalculator priceCalculator = map.get(pct);
        if (priceCalculator == null) {
            throw new IllegalStateException("Pricing strategy not set");
        }
        return priceCalculator;
    }

    public static void setPriceCalculator(String pct, PriceCalculator priceCalculator) {
        map.put(pct, priceCalculator);
    }
}

5、测试

    public static void main(String[] args) {
        PricingStrategy regular = PricingStrategyFactory.getPriceCalculator("Regular");
        regular.calculatePrice(100);
        PricingStrategy discount = PricingStrategyFactory.getPriceCalculator("Discount");
        discount.calculatePrice(100);
        PricingStrategy premium = PricingStrategyFactory.getPriceCalculator("Premium");
        premium.calculatePrice(100);
    }

6、结果

Regular Price: 100.0
Discount Price: 80.0
Premium Price: 130.0

以上的增强只是介绍了一下基本增强方案,大家可以根据自己的思维进一步增强,利用更多的设计模式,使得系统更加健壮


网站公告

今日签到

点亮在社区的每一天
去签到