C++设计模式

一、什么叫C++的设计模式?

C++设计模式是指在软件工程中,特别是在使用C++语言进行面向对象编程时,针对常见问题的一系列经过验证的解决方案。设计模式不是具体的代码,而是用于指导软件设计和实现的高级模板和思想设计模式可以帮助开发者避免重复发明轮子,提高代码的可重用性、可读性和可维护性。

设计模式通常分为三大类:

  1. 创建型模式(Creational Patterns):这些模式专注于对象的创建过程,同时隐藏创建逻辑,以便使程序在不修改现有代码的情况下更加灵活地引入新的对象。常见的创建型模式包括单例模式(Singleton)、工厂方法模式(Factory Method)、抽象工厂模式(Abstract Factory)、建造者模式(Builder)和原型模式(Prototype)。
  2. 结构型模式(Structural Patterns):结构型模式关注如何通过不同的类和对象组合来形成更大的结构,以满足特定的设计需求。常见的结构型模式包括适配器模式(Adapter)、装饰器模式(Decorator)、代理模式(Proxy)、外观模式(Facade)、桥接模式(Bridge)、组合模式(Composite)和享元模式(Flyweight)。
  3. 行为型模式(Behavioral Patterns):行为型模式专注于对象间的交互以及它们如何相互协作以完成复杂的操作和算法。常见的行为型模式包括策略模式(Strategy)、模板方法模式(Template Method)、观察者模式(Observer)、迭代器模式(Iterator)、责任链模式(Chain of Responsibility)、命令模式(Command)、备忘录模式(Memento)、状态模式(State)和访问者模式(Visitor)。
  • 设计模式的应用不仅限于C++,在其他面向对象的编程语言中也广泛使用。每种设计模式都有其特定的上下文和应用场景,合理地使用设计模式可以解决特定的设计问题,提高软件质量。
  • 在C++中,设计模式的应用可能会涉及到语言特有的特性,如多态性、继承、模板和异常处理等。掌握设计模式对于C++开发者来说是一项重要的技能,有助于编写更加优雅和高效的代码。

二、UML类图

UML 类

#include<iostream>
#include<string>
using namespace std;


class Hunter
{
public:
    int m_age = 32;
    static int m_times;
    string getName()
    {
        return m_name;
    }

    void setName(string name)
    {
        m_name = name;
    }

    void goHunting()
    {
        aiming();
        shoot();
    }
    static void saySorry()
    {
        string count = to_string(m_times);
        cout << "Say sorry to every animal " + count + " times!" << endl;
    }

protected:
    string m_name = "Jack";
    void aiming()
    {
        cout << "使用" + m_gunName + "瞄准猎物..." << endl;
    }

private:
    string m_gunName = "AK-47";
    void shoot()
    {
        cout << "使用" + m_gunName + "射击猎物..." << endl;
    }
};
int Hunter::m_times = 3;

可以看到该图分为上中下三部分:上层是类名,中间层是属性(类的成员变量),下层是方法(类的成员函数)。

可见性:+ 表示public、# 表示protected、- 表示private、__(下划线)表示static

属性的表示方式:【可见性】【属性名称】:【类型】= { 缺省值,可选 }

方法的表示方式:【可见性】【方法名称】(【参数名 : 参数类型,……】):【返回值类型】

三、简单工厂模式

1、factory 模式(工厂模式)

  • Factory 模式(工厂模式)
#include <iostream>
using namespace std;

class AbstractSmile    //父类
{
public:
    virtual void transform() {};
    virtual void ability() {};
    virtual ~AbstractSmile() {};
};
// 人造恶魔果实· 绵羊形态              子类
class SheepSmile : public AbstractSmile
{
public:
    void transform() override
    {
        cout << "变成人兽 -- 山羊人形态..." << endl;
    }
    void ability() override
    {
        cout << "将手臂变成绵羊角的招式 -- 巨羊角" << endl;
    }
};

// 人造恶魔果实· 狮子形态
class LionSmile : public AbstractSmile
{
public:
    void transform() override
    {
        cout << "变成人兽 -- 狮子人形态..." << endl;
    }
    void ability() override
    {
        cout << "火遁· 豪火球之术..." << endl;
    }
};

