使用策略模式优化你的代码

使用,策略,模式,优化,代码 · 浏览次数 : 4

小编点评

**策略模式简介** 策略模式是一种对象行为型模式,它定义了一系列算法的接口,并允许使用不同的算法实现类来实现这些算法。 **核心概念** * **策略接口:**定义了一系列算法的接口,每个算法实现类必须实现该接口的方法。 * **具体策略角色:**实现策略接口的具体实现类,每个策略角色对应一个特定的算法。 * **上下文:**一个抽象对象,它定义了策略接口的通用方法,并在子类中实现特定策略的逻辑。 **使用策略模式的优点** * **代码可扩展性:**可以使用不同的算法实现类,从而扩展代码的可扩展性。 * **代码可维护性:**使用策略模式可以更容易地维护代码,因为你可以通过更改策略接口来更改算法。 * **提高效率:**可以使用不同的算法实现类,以优化代码的性能。 **策略模式的缺点** * **复杂性:**策略模式可能比其他设计模式更复杂,因为它需要定义和维护多个算法接口。 * **测试复杂性:**测试策略模式可能更加复杂,因为你需要在测试过程中设置多个策略。 **示例** ```java // 策略接口 public interface PointSendInterface { void sendPoint(Integer points); } // 具体策略角色,实现课程评论和学习课程的积分发放 class CourseCommentPointSend implements PointSendInterface { @Override public void sendPoint(Integer points) { // 发送评论积分逻辑 } } // 具体策略角色,实现电子书阅读的积分发放 class EbookReadPointSend implements PointSendInterface { @Override public void sendPoint(Integer points) { // 发送阅读积分逻辑 } } ``` **总结** 策略模式是一种灵活且易于维护的 design pattern,它可以用于解决代码中的重复逻辑问题。然而,它也可能比其他设计模式更复杂,需要更详细的设计。

正文

策略模式简介

策略模式(Strategy Pattern:Define a family of algorithms,encapsulate each one,and make them interchangeable.)中文解释为:定义一组算法,然后将这些算法封装起来,以便它们之间可以互换,属于一种对象行为型模式。总的来说策略模式是一种比较简单的模式,听起来可能有点费劲,其实就是定义一组通用算法的上层接口,各个算法实现类实现该算法接口,封装模块使用类似于 Context 的概念,Context 暴漏一组接口,Context 内部接口委托到抽象算法层。

策略模式的通用类图如下:

包含的角色如下:

  • 上下文角色(Context):该角色一般是一个实现类或者封装类,起到一定的封装及隔离作用,实际接受请求并将请求委托给实际的算法实现类处理,避免外界对底层策略的直接访问;
  • 抽象策略角色(Strategy):该角色一般是一个抽象角色,为接口或者抽象类扮演,定义具体策略角色的公共接口;
  • 具体策略角色(ConcreteStrategy):实现抽象策略角色的接口,为策略的具体实现类。

使用策略模式优化代码逻辑判断

假设我们有个积分发放功能,需要根据不同的积分类型来发分,我们的积分类型假设如下:

/**
 * 积分类型枚举
 */
public enum PointTypeEnum {
    COURSE_LEARN,
    COURSE_COMMENT,
    EBOOK_READ,
    LIVE_WATCH,
}

然后我们实现一个发放积分的方法:

/**
 * 指定积分类型,发分
 * @param pointTypeEnum 积分类型
 * @param points 要发的积分
 */
private static void sendPoint(PointTypeEnum pointTypeEnum, Integer points) {
    switch (pointTypeEnum) {
        case COURSE_COMMENT:
            log.info("评论课程,获得 {} 积分", points);
            break;
        case COURSE_LEARN:
            log.info("学习课程,获得 {} 积分", points);
            break;
        case EBOOK_READ:
            log.info("阅读电子书,获得 {} 积分", points);
            break;
        case LIVE_WATCH:
            log.info("观看直播,获得 {} 积分", points);
            break;
        default:
            break;
    }
}

