【23种设计模式】策略模式(State Pattern)

个人主页:金鳞踏雨

个人简介:大家好,我是金鳞,一个初出茅庐的Java小白

目前状况:22届普通本科毕业生,几经波折了,现在任职于一家国内大型知名日化公司,从事Java开发工作

我的博客:这里是CSDN,是我学习技术,总结知识的地方。希望和各位大佬交流,共同进步 ~

策略模式概念

策略模式(Strategy Pattern)是一种行为型设计模式,它允许在运行时根据不同的情况选择不同的算法或策略,以解决相似问题的不同变体。它可以以相同的方式调用所有的算法,减少了各种算法类使用类之间的耦合

核心思想是将算法封装成独立的策略类,使得它们可以互相替换,从而使得上下文类在运行时可以选择不同的策略来执行特定的操作。

这种灵活性使得系统更易于扩展和维护,同时也可以根据不同的需求选择最合适的算法。

简单来说,就是为了解决多重 if 的问题,优化代码结构

策略模式角色

策略设计模式中,通常涉及以下几个角色

  1. 环境(Context)/ 上下文:环境是策略模式的核心,它持有一个策略对象的引用,并在需要执行特定算法时,调用策略对象的方法。环境类负责将客户端的请求委派给具体的策略对象。

  2. 抽象策略(Strategy):抽象策略定义了策略类的公共接口,它可以是一个接口或抽象类。它声明了策略类应该实现的方法,以便环境类能够通过统一的接口调用不同的策略。

  3. 具体策略(Concrete Strategy):具体策略是抽象策略的具体实现,它实现了策略接口定义的方法,并封装了具体的算法逻辑。在不同的具体策略中,算法的实现可以有所不同。

【23种设计模式】策略模式(State Pattern)_第1张图片

策略模式代码实现

案例一:多种排序方式选择

常见的排序算法有8种,在一些特定的场景,性能可能差别很大,所以我们需要选择一种策略。

抽象策略-接口

// 抽象策略接口
public interface SortingStrategy {
    void sort(int[] array);
}

首先,我们定义了一个抽象策略接口 SortingStrategy,其中声明了一个 sort() 方法,用于对整数数组进行排序。

2个具体策略

// 具体策略类1:冒泡排序
public class BubbleSortStrategy implements SortingStrategy {
    @Override
    public void sort(int[] array) {
        // 冒泡排序算法实现
    }
}

// 具体策略类2:快速排序
public class QuickSortStrategy implements SortingStrategy {
    @Override
    public void sort(int[] array) {
        // 快速排序算法实现
    }
}

然后,我们实现了两个具体策略类 BubbleSortStrategy QuickSortStrategy ,它们分别实现了 SortingStrategy 接口,并分别实现了冒泡排序和快速排序算法的具体排序逻辑。

环境(Context)/ 上下文 

// 环境/上下文 类
public class SortContext {
    private SortingStrategy strategy;

    public SortContext(SortingStrategy strategy) {
        this.strategy = strategy;
    }

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

    public void performSort(int[] array) {
        strategy.sort(array);
    }
}

接下来,我们定义了一个环境类 SortContext,它持有一个 SortingStrategy 类型的策略对象。构造函数接受一个策略对象作为参数,并提供了 setStrategy() 方法,用于在运行时切换策略。 方法 performSort() 用于执行排序操作,它将排序任务委托给当前策略对象。

// 使用示例
public class StrategyExample {
    public static void main(String[] args) {
        int[] array = {5, 2, 8, 1, 9};

        SortContext context = new SortContext(new BubbleSortStrategy());
        context.performSort(array); // 使用冒泡排序算法

        context.setStrategy(new QuickSortStrategy());
        context.performSort(array); // 使用快速排序算法
    }
}

最后,在 StrategyExample 类的 main 方法中,我们创建了一个整数数组 array ,然后创建了一个 SortContext 对象,并初始化它使用冒泡排序策略。我们调用 performSort() 方法来执行排序操作,使用冒泡排序算法对数组进行排序。

接着,我们通过调用 setStrategy() 方法将策略切换为快速排序策略,并再次调用performSort() 方法来使用快速排序算法对数组进行排序。

案例二:聚合支付平台-余胜军课程示例代码

搭建聚合支付平台的时候,这时候需要对接很多第三方支付接口,比如支付宝、微信支付、小米支付等等。

通过传统if代码判断的,后期的维护性非常差!

public  String toPayHtml2(String payCode){
    if(payCode.equals("ali_pay")){
        return  "调用支付宝接口...";
    }
    if(payCode.equals("xiaomi_pay")){
        return  "调用小米支付接口";
    }
    if(payCode.equals("yinlian_pay")){
        return  "调用银联支付接口...";
    }
    return  "未找到该接口...";
}

这时候可以通过策略模式解决多重if判断问题。 

【23种设计模式】策略模式(State Pattern)_第2张图片

抽象策略-接口

/**
 * 抽象策略-接口
 */
public interface PayStrategy {
    String toPayHtml();
}

具体策略-阿里支付、银联支付

/**
 * 具体策略-阿里支付
 */
@Component
public class AliPayStrategy  implements PayStrategy {
    public String toPayHtml() {
        return "调用支付宝支付接口";
    }
}

/**
 * 具体策略-银联支付
 */
@Component
public class UnionPayStrategy implements PayStrategy {
    public String toPayHtml() {
        return "调用银联支付接口";
    }
}

枚举支付方式

public enum PayEnumStrategy {

    /**
     * 支付宝支付
     */
    ALI_PAY("com.harmony.strategy_pay.impl.AliPayStrategy"),
    /**
     *  银联支付
     */
    UNION_PAY("com.mayikt.strategy.impl.UnionPayStrategy");

    /**
     * class完整地址
     */
    private String className;

    PayEnumStrategy(String className) {
        this.setClassName(className);
    }

    public String getClassName() {
        return className;
    }

    public void setClassName(String className) {
        this.className = className;
    }
}

环境(Context)/ 上下文

@Component
public class PayContextStrategy {

    public  String toPayHtml(String payCode){
        // 1.验证参数
        if(StringUtils.isEmpty(payCode)){
            return  "payCode不能为空!";
        }

        // 2.获取
        PayStrategy payStrategy = StrategyFactory.getPayStrategy(payCode);
        if(payStrategy == null) {
            return "没有找到具体的策略...";
        }

        return payStrategy.toPayHtml();
    }
}

工厂类 

public class StrategyFactory {
    public static PayStrategy getPayStrategy(String strategyType) {
        try {
            // 1.获取枚举中className
            String className = PayEnumStrategy.valueOf(strategyType).getClassName();
            // 2.使用java反射技术初始化类
            return (PayStrategy) Class.forName(className).newInstance();
        } catch (Exception e) {
            return null;
        }
    }
}

使用SpringBoot的方式调用

/**
 * 启动类
 */
@SpringBootApplication
public class AppStart {
    public static void main(String[] args) {
        SpringApplication.run(AppStart.class);
    }
}

/**
 * controller
 * http://localhost:8080/toPayHtml?payCode=ALI_PAY
 */
@RestController
public class PayController {

    @Autowired
    private PayContextStrategy payContextStrategy;

    @RequestMapping("/toPayHtml")
    public String toPayHtml(String payCode) {
        return payContextStrategy.toPayHtml(payCode);
    }
}

文章到这里就结束了,如果有什么疑问的地方,可以在评论区指出~

希望能和大佬们一起努力,诸君顶峰相见

再次感谢各位小伙伴儿们的支持!!!

你可能感兴趣的:(23种设计模式,设计模式,状态模式,java)