class BatSmile : public AbstractSmile
{
public:
    void transform() override
    {
        cout << "变成人兽 -- 蝙蝠人形态..." << endl;
    }
    void ability() override
    {
        cout << "声纳引箭之万剑归宗..." << endl;
    }
};

// 恶魔果实工厂类
enum class Type :char { SHEEP, LION, BAT };
class SmileFactory
{
public:
    SmileFactory() {};
    ~SmileFactory() {};
    AbstractSmile* createSmile(Type type)
    {
        AbstractSmile* ptr = nullptr;
        switch (type)
        {
        case Type::SHEEP:
            ptr = new SheepSmile;
            break;
        case Type::LION:
            ptr = new LionSmile;
            break;
        case Type::BAT:
            ptr = new BatSmile;
            break;
        default:
            break;
        }
        return ptr;
    }
};

int main()
{
    SmileFactory* factory = new SmileFactory;
    AbstractSmile* obj = factory->createSmile(Type::BAT);
    obj->transform();
    obj->ability();
    return 0;
}

2、简单工厂函数说明

  • 由于人造恶魔果实类有继承关系, 并且实现了多态,所以父类的析构函数也应该是虚函数,这样才能够通过父类指针或引用析构子类的对象。
  • 工厂函数createSmile(Type type)的返回值修改成了AbstractSmile*类型,这是人造恶魔果实类的基类,通过这个指针保存的是子类对象的地址,这样就实现了多态,所以在main()函数中,通过obj对象调用的实际是子类BatSmile中的函数,因此打印出的信息应该是这样的:

3、工厂模式概括

工厂模式属于创建型模式之一,它用于处理对象的创建,将对象的创建与使用分离,以提高软件的灵活性和可扩展性工厂模式允许通过接口来请求一个类的对象,而不是直接使用new操作符创建对象

工厂模式有几种不同的形式,包括简单工厂模式工厂方法模式抽象工厂模式

四、工厂模式

简单工厂模式违背了开发-封闭原则(比如枚举时需要加很多的case),简单工厂模式是只有一个工厂类,而工厂模式是有很多的工厂类:

  • 一个基类,包含一个虚工厂函数,用于实现多态。
  • 多个子类,重写父类的工厂函数。每个子工厂类负责生产一种恶魔果实,这相当于再次解耦,将工厂类的职责再次拆分、细化,如果要生产新品种的恶魔果实,那么只需要添加对应的工厂类,无需修改原有的代码。

恶魔果实和工厂均有一个基类(抽象类)和多个子类:

#include <iostream>
using namespace std;

class AbstractSmile
{
public:
    virtual void transform() = 0;
    virtual void ability() = 0;
    virtual ~AbstractSmile() {}
};
// 人造恶魔果实· 绵羊形态
class SheepSmile : public AbstractSmile
{
public:
    void transform() override
    {
        cout << "变成人兽 -- 山羊人形态..." << endl;
    }
    void ability() override
    {
        cout << "将手臂变成绵羊角的招式 -- 巨羊角" << endl;
    }
};

// 人造恶魔果实· 狮子形态
class LionSmile : public AbstractSmile
{
public:
    void transform() override
    {
        cout << "变成人兽 -- 狮子人形态..." << endl;
    }
    void ability() override
    {
        cout << "火遁· 豪火球之术..." << endl;
    }
};

class BatSmile : public AbstractSmile
{
public:
    void transform() override
    {
        cout << "变成人

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

自动驾驶/机器人C++八股精选 文章被收录于专栏

在自动驾驶和机器人领域,C++因其高性能、内存管理高效和跨平台兼容性等特性,被广泛应用。本专栏整理了C++面试中常遇到的八股问题,可私信作者要飞书文档,不论是嵌入式软开、算法、软件开发都可以阅读,包括了C++的虚函数、C++11新特性、C++的STL库、Linux常见命令......

全部评论
写的很棒!
点赞 回复 分享
发布于 09-01 23:14 广东

相关推荐

点赞 评论 收藏
分享
10-26 22:34
C++
点赞 评论 收藏
分享
评论
3
13
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务