策略模式【Strategy Pattern】,什么是策略模式?核心思想?角色?优缺点?应用场景?略模式实现案例?

目录


设计模式专栏目录(点击进入…)



什么是策略模式?

策略模式(Strategy Pattern)是一种行为型设计模式,它定义了一系列算法或策略,将每个算法封装起来,并且使它们可以互相替换。策略模式让算法的变化独立于使用算法的客户端代码,客户端可以在运行时灵活选择不同的策略。


策略模式核心思想

策略模式的核心思想是将一组可互换的算法封装在独立的类中,使得它们可以在不影响客户端代码的情况下互换使用。通过将算法和业务逻辑分离,策略模式使得客户端代码更具灵活性和可扩展性。


策略模式的角色

(1)策略接口(Strategy)

定义所有具体策略类都需要实现的公共接口。策略接口声明了算法的抽象方法,所有策略都必须实现该方法。

(2)具体策略类(Concrete Strategy)

每个具体策略类实现了策略接口,封装了某个具体的算法或行为。不同的策略类可以提供不同的算法实现。

(3)上下文类(Context)

上下文类维护对某个策略对象的引用,并且调用该策略的方法来执行特定的行为。上下文类通常包含设置策略的方法,允许客户端在运行时更改策略。


策略模式的优缺点

优点

(1)遵循开闭原则

新的策略可以很方便地添加,而不需要修改上下文类的代码,具有良好的扩展性。

(2)消除条件判断

通过使用不同的策略类,避免了在客户端代码中使用大量的 if-else 或 switch 语句,简化了代码结构。

(3)提高代码灵活性和可维护性

算法的实现细节对客户端透明,客户端只需设置合适的策略对象,而不需要关心具体算法的实现。

(4)代码复用性强

策略可以独立于上下文,多个上下文类可以共享相同的策略,从而提高了代码的复用性。

缺点

(1)增加了类的数量

每个策略都是一个独立的类,策略模式可能导致系统中类的数量增加,增加了代码的复杂性。

(2)客户端必须了解不同的策略

客户端需要知道有哪些策略以及如何使用这些策略,这对客户端有一定的要求。

(3)策略间可能产生冗余

不同的策略可能实现的内容相似,导致重复代码,需要通过进一步优化来避免。


策略模式的应用场景

(1)多个算法可以替换使用

当一个系统有多个算法可以互相替代,并且这些算法的选择可能会在运行时发生变化时,策略模式是非常合适的。例如,支付系统可以选择不同的支付方式,排序算法可以根据需求动态切换。

(2)消除冗长的条件判断

如果系统中有大量的 if-else 或 switch-case 语句来决定某种行为时,可以通过策略模式将这些条件判断移除,将每个行为封装为一个策略类。

(3)算法的实现需要与使用分离

当算法的实现和算法的使用场景需要分离时,策略模式可以通过将算法封装在独立的策略类中,从而达到算法与业务逻辑分离的效果。
例如:在图形绘制、文本解析等复杂场景中,不同的绘制或解析方式可以作为不同的策略。


策略模式的典型应用

(1)支付系统

支持不同支付方式(如信用卡、PayPal、银行转账等),每种支付方式可以作为一个独立的策略。

(2)排序算法选择

提供不同的排序算法(如快速排序、冒泡排序、插入排序等),在运行时根据数据特征动态选择最佳算法。

(3)加密解密

在安全通信中,可以使用不同的加密算法(如AES、RSA等),策略模式可以用来在运行时选择合适的加密算法。

(4)日志策略

日志系统可以有不同的输出方式(如控制台输出、文件输出、数据库记录等),可以根据需求在运行时选择合适的输出方式。


策略模式实现案例

刘备要到江东娶老婆了,走之前诸葛亮给赵云(伴郎)三个锦囊妙计,说是按天机拆开解决棘手问题,嘿,还别说,真是解决了大问题,搞到最后是周瑜陪了夫人又折兵呀,那咱们先看看这个场景是什么样子的。

这个场景中的要素:三个妙计,一个锦囊,一个赵云,妙计是小亮同志给的,妙计是放置在锦囊
里,俗称就是锦囊妙计嘛,那赵云就是一个干活的人,从锦囊中取出妙计,执行,然后获胜,用 JAVA 程序怎么表现这个呢?

在这里插入图片描述

1、定义一个策略接口

package com.uhhe.common.design.strategy;

