#ifndef ABSTRACTFACTORY_H
#define ABSTRACTFACTORY_H



/****************** 抽象工厂模式示例 ******************/

/**
 * @brief 抽象工厂模式示例，需求如下
 * 这里需求是造一艘船，分为三个版本，基础款、标准款、旗舰款，每款的船的船体、动力、武器都不相同。
--------------------------------
|       | 基础型 | 标准型 | 旗舰型 |
| --------------------------------
| 船体  | 木头   | 钢铁   | 合成金属 |
| 动力  | 手动   | 内燃机 | 核能    |
| 武器  | 枪     | 速射炮 | 激光    |
--------------------------------

    1. 定义船体、动力、武器的抽象类
    2. 创建一个船类，使用“组合”的方式包含船体、动力、武器的抽象类
    3. 创建一个抽象工厂类，定义造船的接口

 */

#include <string>
#include "spdlog/spdlog.h"


/****************** 抽象船体 ******************/
class AbstractShipBody
{
public:
    virtual std::string getShipBody() = 0;
    /* 定义虚析构函数 */
    virtual ~AbstractShipBody() {}
};

class ShipBodyWood : public AbstractShipBody
{
public:
    std::string getShipBody() override
    {
        return std::string("使用《木材》船体");
    }
};

class ShipBodySteel : public AbstractShipBody
{
public:
    std::string getShipBody() override
    {
        return std::string("使用《钢铁》船体");
    }
};

class ShipBodyCompositeMetal : public AbstractShipBody
{
public:
    std::string getShipBody() override
    {
        return std::string("使用《合成金属》船体");
    }
};

/****************** 抽象动力 ******************/
class AbstractEngine
{
public:
    virtual std::string getEngine() = 0;
    /* 定义虚析构函数 */
    virtual ~AbstractEngine() {}
};

class EngineManual : public AbstractEngine
{
public:
    std::string getEngine() override
    {
        return std::string("使用《手动》动力");
    }
};

class EngineInternalCombustion : public AbstractEngine
{
public:
    std::string getEngine() override
    {
        return std::string("使用《内燃机》动力");
    }
};

class EngineNuclearEnergy : public AbstractEngine
{
public:
    std::string getEngine() override
    {
        return std::string("使用《核能》动力");
    }
};

/****************** 抽象武器 ******************/
class AbstractWeapon
{
public:
    virtual std::string getWeapon() = 0;
    /* 定义虚析构函数 */
    virtual ~AbstractWeapon() {}
};

class WeaponGun : public AbstractWeapon
{
public:
    std::string getWeapon() override
    {
        return std::string("使用《枪》武器");
    }
};

class WeaponRapidFireGun : public AbstractWeapon
{
public:
    std::string getWeapon() override
    {
        return std::string("使用《速射炮》武器");
    }
};

class WeaponLaser : public AbstractWeapon
{
public:
    std::string getWeapon() override
    {
        return std::string("使用《激光》武器");
    }
};

/****************** 轮船 ******************/
class Ship
{
public:
    Ship(AbstractShipBody* shipBody, AbstractEngine* engine, AbstractWeapon* weapon)
        : m_shipBody(shipBody), m_engine(engine), m_weapon(weapon)
    {
    }

    ~Ship()
    {
        if (m_shipBody != nullptr)
        {
            delete m_shipBody;
            m_shipBody = nullptr;
        }

        if (m_engine != nullptr)
        {
            delete m_engine;
            m_engine = nullptr;
        }

        if (m_weapon != nullptr)
        {
            delete m_weapon;
            m_weapon = nullptr;
        }
    }

    void showShip()
    {
        SPDLOG_INFO("船体：{}", m_shipBody->getShipBody());
        SPDLOG_INFO("动力：{}", m_engine->getEngine());
        SPDLOG_INFO("武器：{}", m_weapon->getWeapon());
    }
public:
    AbstractShipBody* m_shipBody = nullptr;
    AbstractEngine* m_engine = nullptr;
    AbstractWeapon* m_weapon = nullptr;

};

/****************** 抽象工厂 ******************/
class AbstractFactory
{
public:
    virtual Ship* createShip() = 0;
    /* 定义虚析构函数 */
    virtual ~AbstractFactory() {}
};

class FactoryBase : public AbstractFactory
{
public:
    Ship* createShip() override
    {
        auto ship = new class Ship(new ShipBodyWood(), new EngineManual(), new WeaponGun());
        SPDLOG_INFO("【基础款】船建造完成。");
        return ship;
    }
};

class FactoryStandard : public AbstractFactory
{
public:
    Ship* createShip() override
    {
        auto ship = new class Ship(new ShipBodySteel(), new EngineInternalCombustion(), new WeaponRapidFireGun());
        SPDLOG_INFO("【标准款】船建造完成。");
        return ship;
    }
};

class FactoryUltimate : public AbstractFactory
{
public:
    Ship* createShip() override
    {
        auto ship = new class Ship(new ShipBodyCompositeMetal(), new EngineNuclearEnergy(), new WeaponLaser());
        SPDLOG_INFO("【旗舰款】船建造完成。");
        return ship;
    }
};


#endif // ABSTRACTFACTORY_H
