设计模式:策略模式(C#、JAVA、JavaScript、C++、Python、Go、PHP)

news2024/12/25 22:38:10

简介:

策略模式,它是一种行为型设计模式,它定义了算法族,分别封装起来,让它们之间可以互相替换。策略模式让算法的变化独立于使用算法的客户,降低了耦合,增加了系统的可维护性和可扩展性。

策略模式的结构包括三种角色:
1、策略(Strategy):策略是一个接口,该接口定义了算法标识。
2、具体策略(ConcreteStrategy):具体策略是实现策略接口的类,具体策略实现策略接口所定义的抽象方法,即给出算法标识的具体算法。
3、上下文(Context):上下文是依赖于策略接口的类,即上下文包含有策略声明的变量。上下文中提供了一个方法,该方法委托策略变量调用具体策略所实现的策略接口中的方法。

策略模式的使用场景:
1、针对同一类型问题的多种处理方式,但具体行为有差别时。
2、需要安全地封装多种同一类型的操作时。
3、出现同一抽象类有多个子类,而又需要使用 if-else 或者 switch-case 来选择具体子类时。
4、当业务功能是客户程序的一个难以分割的成分时,增加新的业务算法或改变现有算法将十分困难。
5、当不同的时候需要不同的算法,我们不想支持我们并不使用的业务算法时。
6、当算法使用了客户不应该知道的数据时。
7、当一个类定义了很多行为,而且这些行为在这个类里的操作以多个条件语句的形式出现时。

总之,策略模式是一种非常实用的设计模式,可以用于封装各种类型的规则,并且可以在不同的时间应用不同的业务规则。

策略模式的创建步骤:
1、定义策略接口:首先需要定义一个策略接口,该接口中包含算法的方法。
2、创建具体策略类:根据策略接口,创建实现具体算法的类。
3、创建上下文类:上下文类负责维护和查询策略对象,并在具体策略类中注入策略对象。
4、在上下文类中注入策略对象:通过构造函数或者setter方法,将策略对象注入到上下文类中。
5、在客户端中创建上下文对象:在客户端中创建上下文对象,并将具体策略对象注入到上下文对象中。
6、客户端调用上下文对象:客户端通过上下文对象调用具体策略对象的方法,实现算法的调用。

以上是策略模式的基本创建步骤,具体实现方式可能会因语言和需求而有所不同。

策略模式的优点,主要包括:
1、提供了对“开闭原则”的完美支持,可以在不修改原有系统的基础上选择算法或行为,也可以灵活地增加新的算法或行为。
2、提供了管理相关的算法族的办法,恰当使用继承可以把算法族的公共代码转移到父类里面,从而避免重复的代码。
3、提供了可以替换继承关系的办法,使得系统更加灵活和可维护。
4、使用策略模式可以避免使用多重条件转移语句,如 if...else 语句、switch...case 语句。
5、可以提供相同行为的不同实现,客户可以根据不同时间或空间要求选择不同的实现方式。

策略模式的缺点,主要包括:
1、客户端必须知道所有的策略类,并自行决定使用哪一个策略类,这可能违反了“开闭原则”。
2、策略模式会造成产生很多策略类,增加了系统的复杂性和维护成本。
3、在实现上,策略模式需要使用继承和多态,这会增加代码的复杂性和实现的难度。
4、在使用策略模式时,需要注意策略的正确性和稳定性,因为不同的策略可能会对系统的行为产生不同的影响。

总之,策略模式虽然可以提高系统的灵活性和可维护性,但也存在一些缺点需要注意。在使用策略模式时,需要根据具体情况进行权衡和考虑。

示例:

一、C#策略模式

以下是一个示例,展示了如何在C#中实现策略模式:

//定义策略接口
public interface Strategy  
{  
    void Execute();  
}
//创建具体策略类
public class ConcreteStrategyA : Strategy  
{  
    public void Execute()  
    {  
        Console.WriteLine("执行策略A");  
    }  
}  
  
public class ConcreteStrategyB : Strategy  
{  
    public void Execute()  
    {  
        Console.WriteLine("执行策略B");  
    }  
}
//创建上下文类
public class Context  
{  
    private Strategy strategy;  
  
    public Context(Strategy strategy)  
    {  
        this.strategy = strategy;  
    }  
  
    public void SetStrategy(Strategy strategy)  
    {  
        this.strategy = strategy;  
    }  
  
    public void DoSomething()  
    {  
        strategy.Execute();  
    }  
}
//在客户端中创建上下文对象并注入具体策略对象
public class Client{
    public void Test(){
        Context context = new Context(new ConcreteStrategyA());  
        context.DoSomething();  // 输出:执行策略A  
        context.SetStrategy(new ConcreteStrategyB());  
        context.DoSomething();  // 输出:执行策略B
    }
}

二、java策略模式

策略模式通常通过以下方式实现:

//定义策略接口
public interface Strategy {  
    void execute();  
}
//创建具体策略类
public class ConcreteStrategyA implements Strategy {  
    @Override  
    public void execute() {  
        System.out.println("执行策略A");  
    }  
}  
  
public class ConcreteStrategyB implements Strategy {  
    @Override  
    public void execute() {  
        System.out.println("执行策略B");  
    }  
}
//创建上下文类
public class Context {  
    private Strategy strategy;  
  
    public Context(Strategy strategy) {  
        this.strategy = strategy;  
    }  
  
    public void setStrategy(Strategy strategy) {  
        this.strategy = strategy;  
    }  
  
    public void doSomething() {  
        strategy.execute();  
    }  
}
//在客户端中创建上下文对象并注入具体策略对象
public class Main {  
    public static void main(String[] args) {  
        Context context = new Context(new ConcreteStrategyA());  
        context.doSomething();  // 输出:执行策略A  
        context.setStrategy(new ConcreteStrategyB());  
        context.doSomething();  // 输出:执行策略B
    }
}

三、javascript策略模式

在JavaScript中,策略实现方式如下:

//定义策略接口
function Strategy(execute) {  
    this.execute = execute;  
}
//创建具体策略类
class ConcreteStrategyA extends Strategy {  
    constructor() {  
        super(this.execute);  
    }  
  
    execute() {  
        console.log('执行策略A');  
    }  
}  
  
class ConcreteStrategyB extends Strategy {  
    constructor() {  
        super(this.execute);  
    }  
  
    execute() {  
        console.log('执行策略B');  
    }  
}
//创建上下文类
class Context {  
    constructor(strategy) {  
        this.strategy = strategy;  
    }  
  
    setStrategy(strategy) {  
        this.strategy = strategy;  
    }  
  
    doSomething() {  
        this.strategy.execute();  
    }  
}

//在客户端中创建上下文对象并注入具体策略对象
const context = new Context(new ConcreteStrategyA());  
context.doSomething();  // 输出:执行策略A  
context.setStrategy(new ConcreteStrategyB());  
context.doSomething();  // 输出:执行策略B

四、C++策略模式

以下是在C++中实现策略模式:

//定义策略接口
class Strategy {  
public:  
    virtual void execute() = 0;  
};
//创建具体策略类
class ConcreteStrategyA : public Strategy {  
public:  
    void execute() override {  
        cout << "执行策略A" << endl;  
    }  
};  
  
class ConcreteStrategyB : public Strategy {  
public:  
    void execute() override {  
        cout << "执行策略B" << endl;  
    }  
};
//创建上下文类
class Context {  
public:  
    Context(Strategy* strategy) : strategy_(strategy) {}  
    void setStrategy(Strategy* strategy) {  
        strategy_ = strategy;  
    }  
    void doSomething() {  
        strategy_->execute();  
    }  
private:  
    Strategy* strategy_;  
};
//在客户端中创建上下文对象并注入具体策略对象
int main() {  
    Context context(new ConcreteStrategyA());  
    context.doSomething();  // 输出:执行策略A  
    context.setStrategy(new ConcreteStrategyB());  
    context.doSomething();  // 输出:执行策略B  
    delete context.strategy_;  
    delete context;  
    return 0;  
}

五、python策略模式

以下是在python中实现策略模式:

//定义策略接口
from abc import ABC, abstractmethod  
  
class Strategy(ABC):  
    @abstractmethod  
    def execute(self):  
        pass
        
//创建具体策略类
class ConcreteStrategyA(Strategy):  
    def execute(self):  
        print("执行策略A")  
  
class ConcreteStrategyB(Strategy):  
    def execute(self):  
        print("执行策略B")
        
//创建上下文类
class Context:  
    def __init__(self, strategy):  
        self.strategy = strategy  
      
    def set_strategy(self, strategy):  
        self.strategy = strategy  
      
    def do_something(self):  
        self.strategy.execute()
        
//在客户端中创建上下文对象并注入具体策略对象
context = Context(ConcreteStrategyA())  
context.do_something()  # 输出:执行策略A  
context.set_strategy(ConcreteStrategyB())  
context.do_something()  # 输出:执行策略B

六、go策略模式

以下是一个示例,展示了如何在go中实现策略模式:

//定义策略接口
type Strategy interface {  
    Execute()  
}
//创建具体策略类
type ConcreteStrategyA struct{}  
  
func (s *ConcreteStrategyA) Execute() {  
    fmt.Println("执行策略A")  
}  
  
type ConcreteStrategyB struct{}  
  
func (s *ConcreteStrategyB) Execute() {  
    fmt.Println("执行策略B")  
}
//创建上下文类
type Context struct {  
    strategy Strategy  
}  
  
func (c *Context) SetStrategy(strategy Strategy) {  
    c.strategy = strategy  
}  
  
func (c *Context) DoSomething() {  
    c.strategy.Execute()  
}
//在客户端中创建上下文对象并注入具体策略对象
func main() {  
    context := &Context{}  
    context.SetStrategy(&ConcreteStrategyA{})  
    context.DoSomething()  // 输出:执行策略A  
    context.SetStrategy(&ConcreteStrategyB{})  
    context.DoSomething()  // 输出:执行策略B  
}

七、PHP策略模式

以下是一个示例,展示了如何在PHP中实现策略模式:

//定义策略接口
interface Strategy {  
    public function execute();  
}
//创建具体策略类
class ConcreteStrategyA implements Strategy {  
    public function execute() {  
        echo "执行策略A";  
    }  
}  
  
class ConcreteStrategyB implements Strategy {  
    public function execute() {  
        echo "执行策略B";  
    }  
}
//创建上下文类
class Context {  
    private $strategy;  
      
    public function __construct(Strategy $strategy) {  
        $this->strategy = $strategy;  
    }  
      
    public function setStrategy(Strategy $strategy) {  
        $this->strategy = $strategy;  
    }  
      
    public function doSomething() {  
        $this->strategy->execute();  
    }  
}
//在客户端中创建上下文对象并注入具体策略对象
$context = new Context(new ConcreteStrategyA());  
$context->doSomething();  // 输出:执行策略A  
$context->setStrategy(new ConcreteStrategyB());  
$context->doSomething();  // 输出:执行策略B

通过以上步骤,我们实现了策略模式,使得算法可以独立于使用它的客户端,并且可以在不修改原有系统的基础上选择算法或行为。这种设计模式使得程序更加灵活和可维护。策略模式体现了开闭原则和里氏替换原则,各个策略实现都是兄弟关系,实现了同一个接口或者继承了同一个抽象类。这样只要使用策略的客户端保持面向抽象编程,就可以动态地切换不同的策略实现以进行替换。

《完结》

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1123606.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JSX看着一篇足以入门

JSX 介绍 学习目标&#xff1a; 能够理解什么是 JSX&#xff0c;JSX 的底层是什么 概念&#xff1a; JSX 是 javaScriptXML(HTML) 的缩写&#xff0c;表示在 JS 代码中书写 HTML 结构 作用&#xff1a; 在 React 中创建 HTML 结构&#xff08;页面 UI 结构&#xff09; 优势&a…

mybatis书写

mybatis <select id"selectUserList" resultType"map"> select * from user </select><!--根据主键查询一条--> <select id"selectById" resultType"map" parameterType"java.lang.Integer"> sele…

跨越单线程限制:Thread类的魅力,引领你进入Java并发编程的新纪元

线程的概述 线程是一个程序的多个执行路径&#xff0c;执行调度的单位&#xff0c;依托于进程存在。 线程不仅可以共享进程的内存&#xff0c;而且还拥有一个属于自己的内存空间&#xff0c;这段内存空间也叫做线程栈&#xff0c;是在建立线程时由系统分配的&#xff0c;主要用…

SCSS动态生成类

前言 在项目开发中&#xff0c;为了方便样式的复用和规范化&#xff0c;通常都会统一一些公共的样式类&#xff0c;如果用传统的css来写就会显得很臃肿。 最近看了看接手的项目的公共css文件&#xff0c;发现很多重复的样式声明&#xff0c;还有全局的样式使用不统一问题。 例…

港联证券:哪家证券公司开户好?

在现代社会&#xff0c;出资理财已经成为了一个不可或缺的部分。出资者在进行股票生意时&#xff0c;不可避免地需求选择一家证券公司进行开户。可是&#xff0c;哪家证券公司开户好&#xff1f;这是每个出资者都需求考虑的问题。本文将从多个角度分析&#xff0c;为您供给一些…

不知道怎么选CRM系统?看这篇就够了

CRM客户管理系统近年来已经从简单的客户管理软件发展成为了帮助企业运营发展的工具。它能够帮助企业优化业务流程、提高客户转化率、获得更多业绩。那么企业在选择CRM系统时有什么要点吗&#xff1f; 1、明确是否有自动化功能 自动化功能可以自动处理那些手动且琐碎的销售流程…

AI语音机器人的重点功能配置之话术

AI机器人运营中的重中之重就是对话术的配置&#xff0c;如何将话术运营好将是影响AI机器人效果的关键因素&#xff0c;那接下来我们了解一下AI机器人的话术模块的几个重点功能。 话术配置 有节点库、关键词、话术内容、转接人工、发送短信、知识库标签、客户意向、允许打断、…

VS Code关闭受限模式,关闭信任工作区

打开VS code每次出现这个界面&#xff0c;烦戳死!今天&#xff0c;贷款也要把它关掉&#xff01; 1、打开设置&#xff1a; 2、搜索以下值 security.workspace.trust3、重新启动VS Code即可&#xff01; 4、或者直接在用户的设置文件 settings.json中加入以下&#xff1a; &…

win10下u2net tensorrt模型部署

TensorRT系列之 Win10下yolov8 tensorrt模型加速部署 TensorRT系列之 Linux下 yolov8 tensorrt模型加速部署 TensorRT系列之 Linux下 yolov7 tensorrt模型加速部署 TensorRT系列之 Linux下 yolov6 tensorrt模型加速部署 TensorRT系列之 Linux下 yolov5 tensorrt模型加速部署…

企业需要拓展出海业务?CRM为您保驾护航(上)

2022年企业似乎格外艰难&#xff1a;线上流量看似见顶&#xff0c;线下受疫情影响严重&#xff0c;展会推迟&#xff0c;出差受阻&#xff0c;增长乏力沦为常态。为了寻求增长&#xff0c;一批又一批企业将目光看向海外&#xff0c;那里尚有流量红利和增长空间等待挖掘。CRM客户…

港联证券:短债基金收益?

跟着人们对理财的需求不断增加&#xff0c;短债基金成为了许多出资者关注的焦点。那么&#xff0c;短债基金可以带来什么样的收益呢&#xff1f;本文将从多个角度剖析短债基金的收益。 一、短债基金的概念 短债基金是一种基金类型&#xff0c;风险相对较低&#xff0c;一般出资…

【Docker从入门到入土 4】使用Harbor搭建Docker私有仓库

私有仓库 一、Harbor简介1.1 什么是Harbor?1.2 Harbor的特性1.3 Harbor和docker registry的关系1.4 Harbor的构成1.4 Harbor 配置文件中的两类参数1.4.1 所需参数1.4.2 可选参数 二、Harbor部署2.1 部署Docker-Compose服务2.2 部署 Harbor 服务Step1 下载或上传 Harbor 安装程…

密码即服务-初探vault

欢迎关注微信公众号 singless 1 介绍 https://www.vaultproject.io/ https://lonegunmanb.github.io/essential-vault/ 简单来说&#xff0c;在我们日常的工作中&#xff0c;免不了要和许多的机密信息打交道&#xff0c;可以是云服务的 Access Key 和 Secret Key&#xff0c;也…

whois人员信息python批处理读入与文本输出

使用pytho读取一个ip列表文本&#xff0c;批量获取whois输出并写入到一个文本 import socketif __name__ __main__:# 江苏电信DNS地址mylog open(whois.log, mode a,encodingutf-8)for line in open("ip.txt"):s socket.socket(socket.AF_INET, socket.SOCK_STR…

uniapp map polygons 区域填充色(fillColor)在ios显示正常,但在安卓手机显示是黑色的,怎么解决?

uniapp map polygons 区域填充色&#xff08;fillColor&#xff09;在ios显示正常&#xff0c;但在安卓手机显示是黑色的,怎么解决&#xff1f; <MapPage :longitude"item.centerCoord[0]" :latitude"item.centerCoord[1]":polygons"[{ points: it…

虚拟机使用linux常用问题(虚拟机操作系统:ubuntu 22.04LTS)

1.虚拟机连接外网 ubuntu解决网络连接的解决方案 明明连接好了但是没有网络的情况 2.虚拟机磁盘扩容 相关博客 利用gparted工具时,直接将unallocated空间的前一个位置的磁盘resize,将unallocated的空间全部覆盖 3.虚拟机与本机共享文件 安装vmtools 设置选项中安装vmtools…

软件为什么单独标注支持IPV6?IPV6和IPV4有什么区别?

ipv4和ipv6有何区别&#xff1f; 最关键的区别在于能够提供网络ip地址的数量。 ipv4是互联网协议第四版&#xff0c;地址长度为32位&#xff0c;可以提供ip地址总量为43亿个。目前ipv4地址资源已面临枯竭。 ipv6是互联网协议第六版&#xff0c;地址长度为128位&#xff0c;可…

python打包和发布package

打包 偶尔有一些复用性很高&#xff0c;复杂度也很高的函数要反复调用&#xff0c;可以自行打包&#xff0c;安装 打包结构如下 以iso_timer为例 mkdir common vim __init__.py cd common vim __init__.py vim format.py# init.py from .common import *# /common/init.p…

这Bug只能通过压测发现

大家好&#xff0c;我是洋子。之前发布过一篇有关于在性能测试当中发现Bug的文章《因为一个Bug&#xff0c;差点损失了100w》 这篇文章当时还登上了CSDN全站综合热榜TOP1&#xff0c;最近工作在做性能测试时&#xff0c;又发现了几个比较有意思得Bug&#xff0c;本期分享其中的…

Office技巧(持续更新)

1. Word 1.1 标题设置为多级列表 选住一级标题&#xff0c;之后进行“定义新的多级列表” 1.2 图片和表的题注自动排序 正常插入题注后就可以了。如果一级标题是 “汉字序号”&#xff0c;那么需要对题注进行修改&#xff1a; 从原来的 图 { STYLEREF 1 \s }-{ SEQ 图 \* A…