/**
 * 策略接口
 *
 * @author nizhihao
 * @version 1.0.0
 * @date 2023/2/27 9:14
 */
public interface IStrategy {

    /**
     * 每个锦囊妙计都是一个可执行的算法
     */
    void operate();

}

2、具体策略类( 找乔国老帮忙、孙夫人断后、求吴国太开个绿灯)

package com.uhhe.common.design.strategy;

/**
 * 找乔国老帮忙,使孙权不能杀刘备
 *
 * @author nizhihao
 * @version 1.0.0
 * @date 2023/2/27 9:14
 */
public class BackDoor implements IStrategy {

    @Override
    public void operate() {
        System.out.println("找乔国老帮忙,让吴国太给孙权施加压力");
    }

}
package com.uhhe.common.design.strategy;

/**
 * 孙夫人断后,挡住追兵
 *
 * @author nizhihao
 * @version 1.0.0
 * @date 2023/2/27 9:15
 */
public class BlockEnemy implements IStrategy {

    @Override
    public void operate() {
        System.out.println("孙夫人断后,挡住追兵");
    }

}
package com.uhhe.common.design.strategy;

/**
 * 求吴国太开个绿灯
 *
 * @author nizhihao
 * @version 1.0.0
 * @date 2023/2/27 9:15
 */
public class GivenGreenLight implements IStrategy {

    @Override
    public void operate() {
        System.out.println("求吴国太开个绿灯,放行!");
    }

}

3、锦囊,上下文类(Context)

package com.uhhe.common.design.strategy;

/**
 * 计谋有了,那还要有锦囊
 *
 * @author nizhihao
 * @version 1.0.0
 * @date 2023/2/27 9:17
 */
public class SilkBag {

    /**
     * 构造函数,使用那个妙计
     */
    private final IStrategy strategy;

    public SilkBag(IStrategy strategy) {
        this.strategy = strategy;
    }

    /**
     * 使用计谋
     */
    public void operate() {
        this.strategy.operate();
    }

}

4、赵云使用锦囊

package com.uhhe.common.design.strategy;

/**
 * 策略模式【Strategy Pattern】
 * 场景:三个妙计,一个锦囊,一个赵云,妙计是小亮同志给的,妙计是放置在锦囊里,
 * 俗称就是锦囊妙计,那赵云就是一个干活的人,从锦囊中取出妙计,执行,然后获胜。
 *
 * @author nizhihao
 * @version 1.0.0
 * @date 2023/2/27 9:18
 */
public class ZhaoYun {

    /**
     * 赵云出场了,他根据诸葛亮给他的交代,依次拆开妙计
     * <p>
     * 问题:赵云实际不知道是那个策略呀,他只知道拆第一个锦囊,而不知道是BackDoor这个妙计
     * 咋办? 似乎这个策略模式已经把计谋名称写出来了
     * 错!BackDoor、GivenGreenLight、BlockEnemy只是一个代码,写成first、second、third,没人会说你错!
     * <p>
     * 策略模式的好处就是:体现了高内聚低耦合的特性
     * <p>
     * 策略模式:
     * ①高内聚低耦合的特点也表现出来了,
     * ②扩展性,也就是 OCP 原则,策略类可以继续增加下去,只要修改 SilkBag.java 就可以
     */
    public static void main(String[] args) {
        SilkBag silkBag;
        System.out.println("-----------刚刚到吴国的时候拆第一个-------------");
        // 拿到妙计
        silkBag = new SilkBag(new BackDoor());
        // 拆开执行
        silkBag.operate();
        System.out.println("\n");

        // 刘备乐不思蜀了,拆第二个了
        System.out.println("-----------刘备乐不思蜀了,拆第二个了-------------");
        silkBag = new SilkBag(new GivenGreenLight());
        // 执行了第二个锦囊
        silkBag.operate();
        System.out.println("\n");

        // 被孙权的小兵追了,咋办?拆第三个了
        System.out.println("-----------孙权的小兵追了,咋办?拆第三个----------");
        silkBag = new SilkBag(new BlockEnemy());
        // 孙夫人退兵
        silkBag.operate();
        System.out.println("\n");
    }

}

总结:
策略模式通过将不同的算法封装在独立的类中,使得算法可以互换使用,从而提高系统的灵活性和扩展性。策略模式非常适合那些需要动态选择算法或行为的场景,特别是在消除条件判断和提高代码复用性方面,策略模式是一个非常有效的设计模式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

未禾

您的支持是我最宝贵的财富!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值