当前位置: 首页 > article >正文

【设计模式】【行为型模式(Behavioral Patterns)】之策略模式(Strategy Pattern)

1. 设计模式原理说明

策略模式(Strategy Pattern) 是一种行为设计模式,它允许你定义一系列算法,并将每个算法封装起来,使它们可以互换。策略模式让算法的变化独立于使用算法的客户。通过这种方式,客户端可以根据不同的情况选择不同的算法,而不需要修改其内部结构。

主要角色
  1. Context(上下文):使用某个策略类的对象。它维护着对Strategy对象的引用,用于在运行时切换策略。
  2. Strategy(策略接口):定义所有支持的算法的公共接口。Context使用这个接口来调用具体的策略。
  3. ConcreteStrategy(具体策略):实现了Strategy接口的具体算法。

2. UML 类图及解释

UML 类图
+------------------+                +-----------------------+
|      Context     |                |   Strategy Interface  |
|------------------|                |-----------------------|
| - strategy: Strategy |            | - execute(context): void |
|------------------|                +-----------------------+
| - setStrategy(strategy: Strategy) |                ^
| - performOperation()              |                |
+------------------+                +-----------------------+
                                                   |
                                                   |
                                                   v
                                    +---------------------------+
                                    | ConcreteStrategyA         |
                                    |--------------------------|
                                    | - execute(context): void  |
                                    +---------------------------+
                                                   ^
                                                   |
                                    +---------------------------+
                                    | ConcreteStrategyB         |
                                    |--------------------------|
                                    | - execute(context): void  |
                                    +---------------------------+
类图解释
  • Context:维护对Strategy对象的引用,并提供一个方法performOperation()来执行策略。客户端通过这个方法来调用具体的策略。
  • Strategy:定义了所有支持的算法的公共接口。Context使用这个接口来调用具体的策略。
  • ConcreteStrategyA 和 ConcreteStrategyB:实现了Strategy接口的具体算法。客户端可以选择不同的具体策略来执行不同的算法。

3. 代码案例及逻辑详解

Java 代码案例
// 策略接口
interface Strategy {
    void execute();
}

// 具体策略A
class ConcreteStrategyA implements Strategy {
    @Override
    public void execute() {
        System.out.println("Executing strategy A");
    }
}

// 具体策略B
class ConcreteStrategyB implements Strategy {
    @Override
    public void execute() {
        System.out.println("Executing strategy B");
    }
}

// 上下文
class Context {
    private Strategy strategy;

    public Context(Strategy strategy) {
        this.strategy = strategy;
    }

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

    public void performOperation() {
        strategy.execute();
    }
}

// 客户端
public class Client {
    public static void main(String[] args) {
        Context context = new Context(new ConcreteStrategyA());
        context.performOperation(); // 输出: Executing strategy A

        context.setStrategy(new ConcreteStrategyB());
        context.performOperation(); // 输出: Executing strategy B
    }
}
C++ 代码案例
#include <iostream>

// 策略接口
class Strategy {
public:
    virtual void execute() = 0;
    virtual ~Strategy() {}
};

// 具体策略A
class ConcreteStrategyA : public Strategy {
public:
    void execute() override {
        std::cout << "Executing strategy A" << std::endl;
    }
};

// 具体策略B
class ConcreteStrategyB : public Strategy {
public:
    void execute() override {
        std::cout << "Executing strategy B" << std::endl;
    }
};

// 上下文
class Context {
private:
    Strategy* strategy;
public:
    Context(Strategy* strategy) : strategy(strategy) {}

    void setStrategy(Strategy* strategy) {
        this->strategy = strategy;
    }

    void performOperation() {
        strategy->execute();
    }

    ~Context() {
        delete strategy;
    }
};

// 客户端
int main() {
    Context context(new ConcreteStrategyA());
    context.performOperation(); // 输出: Executing strategy A

    context.setStrategy(new ConcreteStrategyB());
    context.performOperation(); // 输出: Executing strategy B

    return 0;
}
Python 代码案例
# 策略接口
class Strategy:
    def execute(self):
        raise NotImplementedError

# 具体策略A
class ConcreteStrategyA(Strategy):
    def execute(self):
        print("Executing strategy A")

# 具体策略B
class ConcreteStrategyB(Strategy):
    def execute(self):
        print("Executing strategy B")

