《设计模式的艺术》笔记 - 策略模式

这篇具有很好参考价值的文章主要介绍了《设计模式的艺术》笔记 - 策略模式。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

介绍

        策略模式定义一系列算法类,将每一个算法封装起来,并让它们可以相互替换。策略模式让算法独立于使用它的客户而变化,也称为政策模式。策略模式是一种对象行为模式。

实现

myclass.h

//
// Created by yuwp on 2024/1/12.
//

#ifndef DESIGNPATTERNS_MYCLASS_H
#define DESIGNPATTERNS_MYCLASS_H

#include <iostream>
#include <unordered_map>
#include <atomic>
#include <vector>
#include <memory>

class Strategy {    // 抽象策略类
public:
    virtual void algorithm() = 0;
};

class Context {   // 抽象状态类
public:
    void setStrategy(Strategy *strategy);

    void algorithm();

private:
    std::shared_ptr<Strategy> m_strategy;
};

class ConcreteStrategyA : public Strategy {
public:
    void algorithm() override;
};

class ConcreteStrategyB : public Strategy {
public:
    void algorithm() override;
};


#endif //DESIGNPATTERNS_MYCLASS_H

myclass.cpp

//
// Created by yuwp on 2024/1/12.
//

#include "myclass.h"
#include <thread>
#include <unistd.h>
#include <sstream>

void Context::setStrategy(Strategy *strategy) {
    m_strategy.reset(strategy);
}

void Context::algorithm() {
    if (m_strategy) {
        m_strategy->algorithm();
    } else {
        std::cout << "当前没有策略" << std::endl;
    }
}

void ConcreteStrategyA::algorithm() {
    std::cout << "采用策略A" << std::endl;
}

void ConcreteStrategyB::algorithm() {
    std::cout << "采用策略B" << std::endl;
}

main.cpp

#include <iostream>
#include <mutex>
#include "myclass.h"

int main() {
    Strategy *strategyA = new ConcreteStrategyA;
    Strategy *strategyB = new ConcreteStrategyB;
    Context *context = new Context;
    context->setStrategy(strategyA);
    context->algorithm();
    context->setStrategy(strategyB);
    context->algorithm();

    delete context;

    return 0;
}

总结

优点

        1. 策略模式提供了对开闭原则的完美支持。用户可以在不修改原有系统的基础上选择算法或行为,也可以灵活地增加新的算法或行为。

        2. 策略模式提供了管理相关的算法族的办法。策略类的等级结构定义了一个算法或行为族,恰当使用继承可以把公共的代码移到抽象策略类中,从而避免重复代码。

        3. 策略模式提供了一种可以替换继承关系的办法。如果不使用策略模式,那么使用算法的环境类就可能会有一些子类,每一个子类提供一种不同的算法。但是,这样一来算法的使用就和算法本身混在一起,不符合单一职责原则。决定使用哪一种算法的逻辑和该算法本身混合在一起,从而不可能再独立演化;而且使用继承无法实现算法或行为在程序运行时的动态切换。

        4. 使用策略模式可以避免多重条件选择语句。多重条件选择语句不易维护,它把采取哪一种算法或行为的逻辑与算法或行为本身的实现逻辑混合在一起,将它们全部硬编码(Hard Coding)在一个庞大的多重条件选择语句中,比直接继承环境类的办法还要原始和落后。

        5. 策略模式提供了一种算法的复用机制。由于将算法单独提取出来封装在策略类中,因此不同的环境类可以方便地复用这些策略类。

缺点

        1. 客户端必须知道所有的策略类,并自行决定使用哪一个策略类。这就意味着客户端必须理解这些算法的区别,以便适时选择恰当的算法。换言之,策略模式只适用于客户端知道所有的算法或行为的情况。

        2. 策略模式将造成系统产生很多具体策略类。任何细小的变化都将导致系统要增加一个新的具体策略类。

        3. 无法同时在客户端使用多个策略类。也就是说,在使用策略模式时,客户端每次只能使用一个策略类,不支持使用一个策略类完成部分功能后再使用另一个策略类来完成剩余功能的情况。

适用场景

        1. 一个系统需要动态地在几种算法中选择一种。可以将这些算法封装到一个个的具体算法类中,而这些具体算法类都是一个抽象算法类的子类。换言之,这些具体算法类均具有统一的接口。根据里氏代换原则和面向对象的多态性,客户端可以选择使用任何一个具体算法类,并只需要维持一个数据类型是抽象算法类的对象。

        2. 一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重条件选择语句来实现。此时,使用策略模式,把这些行为转移到相应的具体策略类里面,就可以避免使用难以维护的多重条件选择语句。

        3. 不希望客户端知道复杂的、与算法相关的数据结构。在具体策略类中封装算法与相关的数据结构,可以提高算法的保密性与安全性。

练习

myclass.h

