今天是:
带着程序的旅程,每一行代码都是你前进的一步,每个错误都是你成长的机会,最终,你将抵达你的目的地。
title

策略模式(Strategy Pattern)

定义

策略模式允许在运行时选择算法的行为。它允许你定义一系列算法,并将每个算法封装在单独的类中,使它们可以互相替换。这样,客户端可以在不改变其使用方式的情况下选择要使用的算法。这种模式有助于提高代码的灵活性和可维护性,因为它将不同的算法逻辑与主要的业务逻辑分离开来。

意图

使算法的选择与使用者(客户端)的解耦。它允许在不修改客户端代码的情况下动态地改变或切换算法,通过封装不同的算法,使得它们可以相互替换。这样的设计使得系统更灵活、可扩展,并且更容易维护,因为新增、修改或删除算法不会对客户端造成影响。策略模式还有助于避免代码中大量的条件判断语句,提高了代码的可读性和可维护性。

参与者(角色)​​​​​​

  • Context(上下文):上下文是策略模式的主要组成部分,它持有一个对策略接口的引用,并在运行时可以切换不同的具体策略。上下文通常会将客户端请求委派给所选的策略对象执行。

  • Strategy(策略):策略是一个接口或抽象类,它定义了一系列算法的通用接口。所有具体策略类都必须实现这个接口,确保它们拥有相同的行为。

  • Concrete Strategies(具体策略):具体策略是实现了策略接口的具体类。每个具体策略类都封装了一个特定的算法。

举例

已使用不同的支付方式为例

类图:

这个例子中对应类的角色如下:

  • Context(上下文):PayContext

  • Strategy(策略):PayStrategy

  • Concrete Strategies(具体策略):AliPay,CreditCardPay,WeiXinPay

 

PayStrategy接口

public interface PayStrategy {
     void pay(double amount);
}

 

PayContext类

public class PayContext {

    private PayStrategy payStrategy;


    public PayContext(PayStrategy payStrategy) {
        this.payStrategy = payStrategy;
    }

    public void changeStrategy(PayStrategy payStrategy) {
        this.payStrategy = payStrategy;
    }


    public  void execute(double amount){
        payStrategy.pay(amount);
    }
}

 

CreditCardPay支付类

@Slf4j
public class CreditCardPay implements PayStrategy {

    @Override
    public void pay(double amount) {
        log.info("使用信用卡支付了:{}元",amount);
    }
}

 

WeiXinPay类

@Slf4j
public class WeiXinPay implements PayStrategy {

    @Override
    public void pay(double amount) {
        log.info("使用微信支付了:{}元",amount);
    }
}

 

AliPay支付类

@Slf4j
public class AliPay implements PayStrategy {


    @Override
    public void pay(double amount) {
      log.info("使用支付宝支付了:{}元",amount);
    }
}

 

测试

public class App {
    public static void main(String[] args) {

        AliPay aliPay = new AliPay();
        PayContext context = new PayContext(aliPay);
        context.execute(100);
        context.changeStrategy(new WeiXinPay());
        context.execute(200);
        context.changeStrategy(new CreditCardPay());
        context.execute(300);
    }
}

 

优点

  1. 灵活性: 策略模式允许在运行时动态切换算法或策略,无需修改客户端代码,提供了灵活性和可维护性。

  2. 可扩展性: 新的策略可以很容易地添加到系统中,不会影响现有的代码结构,从而提供了可扩展性。

  3. 代码复用: 通过策略模式,不同的算法逻辑被封装在独立的策略类中,可以在多个地方重复使用,促进了代码复用。

  4. 减少条件判断: 策略模式可以避免大量的条件判断语句,提高了代码的可读性和可维护性。

缺点

  1. 类数量增加: 每个策略都需要一个单独的类,可能会导致类的数量增加,尤其是当策略较多时,会增加代码复杂度。

  2. 客户端必须知道所有的策略: 客户端必须了解所有可用的策略并选择使用哪一个,这可能会增加客户端的复杂性。

  3. 上下文与策略的耦合: 在某些情况下,上下文对象与特定的策略类紧密耦合,可能导致修改上下文对象以适应新策略的引入。

策略模式的应用

springSecuriy认证策略。spring-ouauth2-原理

 

//设置不同的认证策略

    void configure(HttpSecurity httpSecurity) {
        AuthenticationManager authenticationManager = (AuthenticationManager)httpSecurity.getSharedObject(AuthenticationManager.class);
        AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils.getAuthorizationServerSettings(httpSecurity);
        OAuth2AuthorizationEndpointFilter authorizationEndpointFilter = new OAuth2AuthorizationEndpointFilter(authenticationManager, authorizationServerSettings.getAuthorizationEndpoint());
        List<AuthenticationConverter> authenticationConverters = createDefaultAuthenticationConverters();
        if (!this.authorizationRequestConverters.isEmpty()) {
            authenticationConverters.addAll(0, this.authorizationRequestConverters);
        }

        this.authorizationRequestConvertersConsumer.accept(authenticationConverters);
        authorizationEndpointFilter.setAuthenticationConverter(new DelegatingAuthenticationConverter(authenticationConverters));
        if (this.authorizationResponseHandler != null) {
            authorizationEndpointFilter.setAuthenticationSuccessHandler(this.authorizationResponseHandler);
        }

        if (this.errorResponseHandler != null) {
            authorizationEndpointFilter.setAuthenticationFailureHandler(this.errorResponseHandler);
        }

        if (StringUtils.hasText(this.consentPage)) {
            authorizationEndpointFilter.setConsentPage(this.consentPage);
        }

        if (this.sessionAuthenticationStrategy != null) {
            authorizationEndpointFilter.setSessionAuthenticationStrategy(this.sessionAuthenticationStrategy);
        }

        httpSecurity.addFilterBefore((Filter)this.postProcess(authorizationEndpointFilter), AbstractPreAuthenticatedProcessingFilter.class);
    }

 

分享到:

专栏

类型标签

网站访问总量