《C++20设计模式》学习笔记---工厂方法及抽象工厂模式代码

news/2024/7/24 13:24:50 标签: c++20, 设计模式, 学习

C++20设计模式

  • 第 3 章 工厂方法及抽象工厂模式代码

第 3 章 工厂方法及抽象工厂模式代码

#include<iostream>
#include<memory>

struct Point2D {
    int x;
    int y;
};

enum class Material {
    brick,
    aerated_concrete,
    drywall,
};

enum class WallType {
    basic,
    main,
    partition,
};

class Wall {
    Point2D start;  // 墙的起始点
    Point2D end;    // 墙的终止点
    int elevation;  // 墙的海拔,相对于某个基线的高度
    int height;     // 墙的高度
public:
    Wall(Point2D start, Point2D end, int elevation, int height)
        :start(start),end{end},elevation{elevation},height{height} {
    }

    // 判断墙体是否相交
    bool intersects(const Wall& wall) {
        return false;
    }

    virtual void print(std::ostream &os) const {
        os << "start: " << start.x << ", " << start.y
           << "\nend: " << end.x << ", " << end.y
           << "\nelevation: " << elevation
           << "\nheight: " << height;
    }

    friend std::ostream& operator<<(std::ostream& os, const Wall& wall) {
        wall.print(os);
        return os;
    }
};

#if 0
class SoildWall: public Wall {
    int width;          //墙的宽度
    Material material;  // 墙的材质
public:
    SoildWall(Point2D start, Point2D end, int elevation, int height,
        int width, Material material)
        :Wall{start,end,elevation,height}, width{width}, material{material} {
        if (elevation < 0 && material == Material::aerated_concrete) {
            // 加气混凝土不能用于地下建筑
            throw std::invalid_argument("elevation");
        }

        if (width < 120 && material == Material::brick) {
            // 墙的最小厚度是120mm
            throw std::invalid_argument("width");
        }
    }
};

void testNoFactory() {
    try
    {
        Point2D start{0,0}, end{0,300};
        SoildWall tmp(start, end, -1, 100, 100, Material::brick);
    }
    catch (const std::exception &e)
    {
        std::cerr <<"create wall error argument: "<< e.what() << '\n';
    }
}
#else

class SoildWall: public Wall {
    friend class WallFactory;
    int width;          //墙的宽度
    Material material;  // 墙的材质
protected:
    SoildWall(Point2D start, Point2D end, int elevation, int height,
              int width, Material material)
        : Wall{start, end, elevation, height}, width{width}, material{material}{
    }

public:
    void print(std::ostream &os) const override {
        Wall::print(os); // 调用基类的输出函数
        os << "\nwidth: " << width
           << "\nmaterial: " << static_cast<int>(material);
    }

    friend std::ostream& operator<<(std::ostream& os, const SoildWall& wall) {
        wall.print(os);
        return os;
    }

    static SoildWall create_main(Point2D start, Point2D end, int elevation, int height) {
        return SoildWall(start, end, elevation, height, 375, Material::aerated_concrete);
    }

    static std::unique_ptr<SoildWall> create_partition(Point2D start,
        Point2D end, int elevation, int height) {
        return std::make_unique<SoildWall>(SoildWall(start, end, elevation, height, 120, Material::brick));
    }

    static std::shared_ptr<SoildWall> create_main2(Point2D start,
        Point2D end, int elevation, int height) {
        if (elevation < 0) {
            return {};
        }
        return std::make_shared<SoildWall>(SoildWall(start,
            end, elevation, height, 120, Material::brick));
    }
};

void testFactoryMethod() {
    Point2D start{0, 0}, end{0, 3000};
    const auto main_wall = SoildWall::create_main({0, 0}, {0, 3000}, 2700, 3000);
    std::cout << main_wall << "\n";
}

void testFactoryCreateMain2() {
    const auto also_main_wall = SoildWall::create_main2({0,0},{0,3000}, -2000, 3000);
    if (!also_main_wall) {
       std::cout << "main wall create failed." << std::endl;
    }
}
#endif

// 3.3 工厂
#include<vector>
class WallFactory {
private:
    static std::vector<std::weak_ptr<Wall>> walls;
public:
    static std::shared_ptr<SoildWall> create_mian(Point2D start,
        Point2D end, int elevation, int height) {
        const auto this_wall = new SoildWall(start, end, elevation,
            height, 120, Material::brick);
        
        for (const auto wall : walls) {
            if (auto p = wall.lock()) {
                if (this_wall->intersects(*p)) {
                    delete this_wall;
                    return {};
                }
            }
        }
        std::shared_ptr<SoildWall> ptr(this_wall);
        walls.push_back(ptr);
        return ptr;
    }