//
// Created by yuwp on 2024/1/12.
//

#ifndef DESIGNPATTERNS_MYCLASS_H
#define DESIGNPATTERNS_MYCLASS_H

#include <iostream>
#include <unordered_map>
#include <atomic>
#include <vector>
#include <memory>

class TakeOff {    // 起飞抽象策略类
public:
    virtual void takeOff() = 0; // 起飞
};

class Flight {      // 飞行抽象策略类
public:
    virtual void flight() = 0;  // 飞行
};

class Plane {
public:
    Plane(TakeOff *takeOff, Flight *flight);
    virtual ~Plane();
    virtual void takeOff();
    virtual void flight();
private:
    TakeOff *m_takeoff;
    Flight *m_flight;
};

class Simulator {   // 模拟系统
public:
    void setPlane(Plane *plane);

    void start();

private:
    std::shared_ptr<Plane> m_plane;
};

class VerticalTakeOff : public TakeOff {    // 垂直起飞策略类
public:
    void takeOff() override;
};

class LongDistanceTakeOff : public TakeOff {    // 长距离起飞策略类
public:
    void takeOff() override;
};

class SubSonicFly : public Flight {     // 亚音速飞行策略类
public:
    void flight() override;
};

class SuperSonicFly : public Flight {     // 超音速飞行策略类
public:
    void flight() override;
};

class Helicopter : public Plane {   // 直升机
public:
    Helicopter();

    void takeOff() override;

    void flight() override;
};

class AirPlane : public Plane {   // 客机
public:
    AirPlane();

    void takeOff() override;

    void flight() override;
};

class FighterPlane : public Plane {   // 歼击机
public:
    FighterPlane();

    void takeOff() override;

    void flight() override;
};

class HarrierPlane : public Plane {   // 鹞式战斗机
public:
    HarrierPlane();

    void takeOff() override;

    void flight() override;
};


#endif //DESIGNPATTERNS_MYCLASS_H

myclass.cpp

//
// Created by yuwp on 2024/1/12.
//

#include "myclass.h"
#include <thread>
#include <unistd.h>
#include <sstream>

Plane::Plane(TakeOff *takeOff, Flight *flight) {
    m_takeoff = takeOff;
    m_flight = flight;
}

Plane::~Plane() {
    if (m_takeoff) {
        delete m_takeoff;
    }
    if (m_flight) {
        delete m_flight;
    }
}

void Plane::takeOff() {
    if (m_takeoff) {
        m_takeoff->takeOff();
    } else {
        std::cout << "没有设置起飞特征" << std::endl;
    }
}

void Plane::flight() {
    if (m_flight) {
        m_flight->flight();
    } else {
        std::cout << "没有设置飞行特征" << std::endl;
    }
}

void Simulator::setPlane(Plane *plane) {
    m_plane.reset(plane);
}

void Simulator::start() {
    if (m_plane) {
        m_plane->takeOff();
        m_plane->flight();
    } else {
        std::cout << "请先设置飞机种类" << std::endl;
    }
}

void VerticalTakeOff::takeOff() {
    std::cout << "垂直起飞" << std::endl;
}

void LongDistanceTakeOff::takeOff() {
    std::cout << "长距离起飞" << std::endl;
}

void SubSonicFly::flight() {
    std::cout << "亚音速飞行" << std::endl;
}

void SuperSonicFly::flight() {
    std::cout << "超音速飞行" << std::endl;
}

Helicopter::Helicopter() : Plane(new VerticalTakeOff(), new SubSonicFly()) {

}

void Helicopter::takeOff() {
    std::cout << "直升机开始起飞" << std::endl;
    Plane::takeOff();
}

void Helicopter::flight() {
    std::cout << "直升机开始飞行" << std::endl;
    Plane::flight();
}

AirPlane::AirPlane() : Plane(new LongDistanceTakeOff(), new SubSonicFly()) {

}

void AirPlane::takeOff() {
    std::cout << "客机开始起飞" << std::endl;
    Plane::takeOff();
}

void AirPlane::flight() {
    std::cout << "客机开始飞行" << std::endl;
    Plane::flight();
}

FighterPlane::FighterPlane() : Plane(new LongDistanceTakeOff(), new SuperSonicFly()) {

}

void FighterPlane::takeOff() {
    std::cout << "歼击机开始起飞" << std::endl;
    Plane::takeOff();
}

void FighterPlane::flight() {
    std::cout << "歼击机开始飞行" << std::endl;
    Plane::flight();
}

HarrierPlane::HarrierPlane() : Plane(new VerticalTakeOff(), new SuperSonicFly()) {

}

void HarrierPlane::takeOff() {
    std::cout << "鹞式战斗机开始起飞" << std::endl;
    Plane::takeOff();
}

void HarrierPlane::flight() {
    std::cout << "鹞式战斗机开始飞行" << std::endl;
    Plane::flight();
}