这里只举例了 4 种积分类型,实际情况可能并不止这么多,而且每种积分发放逻辑都不相同,如果一味的在 switch case 中堆代码是肯定不行,根据我们的设计原则,尽量保证高内聚、低耦合,很显然这种方式是不可取的。

使用策略模式优化下上面的代码,首先我们需要一个策略接口,即积分发放接口:

/**
 * 积分发放接口,各个积分类型需要实现该接口,自定义发放逻辑
 */
public interface PointSendInterface {
    /**
     * 发放积分
     * @param points 要发放的积分
     */
    void sendPoint(Integer points);

    /**
     * 积分类型
     * @return
     */
    PointTypeEnum sendType();
}

然后不同的积分类型需要实现该接口,以便自定义其积分发放规则:

@Slf4j
@Service
public class CourseCommentPointSend implements PointSendInterface {
    @Override
    public void sendPoint(Integer points) {
        log.info("评论课程,获得 {} 积分", points);
    }

    @Override
    public PointTypeEnum sendType() {
        return PointTypeEnum.COURSE_COMMENT;
    }
}

@Slf4j
@Service
public class CourseLearnPointSend implements PointSendInterface {
    @Override
    public void sendPoint(Integer points) {
        log.info("学习课程,获得 {} 积分", points);
    }

    @Override
    public PointTypeEnum sendType() {
        return PointTypeEnum.COURSE_LEARN;
    }
}

@Slf4j
@Service
public class EbookReadPointSend implements PointSendInterface {
    @Override
    public void sendPoint(Integer points) {
        log.info("阅读电子书,获得 {} 积分", points);
    }

    @Override
    public PointTypeEnum sendType() {
        return PointTypeEnum.EBOOK_READ;
    }
}

@Slf4j
@Service
public class LiveWatchPointSend implements PointSendInterface {
    @Override
    public void sendPoint(Integer points) {
        log.info("观看直播,获得 {} 积分", points);
    }

    @Override
    public PointTypeEnum sendType() {
        return PointTypeEnum.LIVE_WATCH;
    }
}

最后我们要实现一个积分发放的 Context 给业务方使用,大致如下:

/**
 * 积分发放类
 */
@Component
public class PointSendContext {
    @Autowired
    private List<PointSendInterface> sendStrategyList;

    private final Map<PointTypeEnum, PointSendInterface> SEND_STRATEGY_MAP = new HashMap<>();

    @PostConstruct
    public void init() {
        sendStrategyList.forEach(strategy -> {
            SEND_STRATEGY_MAP.put(strategy.sendType(), strategy);
        });
    }

    /**
     * 发放积分
     * @param pointTypeEnum 积分类型
     * @param points 要发的分
     */
    public void sendPoint(PointTypeEnum pointTypeEnum, Integer points) {
        PointSendInterface sendStrategy = SEND_STRATEGY_MAP.get(pointTypeEnum);
        // 调用具体实现类发放积分
        sendStrategy.sendPoint(points);
    }
}

这里我们通过 @Autowired 自动注入 PointSendInterface 接口的所有实现类 sendStrategyList,然后通过 @PostConstruct 的初始化方法将每一个实现类组装成 SEND_STRATEGY_MAP 对象以便后续直接通过 pointType 可以映射出来该 pointType 对应的发分方法。调用的话就比较简单了,没有了 switch case 的冗长:

@SpringBootTest
class PointSendContextTest {
    @Autowired
    private PointSendContext pointSendContext;

    @Test
    void sendPoint() {
        pointSendContext.sendPoint(PointTypeEnum.COURSE_LEARN, 20);
    }
}

与使用策略模式优化你的代码相似的内容:

使用策略模式优化你的代码

