(一)详解策略模式

news/2024/6/17 10:11:25 标签: 策略模式

目录

必备背景知识

一.使用场景

二.核心逻辑

三.举例子

总结


必备背景知识

  • 针对接口编程,而不是针对实现编程(修改功能更加容易,我们只需要对接口作出修改即可)
  • 优先使用组合而不是继承(继承会导致后来的子类都具备了父类的功能,有时候我们想让子类没有父类的某些功能)

一.使用场景

由当前对象所拓展出来的对象有可能有新增功能,或者不具备原来某些功能的时候可以使用。优点在于可拓展性高,维护便捷,能动态的改变对象的属性。若想给所有同一大类但不同属性的不同对象增加一个新的公用功能,直接提供接口即可。不用依次修改。

二.核心逻辑

将不同对象反复变化的部分抽象封装出来,后序修改时只针对变化的部分进行修改这样不会影响其他不变化的部分。

三.举例子

从代码理解好理解一些。假设我们有个基类鸭子,我想拥有不同种类的鸭子子类。不同鸭子拥有不同的行为。有的会叫有的不会叫。我们统一将这些变化的属性抽象出来并单独成为一个行为类。同时基类提供接口来获取这些行为对象。同时针对这个行为,我们可以实现多种不同的实现方法类。这样我们通过子类继承基类,并在子类内特化这些行为对象选择对应的方法类就能动态的实现不同鸭子的不同行为了。把行为的决定权下放到子类而不是基类决定。基类只负责提供获取接口。

首先我们看基类duck

class Duck 
{
public:
    std::unique_ptr<FlyBehavior> flyBehavior;    //两个行为对象,由不同子类对象特化具体行为
    std::unique_ptr<QuackBehavior> quackBehavior;
    
    Duck(std::unique_ptr<FlyBehavior> flyBehavior, std::unique_ptr<QuackBehavior> quackBehavior);    //这里采取将行为类在构造函数内传递的方式,不同的鸭子将不同方法传给鸭子基类以实现构造

    virtual ~Duck() = default;    //析构函数虚继承为了正确释放

    void performQuack() const    //父类提供接口给用户,用户直接调取对应鸭子的状态
    {
        quackBehavior->quack();    //调用行为类内的接口,具体实现由行为类下的实现方法类完成
    }

    virtual void display() const = 0;    //用于测试或实现鸭子具体功能
    
    void performFly() const
    {
        flyBehavior->fly();
    }
};

这样我们就需要提供对应的行为类。也就是飞行行为和叫行为。我们需要在两种行为类内实现接口提供给后来的行为的实现类使用,并且保持一致。同时让鸭子的基类提供给用户使用的接口函数调用这个接口,就能直接获取到不同的行为实现方法。

这里以飞行行为为例

class FlyBehavior {
public:
    virtual void fly() const = 0;    //后序实现所有有关飞行行为的实现方法都要提供fly的实现
                                     
    virtual ~FlyBehavior() = default;
};

这样我们就可以实现关于飞行的多种不同实现方式。包括但不限于用翅膀飞或者完全不能飞。

class FlyNoWay: public FlyBehavior {
public:    
    void fly() const 
    {
         std::cout << "I can't fly!" << std::endl;    //实现不会飞的鸭子
    }
};


class FlyWithWings: public FlyBehavior {
public:
    virtual void fly() const 
    {
         std::cout << "I'm flying!" << std::endl;    //实现用翅膀飞的鸭子
    }
};

到目前为止大体框架已经完成了。若想添加动态设置功能。我们可以不用智能指针并且在duck的基类内添加set接口,将参数设置为行为方式,将接受到的行为方式复制给当前鸭子内的行为方式即可。

总结

策略模式定义了一个算法族,分辨封装,使得相互之间可以互相转化。让各个模块独立。


http://www.niftyadmin.cn/n/5053753.html

相关文章

用友U8 CRM客户关系管理任意文件上传漏洞复现【附POC】

文章目录 用友U8 CRM客户关系管理任意文件上传漏洞复现0x01 前言0x02 漏洞描述0x03 影响平台0x04 漏洞环境0x05 漏洞复现1.访问漏洞环境2.构造POC3.复现4.访问shell地址 0x06 整改建议 用友U8 CRM客户关系管理任意文件上传漏洞复现 0x01 前言 免责声明&#xff1a;请勿利用文…

git使用过程中出现乱码的解决办法

当我们使用git log或者git diff等git操作时&#xff0c;在终端很可能会遇到乱码&#xff0c;乱码效果如下&#xff1a; <E6><B7><BB><E5><8A><A0><E4><BA><86><E4><B8><80><E4><BA>&…

Python Urllib:网络库(stdlib)的强大功能与灵活运用

当我们谈论Python中的网络编程时&#xff0c;Urllib这个内置库无疑是我们应该重点关注的对象。Urllib为Python开发者提供了一套全面、易用的API&#xff0c;用于处理网络请求和数据传输。借助Urllib&#xff0c;我们可以发送HTTP请求、进行URL编码和解码、处理cookies和会话等。…

在比特币上支持椭圆曲线 BLS12–381

通过使用智能合约实现来支持任何曲线 BLS12–381 是一种较新的配对友好型椭圆曲线。 与常用的 BN-256 曲线相比&#xff0c;BLS12-381 的安全性明显更高&#xff0c;并且安全目标是 128 位。 所有其他区块链&#xff0c;例如 Zcash 和以太坊&#xff0c;都必须通过硬分叉才能升…

腾讯大牛耗时1个月整理的“JVM学习笔记“深入底层,面面俱到!

为什么要学习JVM&#xff1f; 1、 程序调优2、 排查程序运行问题3、 掌握了程序执行的根本和原理4、 规避写代码时候的一些错误5、 应付面试6、 掌握了其他语言的通用机制 怎么有效的学习JVM&#xff1f; 以上了解了学习JVM的种种好处&#xff0c;但是怎么有效的学习JVM呢&a…

该函数的功能是将一个字符数组src中的内容复制到另一个字符数组des中,并在复制完成后将des长度设置为src长度加1

函数功能解释 int byteArrayBeforeWriteProc(char *src, int srcLen,char *des, int &desLen) {if (srcLen > 0 && des ! nullptr && desLen > srcLen 1) {memcpy(des, src, srcLen);des[srcLen] \0;desLen srcLen 1;return 0;}return -1; // 处…

正点原子lwIP学习笔记——NETCONN接口简介

1. NETCONN接口简介 NETCONN API 使用了操作系统的 IPC 机制&#xff0c; 对网络连接进行了抽象&#xff0c;使用同一的接口完成UDP和TCP连接。 NETCONN API接口是在RAW接口基础上延申出来的一套API接口 首先会调用netconn_new创建一个pcb控制块&#xff0c;其实际是一个宏定…

spring bean实例化过程及顺序

spring bean的初始化从doCreateBean方法开始&#xff0c;依次会调用下面三个方法执行bean的初始化。大部分方法都在AbstractAutowireCapableBeanFactory类中。 实例化 createBeanInstance()方法根据BeanDef获取bean对应的class通过反射调用构造函数进行bean的实例化。 这里会…