    // 3.4
    static std::shared_ptr<Wall> create_wall(WallType type, Point2D start,
        Point2D end, int elevation, int height) {
        switch(type) {
            case WallType::main:
            {
                return std::make_shared<SoildWall>(SoildWall(start, end, elevation, height,
                    375, Material::aerated_concrete));
            }

            case WallType::partition:
            {
                return std::make_shared<SoildWall>(SoildWall(start, end, elevation, height,
                    120, Material::brick));
            }

            case WallType::basic:
            {
                // return std::make_shared<Wall>(start, end, elevation, height);
                return std::shared_ptr<Wall>{new Wall(start, end, elevation, height)};
            }
            default:
                return {};
        }
    }
};

// 类外实例化
std::vector<std::weak_ptr<Wall>> WallFactory::walls;


void testWallFactory() {
    const auto partition = WallFactory::create_mian({2000,0}, {2000,4000}, 0, 2700);
    std::cout << *partition << std::endl;
}

// 3.4
void testPolymorphicFactory()
{
    auto also_partition = 
        WallFactory::create_wall(WallType::partition, {0,0}, {5000, 0}, 0, 4200);

    // 把WallType::partition 改为WallType::basic, 下面的tmp会为空,Segmentation fault(空指针异常)
    if (also_partition) {
        auto tmp = std::dynamic_pointer_cast<SoildWall>(also_partition);
        if (tmp == nullptr) {
            std::cout << "hahhahahha" << std::endl;
        }
        std::cout << "\ntestPolymorphicFactory: \n" << 
            *std::dynamic_pointer_cast<SoildWall>(also_partition) << "\n";
    }

    std::cout << "\ntestPolymorphicFactory2: \n" << 
            (*also_partition) << "\n";
}

// 3.5嵌套工厂
namespace NestFactory{
    class Wall
    {
        Point2D start; // 墙的起始点
        Point2D end;   // 墙的终止点
        int elevation; // 墙的海拔,相对于某个基线的高度
        int height;    // 墙的高度
    public:
        Wall(Point2D start, Point2D end, int elevation, int height)
            : start(start), end{end}, elevation{elevation}, height{height}
        {
        }

        // 判断墙体是否相交
        bool intersects(const Wall &wall)
        {
            return false;
        }

        virtual void print(std::ostream &os) const
        {
            os << "start: " << start.x << ", " << start.y
               << "\nend: " << end.x << ", " << end.y
               << "\nelevation: " << elevation
               << "\nheight: " << height;
        }

        friend std::ostream &operator<<(std::ostream &os, const Wall &wall)
        {
            wall.print(os);
            return os;
        }
    
    private:
        class BasicWallFactory{
             // friend class Wall;
            BasicWallFactory()=default;
        public:
            std::shared_ptr<Wall> create(const Point2D start, 
                const Point2D end,
                const int elevation, const int height) {
                Wall *wall = new Wall(start, end, elevation, height);
                return std::shared_ptr<Wall>(wall); 
            }
        };
    public:
        static BasicWallFactory factory;
    };
    Wall::BasicWallFactory Wall::factory{};
    // Wall::BasicWallFactory Wall::factory;
    void testNestFactory() {
        auto basic = Wall::factory.create({0, 0}, {5000, 6666}, 0, 4444);
        std::cout << "\n3.5 ======= \n" << *basic << "\n";
    }

}; // NestFactory end

// 3.6 abstract factory mode
#include<map>
namespace AbstractFactory{
    struct HotDrink {
        virtual void prepare(int volume) = 0;
    };

    struct Tea: HotDrink {
        void prepare(int volume) override {
            std::cout << "take tea bag, boil water, pour " << volume
                << "ml, add some lemon" << std::endl;
        }
    };

    struct Coffee: HotDrink {
        void prepare(int volume) override {
            std::cout << "take coffee bag, boil water, pour " << volume
                << "ml, add some lemon" << std::endl;
        }
    };

    std::unique_ptr<HotDrink> make_drink(std::string type) {
        std::unique_ptr<HotDrink> drink = nullptr;
        if (type == "tea") {
            drink = std::make_unique<Tea>();
            drink->prepare(200);
        } else {
            drink = std::make_unique<Coffee>();
            drink->prepare(50);
        }
        return drink;
    }

    class HotDrinkFactory {
    public:
        virtual std::unique_ptr<HotDrink> make() const = 0;
    };

    class CoffeeFactory: public HotDrinkFactory {
    public:
        std::unique_ptr<HotDrink> make() const override {
            return std::make_unique<Coffee>();
        }
    };

    class TeaFactory: public HotDrinkFactory {
    public:
        std::unique_ptr<HotDrink> make() const override {
            return std::make_unique<Tea>();
        }
    };

    class DrinkFactory {
        std::map<std::string, std::unique_ptr<HotDrinkFactory>> hot_factory;
    public:
        DrinkFactory() {
            hot_factory["coffee"] = std::make_unique<CoffeeFactory>();
            hot_factory["tea"] = std::make_unique<TeaFactory>();
        }
        