策略模式简介 策略模式(Strategy Pattern:Define a family of algorithms,encapsulate each one,and make them interchangeable.)中文解释为:定义一组算法,然后将这些算法封装起来,以便它们之间可以互换,属于一

使用 TensorRT C++ API 调用GPU加速部署 YOLOv10 实现 500FPS 推理速度——快到飞起!!

NVIDIA ® TensorRT ™ 是一款用于高性能深度学习推理的 SDK,包含深度学习推理优化器和运行时,可为推理应用程序提供低延迟和高吞吐量。YOLOv10是清华大学研究人员近期提出的一种实时目标检测方法,通过消除NMS、优化模型架构和引入创新模块等策略,在保持高精度的同时显著降低了计算开销...

【OpenVINO™】在C#中使用 OpenVINO™ 部署 YOLOv10 模型实现目标

最近YOLO家族又添新成员:YOLOv10,YOLOv10 提出了一种一致的双任务方法,用于无nms训练的YOLOs,它同时带来了具有竞争力的性能和较低的推理延迟。此外,还介绍了整体效率-精度驱动的模型设计策略,从效率和精度两个角度对YOLOs的各个组成部分进行了全面优化,大大降低了计算开销,增强了...

使用策略模式重构 if/elseif/elseif

本文翻译自国外论坛 medium,原文地址:https://medium.com/aia-sg-techblog/refactor-if-elseif-elseif-using-strategy-design-pattern-80c51913a539 策略设计模式是一种允许在运行时选择算法的行为。这

【设计模式】策略模式

一、介绍 策略模式是一种行为设计模式,它能让你定义一系列算法,并将每种算法分别放入独立的类中,以使算法的对象能够相互替换。 这里列举两个例子来说明下策略模式的使用场景: (1)根据会员等级来计算折扣力度。不同等级拥有不同的折扣力度,这样就可以根据策略模式去灵活的计算,就算之后又新增了几个等级的会员,

万字详解常用设计模式

本文是博主在工作中对常用设计模式的使用经验总结归纳而来分享给大家。 设计模式一共有23种,本文讲解涉及如下: 责任链模式 模板方法模式 发布订阅模式 策略模式 三大分类 业界一般将设计模式分为三大类: 创建型模式:对类的实例化过程进行了抽象,能够将软件模块中对象的创建和对象的使用分离。有五种创建型模

深入理解java和dubbo的SPI机制

1 SPI简介 1.1 SPI(Service Provider Interface) 本质:将接口实现类的全限定名配置在文件中,并由服务加载器读取配置文件,加载实现类。这样可以在运行时,动态为接口替换实现类。 java SPI:用来设计给服务提供商做插件使用的。基于策略模式来实现动态加载的机制。我

【Azure API 管理】Azure APIM服务集成在内部虚拟网络后,在内部环境中打开APIM门户使用APIs中的TEST功能失败

问题描述 使用微软API管理服务(Azure API Management),简称APIM。 因为公司策略要求只能内部网络访问,所以启用了VNET集成。集成方式见: (在内部模式下使用 Azure API 管理连接到虚拟网络:https://docs.azure.cn/zh-cn/api-manag

滴滴面试:谈谈你对Netty线程模型的理解?

Netty 线程模型是指 Netty 框架为了提供高性能、高并发的网络通信,而设计的管理和利用线程的策略和机制。 Netty 线程模型被称为 Reactor(响应式)模型/模式,它是基于 NIO 多路复用模型的一种升级,它的核心思想是将 IO 事件和业务处理进行分离,使用一个或多个线程来执行任务的一

行为型:策略模式

定义 定义一系列的算法,将他们一个个封装起来,使他们直接可以相互替换。 算法:就是写的逻辑可以是你任何一个功能函数的逻辑 封装:就是把某一功能点对应的逻辑给抽出来 可替换:建立在封装的基础上,这些独立的算法可以很方便的替换 通俗的理解就是,把你的算法(逻辑)封装到不同的策略中,在不同的策略中是互相独