设计模式-策略模式

设计模式专栏



模式介绍

策略模式是一种软件设计模式,它定义了一组算法(业务规则),并封装了每个算法。这族的算法可以互换代替。策略模式的目标是将算法与使用算法的客户端分离,使它们可以独立演化。

在策略模式中,抽象策略角色通常由一个接口或者抽象类实现,具体策略角色则封装了相关的算法和行为。环境角色则持有一个策略类的引用,可以选择使用不同的策略进行计算或操作。

在应用场景中,策略模式适用于需要根据不同情况选择不同算法的情况。例如,在交个人所得税的场景中,需要根据不同国家的税收政策选择不同的算税方法。

策略模式是一种灵活的设计模式,可以使代码更加可维护、可扩展和可复用。

模式特点

策略模式的优点主要包括:

    1. 策略模式提供了对开放-封闭原则的完美支持,将算法封装在独立的Strategy类中,使得它们易于切换,易于理解,易于扩展。
    1. 策略模式利用组合、委托和多态等技术和思想,可以有效地避免多重条件判断语句。
    1. 策略模式中的算法也可以复用在系统的其他地方,从而避免许多重复的复制黏贴工作。
    1. 在策略模式中利用组合和委托来让Context拥有执行算法的能力,这也是继承的一种更轻便的替代方案。

策略模式的缺点主要包括:

    1. 客户端必须知道所有的策略类,并自行决定使用哪一个策略类。
    1. 会增加策略对象。
    1. 要了解所有策略的不同,违反最少知识原则。

应用场景

策略模式的使用场景包括:

  1. 许多相关的类仅仅是行为有异:当有多个类仅在行为上有差别时,可以使用策略模式。通过将行为封装在策略类中,可以使得这些类具有一致的接口,并且可以相互替换。
  2. 需要使用一个算法的不同变体:当需要使用一个算法的不同变体时,可以使用策略模式。通过将算法封装在策略类中,可以使得算法独立于使用它的客户端,并且可以根据需要选择不同的算法。
  3. 算法使用客户不应该知道的数据:当算法使用客户不应该知道的数据时,可以使用策略模式。通过将数据封装在策略类中,可以保护数据的安全性,并且可以使得算法和数据相互独立。
  4. 一个类定义了多种行为,并且这些行为在类的操作中以多个条件语句的形式出现:当一个类定义了多种行为,并且这些行为在类的操作中以多个条件语句的形式出现时,可以使用策略模式。通过将行为封装在策略类中,可以减少条件语句的数量,并且可以使得代码更加清晰和易于维护。

策略模式适用于需要根据不同情况选择不同算法的情况。它可以使代码更加灵活、可维护、可扩展和可复用。

策略模式和工厂方法模式的区别

策略模式和工厂方法模式的主要区别在于它们的目的、使用场景和结构上。

  1. 目的 :策略模式的主要目的是为了解决算法的切换与扩展,更简洁的说是定义策略族,分别封装起来,让他们之间可以相互替换,策略模式让策略的变化独立于使用策略的客户。而工厂方法模式的主要目的是创建型设计模式,它接受指令,创建出符合要求的实例。
  2. 使用场景 :策略模式适用于需要根据不同情况选择不同算法的情况。它可以使代码更加灵活、可维护、可扩展和可复用。而工厂方法模式则适用于当一个类希望通过内部配置来创建不同的对象时。
  3. 结构 :策略模式通常包含抽象策略类、具体策略类和环境类。抽象策略类定义了算法的通用接口,具体策略类实现了抽象策略类定义的算法,环境类则持有具体策略类的实例,并调用具体策略类的算法。而工厂方法模式则包含抽象工厂类、具体工厂类和产品类。抽象工厂类定义了创建产品的接口,具体工厂类实现了抽象工厂类定义的创建产品的接口,产品类则是需要创建的对象。

策略模式和工厂方法模式都是常见的软件设计模式,它们在不同的场景下有着不同的应用。

代码示例

Java实现策略模式

下面是一个简单的Java实现策略模式的示例:

java 复制代码
// 抽象策略接口
interface PaymentStrategy {
    void pay(double amount);
}

// 具体策略1:使用信用卡支付
class CreditCardPayment implements PaymentStrategy {
    private String name;
    private String cardNumber;
    private String cvv;
    private String expirationDate;

    public CreditCardPayment(String name, String cardNumber, String cvv, String expirationDate) {
        this.name = name;
        this.cardNumber = cardNumber;
        this.cvv = cvv;
        this.expirationDate = expirationDate;
    }

    @Override
    public void pay(double amount) {
        System.out.println("Paying " + amount + " dollars with credit card.");
        // 实现信用卡支付的具体逻辑
    }
}

// 具体策略2:使用PayPal支付
class PayPalPayment implements PaymentStrategy {
    private String email;
    private String password;

    public PayPalPayment(String email, String password) {
        this.email = email;
        this.password = password;
    }

    @Override
    public void pay(double amount) {
        System.out.println("Paying " + amount + " dollars with PayPal.");
        // 实现PayPal支付的具体逻辑
    }
}

// 环境类,持有具体策略的实例,并调用具体策略的算法
class PaymentContext {
    private PaymentStrategy strategy;

    public PaymentContext(PaymentStrategy strategy) {
        this.strategy = strategy;
    }

    public void executeStrategy(double amount) {
        strategy.pay(amount);
    }
}

// 客户端代码,使用环境类来执行具体的策略算法
public class Client {
    public static void main(String[] args) {
        PaymentContext context = new PaymentContext(new CreditCardPayment("John Doe", "1234 5678 9012 3456", "123", "12/24"));
        context.executeStrategy(100.0); // 使用信用卡支付100美元
        context.executeStrategy(50.0); // 使用PayPal支付50美元
    }
}