        std::unique_ptr<HotDrink> make_drink(const std::string &name) {
            auto drink = hot_factory[name]->make();
            drink->prepare(200);
            return drink;
        }
    };
}; // AbstractFactory
// 3.7
#include<functional>
namespace FunctionFactory{
    class DrinkWithVolumFactory
    {
        std::map<std::string, std::function<std::unique_ptr<AbstractFactory::HotDrink>()>> factories;
    public:
        DrinkWithVolumFactory() {
            factories["tea"] = [] {
                auto tea = std::make_unique<AbstractFactory::Tea>();
                tea->prepare(200);
                return tea;
            };

            factories["coffee"] = [] {
                auto coffee = std::make_unique<AbstractFactory::Coffee>();
                coffee->prepare(50);
                return coffee;
            };
        }
        inline std::unique_ptr<AbstractFactory::HotDrink>make_drink(const std::string &name);

    };
    std::unique_ptr<AbstractFactory::HotDrink>
    DrinkWithVolumFactory::make_drink(const std::string &name)
    {
        return factories[name]();
    }

    void testFunctionFunctionFactory() {
        std::cout << "\n" << __FUNCTION__ << " start. \n";
        DrinkWithVolumFactory dwvf;
        dwvf.make_drink("tea");
        dwvf.make_drink("coffee");
        std::cout << __FUNCTION__ << " end. \n\n";
    }
} // FunctionFactory
int main()
{
    testFactoryMethod();
    testFactoryCreateMain2();
    testWallFactory();
    testPolymorphicFactory();
    NestFactory::testNestFactory();
    FunctionFactory::testFunctionFunctionFactory();
    return 0;
}

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

相关文章

早日退休!

文章目录 工作内容的复杂度技术难度的较量角色的重要程度鄙视产生的因素没有必要的相互鄙视打工人何苦为难打工人 祝各位IT大佬早日退休&#xff01;&#xff01;&#xff01; 在快速发展的现代社会中&#xff0c;IT行业已经成为了许多人眼中充满无限可能与挑战的职场。然而&am…

【蓝桥杯软件赛 零基础备赛20周】第4周——简单模拟

文章目录 什么是简单模拟简单模拟和编程能力刷题 什么是简单模拟 正在学编程语言&#xff08;C/C、Python、Java&#xff09;&#xff0c;或者刚学过语言&#xff0c;还没有开始学数据结构和算法的同学&#xff0c;有一些疑问&#xff1a;如何快速入门算法竞赛&#xff1f;如何…

我从来不理解JavaScript闭包,但我用了它好多年

前言 &#x1f4eb; 大家好&#xff0c;我是南木元元&#xff0c;热衷分享有趣实用的文章&#xff0c;希望大家多多支持&#xff0c;一起进步&#xff01; &#x1f345; 个人主页&#xff1a;南木元元 你是否学习了很久JavaScript但还没有搞懂闭包呢&#xff1f;今天就来聊一下…

SQL数据库-客观题 复习

一.单选 2.学校新开发了一个系统&#xff0c;通过收集与分析学生的学习行为&#xff0c;对其进行精准画像&#xff0c;进而提供个性化的学习策略&#xff0c;这属于________系统。 答案&#xff1a;D 知识点&#xff1a;【32010200】 知识考核要求&#xff1a;【3】 能力考…

基于Java SSM框架实现电影售票系统项目【项目源码+论文说明】计算机毕业设计

基于java的SSM框架实现电影售票系统演示 摘要 21世纪的今天&#xff0c;随着社会的不断发展与进步&#xff0c;人们对于信息科学化的认识&#xff0c;已由低层次向高层次发展&#xff0c;由原来的感性认识向理性认识提高&#xff0c;管理工作的重要性已逐渐被人们所认识&#…

UEC++ 虚幻5笔记(数字孪生示例) day13

智慧工地系统 制作主UI 日期时间UI制作 添加一个缩放框进行布局用来约束最上面的组件 车辆情况UI制作 工地UI制作 巡查UI制作 能源UI制作 底部按钮UI制作 摄像头UI制作 职工考勤UI制作 监控与咨询UI制作 数据中心UI制作 更新当前时间 首先将数据中心设置为已折叠 然后…

深度学习为什么要进行训练

深度学习模型之所以需要进行训练&#xff0c;是因为这些模型通常是通过学习从数据中提取模式和表示来完成任务的。训练是一个模型学习适应任务的过程&#xff0c;通过大量的标记数据来调整模型的参数&#xff0c;使其能够对未见过的数据做出准确的预测或执行特定的任务。以下是…

服务器感染了.DevicData-D-XXXXXXXX勒索病毒,如何确保数据文件完整恢复?

引言&#xff1a; 勒索病毒成为网络安全的严峻挑战&#xff0c;而最新的.DevicData-D-XXXXXXXX勒索病毒更是引起广泛关注。本文将深入介绍.DevicData-D-XXXXXXXX勒索病毒的特征&#xff0c;提供恢复被其加密的数据文件的方法&#xff0c;并分享预防措施&#xff0c;以确保您的数…