设计模式-策略模式

文章目录

前言

当我们需要在不同情境下使用不同的算法或行为时,策略模式是一个非常有用的设计模式。这种模式允许我们将不同的算法封装成独立的策略类,然后根据需要在运行时选择合适的策略。这篇博客将介绍策略模式的概念,并提供一个简单的Java代码示例来说明如何使用策略模式。

策略模式简介

策略模式是一种行为型设计模式,它允许我们定义一系列算法,将每个算法封装成一个独立的策略类,然后在运行时选择使用哪个策略。这种模式有助于将算法的实现与客户端代码分离,使代码更加灵活、可维护和可扩展。

策略模式包括以下主要角色:

  1. 环境(Context):维护一个对策略对象的引用,并在需要时调用所选策略的方法。
  2. 策略(Strategy):定义一组算法接口,具体策略类实现这个接口以提供不同的算法实现。
  3. 具体策略(Concrete Strategy):实现策略接口的具体算法类。

Java代码示例

假设我们正在开发一个电商网站,需要计算购物车中商品的总价格,但不同类型的商品可能有不同的折扣策略。我们可以使用策略模式来实现这个功能。

首先,让我们创建策略接口 PricingStrategy

java 复制代码
// 策略接口
public interface PricingStrategy {
    double calculatePrice(double originalPrice);
}

然后,我们可以创建不同的具体策略类,每个类代表一个不同的折扣策略:

java 复制代码
// 具体策略类:无折扣策略
public class NoDiscountStrategy implements PricingStrategy {
    @Override
    public double calculatePrice(double originalPrice) {
        return originalPrice;
    }
}

// 具体策略类:百分之二十折扣策略
public class TwentyPercentDiscountStrategy implements PricingStrategy {
    @Override
    public double calculatePrice(double originalPrice) {
        return originalPrice * 0.8; // 80% 的价格
    }
}

// 具体策略类:固定折扣策略
public class FixedDiscountStrategy implements PricingStrategy {
    private double discountAmount;

    public FixedDiscountStrategy(double discountAmount) {
        this.discountAmount = discountAmount;
    }

    @Override
    public double calculatePrice(double originalPrice) {
        return originalPrice - discountAmount;
    }
}

接下来,我们创建环境类 ShoppingCart,它维护一个对当前选定策略的引用,并在需要时调用该策略:

java 复制代码
public class ShoppingCart {
    private PricingStrategy pricingStrategy;

    public void setPricingStrategy(PricingStrategy pricingStrategy) {
        this.pricingStrategy = pricingStrategy;
    }

    public double checkout(double originalPrice) {
        // 使用选定的策略来计算最终价格
        double finalPrice = pricingStrategy.calculatePrice(originalPrice);
        return finalPrice;
    }
}

最后,我们可以在客户端代码中使用策略模式:

java 复制代码
public class Main {
    public static void main(String[] args) {
        ShoppingCart cart = new ShoppingCart();
        double originalPrice = 100.0;

        // 选择不同的折扣策略
        cart.setPricingStrategy(new NoDiscountStrategy());
        double finalPrice1 = cart.checkout(originalPrice);

        cart.setPricingStrategy(new TwentyPercentDiscountStrategy());
        double finalPrice2 = cart.checkout(originalPrice);

        cart.setPricingStrategy(new FixedDiscountStrategy(10.0));
        double finalPrice3 = cart.checkout(originalPrice);

        System.out.println("无折扣策略价格:" + finalPrice1);
        System.out.println("百分之二十折扣策略价格:" + finalPrice2);
        System.out.println("固定折扣策略价格:" + finalPrice3);
    }
}

这个示例演示了策略模式的使用,客户端代码可以根据需要在运行时选择不同的策略来计算最终价格。策略模式使代码更加灵活,易于维护和扩展,因为我们可以轻松添加新的折扣策略而不影响现有代码。

策略模式使用场景