在这个示例中,我们定义了一个抽象策略接口PaymentStrategy,它包含了支付操作的抽象方法pay。然后我们实现了两个具体策略类CreditCardPaymentPayPalPayment,它们分别实现了信用卡支付和PayPal支付的具体逻辑。接着我们定义了一个环境类PaymentContext,它持有具体策略的实例,并提供了执行策略的方法executeStrategy。最后在客户端代码中,我们创建了一个环境类的实例,并使用它来执行具体的策略算法。

python实现策略模式

下面是一个使用Python实现策略模式的示例:

python 复制代码
# 抽象策略接口
class PaymentStrategy:
    def pay(self, amount):
        pass

# 具体策略1:使用信用卡支付
class CreditCardPayment(PaymentStrategy):
    def __init__(self, name, card_number, cvv, expiration_date):
        self.name = name
        self.card_number = card_number
        self.cvv = cvv
        self.expiration_date = expiration_date
    
    def pay(self, amount):
        print("Paying {} dollars with credit card.".format(amount))
        # 实现信用卡支付的具体逻辑

# 具体策略2:使用PayPal支付
class PayPalPayment(PaymentStrategy):
    def __init__(self, email, password):
        self.email = email
        self.password = password
    
    def pay(self, amount):
        print("Paying {} dollars with PayPal.".format(amount))
        # 实现PayPal支付的具体逻辑

# 环境类,持有具体策略的实例,并调用具体策略的算法
class PaymentContext:
    def __init__(self, strategy):
        self.strategy = strategy
    
    def execute_strategy(self, amount):
        self.strategy.pay(amount)

# 客户端代码,使用环境类来执行具体的策略算法
def client_code():
    credit_card_payment = CreditCardPayment("John Doe", "1234 5678 9012 3456", "123", "12/24")
    payment_context = PaymentContext(credit_card_payment)
    payment_context.execute_strategy(100.0) # 使用信用卡支付100美元
    
    paypal_payment = PayPalPayment("john.doe@example.com", "password")
    payment_context = PaymentContext(paypal_payment)
    payment_context.execute_strategy(50.0) # 使用PayPal支付50美元

if __name__ == "__main__":
    client_code()

在这个示例中,我们定义了一个抽象策略接口PaymentStrategy,它包含了支付操作的抽象方法pay。然后我们实现了两个具体策略类CreditCardPaymentPayPalPayment,它们分别实现了信用卡支付和PayPal支付的具体逻辑。接着我们定义了一个环境类PaymentContext,它持有具体策略的实例,并提供了执行策略的方法execute_strategy。最后在客户端代码中,我们创建了一个环境类的实例,并使用它来执行具体的策略算法。

策略模式在spring中的应用

策略模式在Spring框架中有广泛的应用。Spring框架提供了许多策略接口和实现类,用于处理各种业务逻辑和数据访问操作。以下是一些策略模式在Spring中的应用示例:

  1. 数据访问策略 :Spring框架提供了多种数据访问实现,如JDBC、Hibernate、MyBatis等。你可以使用抽象数据访问策略接口org.springframework.jdbc.core.JdbcTemplate,为不同的数据库实现不同的数据访问策略。例如,你可以定义一个继承了JdbcTemplate的自定义类,根据需要选择使用哪种数据库连接池、异常处理机制等。
  2. 事务管理策略 :Spring框架支持声明式事务管理,通过@Transactional注解实现。你可以根据不同的业务需求,选择不同的事务管理策略,如传播行为、隔离级别等。这些策略可以通过配置文件或注解的方式进行配置。
  3. 缓存策略 :Spring框架提供了多种缓存实现,如EhCache、Redis等。你可以使用抽象缓存策略接口org.springframework.cache.CacheManager,为不同的缓存实现定义不同的缓存策略。例如,你可以定义一个继承了CacheManager的自定义类,根据需要选择使用哪种缓存实现、缓存策略等。
  4. 安全策略 :Spring框架提供了多种安全认证和授权实现,如Spring Security。你可以使用抽象安全策略接口org.springframework.security.access.AccessDecisionManager,为不同的安全需求定义不同的安全策略。例如,你可以定义一个继承了AccessDecisionManager的自定义类,根据需要选择使用哪种认证方式、授权规则等。

这些示例只是Spring框架中策略模式应用的一部分。实际上,Spring框架中的许多组件和模块都采用了策略模式,以提供灵活性和可扩展性。通过使用策略模式,你可以根据不同的业务需求和场景,选择合适的策略实现类或自定义策略类,以满足特定的功能需求。

设计模式-原型模式
设计模式-建造者模式
设计模式-工厂模式
设计模式-单例模式
设计模式-适配器模式
设计模式-装饰器模式
设计模式-代理模式
设计模式-外观模式
设计模式-桥接模式
设计模式-组合模式
设计模式-享元模式


相关推荐
考虑考虑7 小时前
Jpa使用union all
java·spring boot·后端
用户3721574261357 小时前
Java 实现 Excel 与 TXT 文本高效互转
java
浮游本尊8 小时前
Java学习第22天 - 云原生与容器化
java
渣哥10 小时前
原来 Java 里线程安全集合有这么多种
java
间彧10 小时前
Spring Boot集成Spring Security完整指南
java
间彧10 小时前
Spring Secutiy基本原理及工作流程
java
数据智能老司机11 小时前
精通 Python 设计模式——创建型设计模式
python·设计模式·架构
Java水解11 小时前
JAVA经典面试题附答案(持续更新版)
java·后端·面试
数据智能老司机12 小时前
精通 Python 设计模式——SOLID 原则
python·设计模式·架构
洛小豆14 小时前
在Java中,Integer.parseInt和Integer.valueOf有什么区别
java·后端·面试