本文参考:简单工厂模式 - 人造恶魔果实工厂1 | 爱编程的大丙 工厂模式 - 人造恶魔果实工厂2 | 爱编程的大丙
抽象工厂模式 - 弗兰奇一家 | 爱编程的大丙
工厂我们就可以得到想要的东西,在程序设计中,这种模式就叫做工厂模式,工厂生成出的产品就是某个类的实例,也就是对象。关于工厂模式一共有三种,分别是:简单工厂模式、工厂模式、抽象工厂模式。
不论使用哪种工厂模式其主要目的都是实现类与类之间的解耦合,这样我们在创建对象的时候就变成了拿来主义,使程序更加便于维护。
基于简单工厂模式去创建对象的时候,需要提供一个工厂类,专门用于生产需要的对象,这样关于对象的创建操作就被剥离出去了。
简单工厂模式相关类的创建和使用步骤:
1、创建一个新的类, 可以将这个类称之为工厂类。对于简单工厂模式来说,需要的工厂类只有一个。
2、在这个工厂类中添加一个公共的成员函数,通过这个函数来创建我们需要的对象,关于这个函数一般将其称之为工厂函数。
3、关于使用,首先创建一个工厂类对象,然后通过这个对象调用工厂函数,这样就可以生产出一个指定类型的实例对象了。
下面以生成三种“动物型恶魔果实”为例
#include
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;
}
程序结果:
变成人兽 -- 蝙蝠人形态...
声纳引箭之万剑归宗...
通过上面的代码,实现了一个简单工厂模式
由于人造恶魔果实类有继承关系, 并且实现了多态,所以父类的析构函数也应该是虚函数,这样才能够通过父类指针或引用析构子类的对象。
工厂函数createSmile(Type type)的返回值修改成了AbstractSmile*类型,这是人造恶魔果实类的基类,通过这个指针保存的是子类对象的地址,这样就实现了多态,所以在main()函数中,通过obj对象调用的实际是子类BatSmile中的函数。
简单工厂模式存在一个弊端,其违法了开放-封闭原则。
开放-封闭原则:软件实体(类、模块、函数等)可以扩展,但是不可以修改。也就是说对于扩展是开放的,对于修改是封闭的。
在上面的工厂函数中需要生成三种人造恶魔果实,现在如果想要生成更多,那么就需要在工厂函数的switch语句中添加更多的case,很明显这违背了封闭原则,也就意味着需要基于开放原则来解决这个问题。
所以有了工厂模式。简单工厂模式只有一个工厂类,工厂模式有很多个工厂类
1、一个基类,包含一个虚工厂函数,用于实现多态。
2、多个子类,重写父类的工厂函数。每个子工厂类负责生产一种恶魔果实,这相当于再次解耦,将工厂类的职责再次拆分、细化,如果要生产新品种的恶魔果实,那么只需要添加对应的工厂类,无需修改原有的代码。
完整代码:
#include
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 << "变成人兽 -- 蝙蝠人形态..." << endl;
}
void ability() override
{
cout << "声纳引箭之万剑归宗..." << endl;
}
};
// 恶魔果实工厂类
class AbstractFactory
{
public:
virtual AbstractSmile* createSmile() = 0;
virtual ~AbstractFactory() {}
};
class SheepFactory : public AbstractFactory
{
public:
AbstractSmile* createSmile() override
{
return new SheepSmile;
}
~SheepFactory()
{
cout << "释放 SheepFactory 类相关的内存资源" << endl;
}
};
class LionFactory : public AbstractFactory
{
public:
// 工厂函数
AbstractSmile* createSmile() override
{
return new LionSmile;
}
~LionFactory()
{
cout << "释放 LionFactory 类相关的内存资源" << endl;
}
};
class BatFactory : public AbstractFactory
{
public:
// 工厂函数
AbstractSmile* createSmile() override
{
return new BatSmile;
}
~BatFactory()
{
cout << "释放 BatFactory 类相关的内存资源" << endl;
}
};
int main()
{
AbstractFactory* factory = new BatFactory;
AbstractSmile* obj = factory->createSmile();
obj->transform();
obj->ability();
return 0;
}
工厂模式创建的产品对象相对简单,抽象工厂模式创建的产品对象相对复杂,这个类组件中有可变的因素,这里以造船为例。
基础型 | 标准型 | 旗舰型 | |
船体 | 木头 | 钢铁 | 合成金属 |
动力 | 手动 | 内燃机 | 核能 |
武器 | 枪 | 速射炮 | 激光 |
在这个图中有四个抽象类,分别是:
ShipBody 类:船体的抽象类
有三个子类,在子类中通过不同的材料来建造船体
Weapon 类:武器的抽象类
有三个子类,在子类中给战船提供不同种类的武器
Engine 类:动力系统抽象类
有三个子类,在子类中给战船提供不同动力系统
AbstractFactory 类:抽象工厂类
在子工厂类中生产不同型号的战船
和ShipBody 、Weapon、Engine有依赖关系,在工厂函数中创建了它们的实例对象
和Ship 类有依赖关系,在工厂函数中创建了它的实例对象
关于Ship类它可以和ShipBody 、Weapon、Engine可以是聚合关系,也可以是组合关系:
组合关系:析构Ship类对象的时候,也释放了ShipBody 、Weapon、Engine对象
聚合关系:析构Ship类对象的时候,没有释放ShipBody 、Weapon、Engine对象
ShipBody类以及其子类:
// 船体
class ShipBody
{
public:
virtual string getShipBody() = 0;
virtual ~ShipBody() {}
};
class WoodBody : public ShipBody
{
public:
string getShipBody() override
{
return string("用<木材>制作轮船船体...");
}
};
class IronBody : public ShipBody
{
public:
string getShipBody() override
{
return string("用<钢铁>制作轮船船体...");
}
};
class MetalBody : public ShipBody
{
public:
string getShipBody() override
{
return string("用<合金>制作轮船船体...");
}
};
Engine类以及其子类
// 动力
class Engine
{
public:
virtual string getEngine() = 0;
virtual ~Engine() {}
};
class Human : public Engine
{
public:
string getEngine() override
{
return string("使用<人力驱动>...");
}
};
class Diesel : public Engine
{
public:
string getEngine() override
{
return string("使用<内燃机驱动>...");
}
};
class Nuclear : public Engine
{
public:
string getEngine() override
{
return string("使用<核能驱动>...");
}
};
Weapon类以及其子类
// 武器
class Weapon
{
public:
virtual string getWeapon() = 0;
virtual ~Weapon() {}
};
class Gun : public Weapon
{
public:
string getWeapon() override
{
return string("配备的武器是<枪>");
}
};
class Cannon : public Weapon
{
public:
string getWeapon() override
{
return string("配备的武器是<自动机关炮>");
}
};
class Laser : public Weapon
{
public:
string getWeapon() override
{
return string("配备的武器是<激光>");
}
};
Ship类
// 轮船类
class Ship
{
public:
Ship(ShipBody* body, Weapon* weapon, Engine* engine) :
m_body(body), m_weapon(weapon), m_engine(engine)
{
}
string getProperty()
{
string info = m_body->getShipBody() + m_weapon->getWeapon() + m_engine->getEngine();
return info;
}
~Ship()
{
delete m_body;
delete m_engine;
delete m_weapon;
}
private:
ShipBody* m_body = nullptr;
Weapon* m_weapon = nullptr;
Engine* m_engine = nullptr;
};
工厂类及其子类
// 工厂类
class AbstractFactory
{
public:
virtual Ship* createShip() = 0;
virtual ~AbstractFactory() {}
};
class BasicFactory : public AbstractFactory
{
public:
Ship* createShip() override
{
Ship* ship = new Ship(new WoodBody, new Gun, new Human);
cout << "<基础型>战船生产完毕, 可以下水啦..." << endl;
return ship;
}
};
class StandardFactory : public AbstractFactory
{
public:
Ship* createShip() override
{
Ship* ship = new Ship(new IronBody, new Cannon, new Diesel);
cout << "<标准型>战船生产完毕, 可以下水啦..." << endl;
return ship;
}
};
class UltimateFactory : public AbstractFactory
{
public:
Ship* createShip() override
{
Ship* ship = new Ship(new MetalBody, new Laser, new Nuclear);
cout << "<旗舰型>战船生产完毕, 可以下水啦..." << endl;
return ship;
}
};
int main()
{
AbstractFactory* factroy = new StandardFactory;
Ship* ship = factroy->createShip();
cout << ship->getProperty();
delete ship;
delete factroy;
return 0;
}
抽象工厂模式适用于比较复杂的多变的业务场景,总体上就是给一系列功能相同但是属性会发生变化的组件(如:船体材料、武器系统、动力系统)添加一个抽象类,这样就可以非常方便地进行后续的拓展,再搭配工厂类就可以创建出我们需要的对象了。