# 上下文
class Context:
    def __init__(self, strategy: Strategy):
        self._strategy = strategy

    def set_strategy(self, strategy: Strategy):
        self._strategy = strategy

    def perform_operation(self):
        self._strategy.execute()

# 客户端
if __name__ == "__main__":
    context = Context(ConcreteStrategyA())
    context.perform_operation()  # 输出: Executing strategy A

    context.set_strategy(ConcreteStrategyB())
    context.perform_operation()  # 输出: Executing strategy B
Go 代码案例
package main

import (
	"fmt"
)

// 策略接口
type Strategy interface {
	execute()
}

// 具体策略A
type ConcreteStrategyA struct{}

func (c *ConcreteStrategyA) execute() {
	fmt.Println("Executing strategy A")
}

// 具体策略B
type ConcreteStrategyB struct{}

func (c *ConcreteStrategyB) execute() {
	fmt.Println("Executing strategy B")
}

// 上下文
type Context struct {
	strategy Strategy
}

func NewContext(strategy Strategy) *Context {
	return &Context{strategy: strategy}
}

func (c *Context) SetStrategy(strategy Strategy) {
	c.strategy = strategy
}

func (c *Context) PerformOperation() {
	c.strategy.execute()
}

// 客户端
func main() {
	context := NewContext(&ConcreteStrategyA{})
	context.PerformOperation() // 输出: Executing strategy A

	context.SetStrategy(&ConcreteStrategyB{})
	context.PerformOperation() // 输出: Executing strategy B
}

4. 总结

策略模式 是一种行为设计模式,它允许你定义一系列算法,并将每个算法封装起来,使它们可以互换。这种模式的主要目的是在不改变客户端代码的情况下,通过不同的策略来实现不同的行为。

主要优点
  1. 算法可互换:可以在运行时动态地选择不同的算法,提高了灵活性。
  2. 职责分离:将算法的实现和使用算法的客户端分离,降低了耦合度。
  3. 易于扩展:增加新的策略非常容易,只需要实现策略接口即可。
主要缺点
  1. 增加了类的数量:每种策略都需要一个具体的类,可能会导致类的数量增多。
  2. 客户端需要了解所有策略:客户端需要知道所有的策略类,以便在运行时选择合适的策略。
适用场景
  • 当有多个相似的算法需要根据环境或条件动态选择时。
  • 当需要在运行时动态地改变对象的行为时。
  • 当类的行为由其子类决定时,可以考虑使用策略模式来避免大量的子类继承。
  • 当需要封装不同的算法或行为,并且这些算法或行为可以互换时。

http://www.kler.cn/a/411778.html

相关文章:

  • rabbitmq 启动异常问题排查
  • mmaction 、mmpose、rtmo和rtmpose
  • 【数据结构与算法】合并链表、链表分割、链表回文结构
  • CSS中calc语法不生效
  • JavaScript数据类型判断
  • VSCode 汉化教程【简洁易懂】
  • 【微服务架构】Kubernetes与Docker在微服务架构中的最佳实践(详尽教程)
  • 《免费学习网站推荐1》
  • 【JAVA】Java高级:Java网络编程——TCP/IP与UDP协议基础
  • 鸿蒙中拍照上传与本地图片上传
  • JavaWeb--JDBC
  • 如何搭建一个小程序:从零开始的详细指南
  • 过滤条件包含 OR 谓词,如何进行查询优化——OceanBase SQL 优化实践
  • C++设计模式-中介者模式
  • 【31-40期】从Java反射到SSO:深度解析面试高频问题
  • 17. 【.NET 8 实战--孢子记账--从单体到微服务】--记账模块--主币种设置
  • qt 读写文本、xml文件
  • 0 基础 入门简单 linux操作 上篇 利用apt命令装13 linux搭建自己的服务器
  • 【WEB开发.js】getElementById :通过元素id属性获取HTML元素
  • SpringMVC框架---SpringMVC概述、入门案例、常用注解
  • Flink Transformation-转换算子
  • C++设计模式之组合模式的基本结构
  • 【多线程-第一天-多线程的技术方案-pthread演示 Objective-C语言】
  • React中事件处理和合成事件:理解与使用
  • [RabbitMQ] 保证消息可靠性的三大机制------消息确认,持久化,发送方确认
  • 写个添加球队和展示球队的功能--laravel与inertia