策略模式在以下情况下特别有用,可以帮助组织代码并提高可维护性:

  1. 多种算法或行为选择:当一个类有多种算法或行为可以选择,并且需要在运行时动态切换它们时,策略模式非常有用。这样可以避免使用大量的条件语句来判断应该执行哪个算法。

  2. 避免条件语句的滥用:策略模式有助于减少大量的条件语句,提高代码的可读性和可维护性。替代条件语句通常是一个更好的选择。

  3. 相似的类仅在算法或行为上有差异:如果你有多个类,它们的方法实现基本相同,但在某些算法或行为上有差异,策略模式可以将共享的代码放在一个类中,并将不同的算法封装到独立的策略类中。

  4. 动态配置和扩展:策略模式允许在不修改现有代码的情况下添加新的策略,从而实现动态的配置和扩展。这对于插件系统和可扩展的应用程序非常有用。

  5. 算法族:当你有一个算法族,其中每个算法都可以看作是一个变体时,策略模式非常适用。例如,排序算法就是一个典型的算法族,其中不同的排序算法可以作为不同的策略。

  6. 测试和单元测试:使用策略模式可以更容易地进行单元测试,因为可以为每个策略编写独立的测试用例,而不需要涉及复杂的状态管理。

  7. 减少代码重复:策略模式有助于减少重复的代码。相同的策略可以在不同的上下文中共享和重用。

总之,策略模式是一种有助于提高代码的灵活性、可维护性和可扩展性的设计模式,特别适用于需要动态选择算法或行为的情况。它有助于将不同的策略封装成独立的类,降低了耦合度,使代码更易于理解和维护。

策略模式优缺点

策略模式是一种有用的设计模式,但它也有其优点和缺点,下面分别介绍:

优点:

  1. 可扩展性:策略模式允许在不修改现有代码的情况下添加新的策略。这使得系统更具可扩展性,可以轻松地引入新的算法或行为。

  2. 灵活性:策略模式提供了一种动态切换算法或行为的方式,使得在运行时可以选择不同的策略。这种灵活性对于根据不同条件应用不同的策略非常有用。

  3. 可维护性:将每个策略封装到独立的类中,有助于代码的组织和维护。策略模式有助于减少条件语句的使用,提高代码的可读性和可维护性。

  4. 单一职责原则:策略模式有助于遵循单一职责原则,因为每个策略类都只负责一个特定的算法或行为。

  5. 测试容易:由于每个策略都是独立的,因此可以更容易地编写单元测试来验证每个策略的正确性。

缺点:

  1. 类数量增加:使用策略模式会引入许多策略类,这可能会导致类的数量增加,使代码变得更加复杂。在某些情况下,这可能会导致类爆炸问题。

  2. 客户端责任:客户端需要知道各种策略的存在并选择合适的策略。这可能会增加客户端的复杂性,特别是在策略较多时。

  3. 策略切换开销:在某些情况下,动态切换策略可能会引入一些运行时开销,因为需要进行策略选择和切换。这可能会影响性能。

  4. 不适用于所有情况:策略模式并不是适用于所有问题的解决方案。它最适用于需要在运行时选择不同算法或行为的情况,而对于某些简单的情况,条件语句可能更为合适。

总的来说,策略模式是一种有助于提高代码灵活性和可维护性的设计模式,但它也可能引入一些复杂性,并且不适用于所有情况。在使用策略模式时,需要权衡其优点和缺点,确保在特定情境下使用它是合适的选择。

相关推荐
闲人一枚(学习中)1 小时前
设计模式-创建型-抽象工厂模式
设计模式·抽象工厂模式
小白不太白9504 小时前
设计模式之 观察者模式
观察者模式·设计模式
小白不太白9505 小时前
设计模式之 责任链模式
python·设计模式·责任链模式
bug管理者5 小时前
UI自动化测试中公认最佳的设计模式-POM
jenkins·策略模式
吾与谁归in5 小时前
【C#设计模式(13)——代理模式(Proxy Pattern)】
设计模式·c#·代理模式
吾与谁归in5 小时前
【C#设计模式(14)——责任链模式( Chain-of-responsibility Pattern)】
设计模式·c#·责任链模式
闲人一枚(学习中)6 小时前
设计模式-创建型-原型模式
设计模式
Iced_Sheep6 小时前
干掉 if else 之策略模式
后端·设计模式
哪 吒13 小时前
最简单的设计模式,抽象工厂模式,是否属于过度设计?
设计模式·抽象工厂模式
Theodore_102213 小时前
4 设计模式原则之接口隔离原则
java·开发语言·设计模式·java-ee·接口隔离原则·javaee