main.cpp文章来源地址https://www.toymoban.com/news/detail-824285.html

#include <iostream>
#include <mutex>
#include "myclass.h"

int main() {
    Simulator *simulator = new Simulator();
    Plane *plane = new Helicopter();
    simulator->setPlane(plane);
    simulator->start();
    std::cout << "----------------------" << std::endl;
    plane = new AirPlane();
    simulator->setPlane(plane);
    simulator->start();
    std::cout << "----------------------" << std::endl;
    plane = new FighterPlane();
    simulator->setPlane(plane);
    simulator->start();
    std::cout << "----------------------" << std::endl;
    plane = new HarrierPlane();
    simulator->setPlane(plane);
    simulator->start();

    delete simulator;

    return 0;
}

到了这里,关于《设计模式的艺术》笔记 - 策略模式的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 《设计模式的艺术》笔记 - 状态模式

            状态模式允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。其别名为状态对象,状态模式是一种对象行为模式。 myclass.h myclass.cpp main.cpp         1. 封装了状态的转换规则。在状态模式中可以将状态的转换代码封装在环境类或者具体状

    2024年01月25日
    浏览(47)
  • 《设计模式的艺术》笔记 - 代理模式

            代理模式是给某一个对象提供一个代理,并由代理对象控制对原对象的引用。代理模式是一种对象结构型模式。 myclass.h myclass.cpp main.cpp         1. 代理模式能够协调调用者和被调用者,在一定程度上降低了系统的耦合度,满足迪米特法则。         2. 客户端可以

    2024年01月19日
    浏览(46)
  • 《设计模式的艺术》笔记 - 桥接模式

            桥接模式将抽象部分与其实现部分分离,使它们都可以独立地变化。它是一种对象结构型模式,又称为柄体模式或接口模式 myclass.h myclass.cpp main.cpp         1. 分离抽象接口及其实现部分。桥接模式使用“对象间的关联关系”解耦了抽象和实现之间固有的绑定关系,

    2024年01月18日
    浏览(45)
  • 《设计模式的艺术》笔记 - 命令模式

            命令模式将一个请求封装为一个对象,从而可用不同的请求对客户进行参数化;对请求排队或者记录请求日志,以及支持可撤销的操作。命令模式是一种对象行为模式,其别名为动作模式或事务模式。 myclass.h myclass.cpp main.cpp         只需要增加一个CommandQueue类即可

    2024年01月20日
    浏览(44)
  • 《设计模式的艺术》笔记 - 享元模式

            享元模式运用共享技术有效地支持大量细粒度对象的复用。系统只使用少量的对象,而这些对象都很相似,状态变化很小,可以实现对象的多次复用。由于享元模式要求能够共享的对象必须是细粒度对象,因此它又称为轻量级模式,是一种对象结构型模式。 myclass.

    2024年01月19日
    浏览(32)
  • 《设计模式的艺术》笔记 - 单例模式

            单例模式优点是可以确保系统中只存在单个对象实例,缺点是不便扩展,一定程度上违背单一原则,既提供业务方法,又提供创建对象方法         在类加载的时候就创建好对象,获取对象时直接返回即可         在类加载的时候没有创建对象,第一次获取对象

    2024年02月02日
    浏览(32)
  • 《设计模式的艺术》笔记 - 工厂方法模式

            在简单工厂模式中,当系统中需要引入新的产品时,由于静态工厂方法通过所传入的参数的不同来创建不同的产品,这必定要修改工厂类的源代码,将违背开闭原则。因此,工厂方法模式应运而生。工厂方法模式是定义一个用于创建对象的接口,让子类决定将哪一个

    2024年01月23日
    浏览(37)
  • 《设计模式的艺术》笔记 - 抽象工厂模式

            提供了一个创建一系列相关或相互依赖的对象的接口,而无须指定它们具体的类。抽象工厂模式又称为Kit模式,它是一种对象创建型模式。         在抽象工厂模式中,每个具体工厂都提供了多个工厂方法用于产生多种不同类型的产品,这些产品构成了一个产品族。

    2024年01月16日
    浏览(29)
  • 《设计模式的艺术》笔记 - 建造者模式

            建造者模式将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。建造这模式是一种对象创建型模式。 myclass.h myclass.cpp main.cpp         优点:         1. 在建造者模式中,客户端不必知道产品内部组成的细节,将产品本身与产品的创建

    2024年01月16日
    浏览(31)
  • 《设计模式的艺术》笔记 - 简单工厂模式

            定义一个工厂类,它可以根据参数的不同返回不同类的实例,被创建的实例通常都具有相同的父类。因为在简单工厂模式中用于创建实例的方法是静态方法,因此简单工厂模式又被称为静态工厂方法模式,属于类创建型模式         将Factory合并到父类Product中,此时

    2024年01月16日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包