目录
工厂模式是用来干什么的?
工厂模式是一种设计模式,用于创建对象实例的方法。它通过定义一个用于创建对象的接口,但让子类决定实例化哪个类来创建对象。这种模式使得一个类的实例化延迟到子类中,从而让子类来决定创建哪个类的实例。
工厂模式有哪几种?
工厂模式有三种常见的实现方式:简单工厂模式、工厂方法模式和抽象工厂模式。
简单工厂模式:由一个工厂类来决定创建哪个具体类的实例。客户端只需传递一个参数给工厂类,由工厂类根据参数的不同来创建不同的实例。
工厂方法模式:定义一个工厂创建对象的接口,但由子工厂类来决定具体实例化哪个类。每个子类都会对应创建一个特定的工厂对象。
抽象工厂模式:提供一个创建一系列相关或相互依赖对象的接口,而无需指定具体类。客户端使用工厂接口来创建一系列相关的对象,而不需要关心具体实现类。
简单工厂模式
简单工厂模式也叫静态工厂模式,具体是只使用一个工厂,根据用户传递的产品参数创建对应的产品;
下面我以水果工厂为例说明:
//水果类--抽象类
class fruits
{
public:
fruits() {}//继承实例化会调用默认构造
fruits(int num) :_num(num) {}
virtual ~fruits() {}
public:
virtual void debug() = 0;
private:
int _num;
};
//苹果类
class apple :public fruits
{
public:
apple(int num) :_num(num) {}
~apple() {}
public:
virtual void debug()override
{
printf("我是苹果,一共有%d个...\n", _num);
}
private:
int _num;
};
//香蕉类
class banana :public fruits
{
public:
banana(int num) :_num(num) {}
~banana() {}
public:
virtual void debug()override
{
printf("我是香蕉,一共有%d个...\n", _num);
}
private:
int _num;
};
由于工厂类用途侧重于创建对象,关键使用的技术是继承和多态,所以这里我使用一个产品基类,又实现了两个水果产品类(苹果,香蕉);并且使用了一个抽象方法debug用来调试证明确实创建了对象;
产品声明好了,下面就是工厂类:
class Factory
{
public:
fruits* Create(string fruit)
{
if (fruit == "banana")
{
return (fruits*)(new banana(10));
}
else if (fruit == "apple")
{
return (fruits*)(new apple(10));
}
}
};
这段代码其实不难理解,其实就是使用if,else if条件判断根据参数创建对象,注意返回值统一使用fruits*基类指针,这就是多态的用处;后序我们直接使用fruits* 调用debug就可以证明对象是哪一个了;
展示下整体代码:
namespace StaticFactory {
//水果类--抽象类
class fruits
{
public:
fruits() {}//继承实例化会调用默认构造
fruits(int num) :_num(num) {}
virtual ~fruits() {}
public:
virtual void debug() = 0;
private:
int _num;
};
//苹果类
class apple :public fruits
{
public:
apple(int num) :_num(num) {}
~apple() {}
public:
virtual void debug()override
{
printf("我是苹果,一共有%d个...\n", _num);
}
private:
int _num;
};
//香蕉类
class banana :public fruits
{
public:
banana(int num) :_num(num) {}
~banana() {}
public:
virtual void debug()override
{
printf("我是香蕉,一共有%d个...\n", _num);
}
private:
int _num;
};
class Factory
{
public:
fruits* Create(string fruit)
{
if (fruit == "banana")
{
return (fruits*)(new banana(10));
}
else if (fruit == "apple")
{
return (fruits*)(new apple(10));
}
}
};
}
这是测试用例:
/// 静态工厂模式
void TestStaticFactory()
{
using namespace StaticFactory;
Factory factory;
fruits* apple = factory.Create("apple");
apple->debug();
delete apple;
fruits* banana = factory.Create("banana");
banana->debug();
delete banana;
}
运行结果:
缺点
违背开闭原则:每次新增一个产品类型,都需要修改简单工厂的代码以支持新产品的创建,违背了开闭原则,即系统的设计应该是对扩展开放,对修改关闭。
职责过重:简单工厂模式将产品的创建和对象的选择逻辑放在同一个工厂类中,导致工厂类职责过重,难以维护和扩展。
可扩展性差:当需要新增产品类型时,需要修改简单工厂类的代码,容易引起其他部分代码的影响,使系统的扩展性变差。
单一职责原则:简单工厂模式中的工厂类不仅负责创建对象,还要负责选择具体产品类型,违反了单一职责原则。
系统复杂度增加:随着产品类型的增加,简单工厂模式的工厂类会变得越来越复杂,使得系统整体变得复杂难以维护。
针对这些缺点,可以考虑使用其他设计模式,如工厂方法模式、抽象工厂模式等来解决问题。
工厂方法模式
工厂方法模式每次新增对象不会影响到其他的产品生产,这里采用的策略是一个产品对应一个工厂,一种工厂只生产一种产品;所以就会有多个工厂;
话不多说,直接看代码:
(---前面的产品类与上面的是一样的)
//------------------------工厂部分------------------------------
class Factory
{
public:
virtual fruits* createobj() = 0;
};
class AppleFactory :public Factory
{
public:
virtual fruits* createobj()override
{
return (fruits*)(new apple(10));
}
};
class BananaFactory :public Factory
{
public:
virtual fruits* createobj()override
{
return (fruits*)(new banana(10));
}
};
这里我们让每一个创建一种产品,这样我们即使新增产品,也只需要新增一个工厂继承Factory既可以了,不会影响到其他的工厂和产品的生产;起到了解耦合作用;
使用模版创建工厂优化代码
我们会发现,如果工厂太多每次都需要手写一个实在是太麻烦了,那我们观察到其实这些工厂类结构是很相似的只有产品不同,所以我们可以使用模版类,来让编译器帮我们生成代码,爽歪歪!
故此,工厂部分可以替换成这样:
class Factory
{
public:
virtual fruits* createobj() = 0;
};
//使用模版简化代码
template <class fruit>
class ObjFactory :public Factory
{
public:
virtual fruits* createobj()override
{
return (fruit*)(new fruit(200));
}
};
是不是轻松多了?
完整代码展示:
namespace FactoryMethod {
//-----------------------------产品部分-----------------------
//水果类--抽象类
class fruits
{
public:
fruits() {}//继承实例化会调用默认构造
fruits(int num) :_num(num) {}
virtual ~fruits() {}
public:
virtual void debug() = 0;
private:
int _num;
};
//苹果类
class apple :public fruits
{
public:
apple(int num) :_num(num) {}
~apple() {}
public:
virtual void debug()override
{
printf("我是苹果,一共有%d个...\n",_num);
}
private:
int _num;
};
//香蕉类
class banana :public fruits
{
public:
banana(int num) :_num(num) {}
~banana() {}
public:
virtual void debug()override
{
//cout << "我是香蕉,...." << endl;
printf("我是香蕉,一共有%d个...\n",_num);
}
private:
int _num;
};
//------------------------工厂部分------------------------------
class Factory
{
public:
virtual fruits* createobj() = 0;
};
class AppleFactory :public Factory
{
public:
virtual fruits* createobj()override
{
return (fruits*)(new apple(10));
}
};
class BananaFactory :public Factory
{
public:
virtual fruits* createobj()override
{
return (fruits*)(new banana(10));
}
};
///
//使用模版简化代码
template <class fruit>
class ObjFactory :public Factory
{
public:
virtual fruits* createobj()override
{
return (fruit*)(new fruit(200));
}
};
}
这是测试用例,大家也可以自己写用例,我这里仅供参考:
/// 工厂方法模式测试
void TestFactoryMethod1()
{
using namespace FactoryMethod;
//生产苹果
Factory* appfactobj = new AppleFactory();
fruits* appleobj = appfactobj->createobj();
appleobj->debug();
delete appfactobj; delete appleobj;
//生产香蕉
Factory* banfactobj = new BananaFactory();
fruits* bananaobj = banfactobj->createobj();
bananaobj->debug();
delete banfactobj; delete bananaobj;
}
//使用模版优化
void TestFactoryMethod2()
{
using namespace FactoryMethod;
Factory* applefact = new ObjFactory<apple>();
fruits* apple = applefact->createobj();
apple->debug();
delete apple; delete applefact;
Factory* bananafact = new ObjFactory<banana>();
fruits* banana = bananafact->createobj();
banana->debug();
delete banana; delete bananafact;
}
抽象工厂模式
我们学完工厂方法模式后,其实学习抽象工厂模式不难,二者在代码上其实差别不是很大,在实现逻辑上稍有不同;
这里我以游戏中,(角色)战士,法师,(武器)剑,法杖为例;我们会发现其实这里不只有一类产品;
---->武器产品
class Weapon {
public:
virtual void use() = 0;
};
// 具体产品:剑
class Sword : public Weapon {
public:
void use() override {
std::cout << "使用剑进行攻击" << std::endl;
}
};
// 具体产品:法杖
class Staff : public Weapon {
public:
void use() override {
std::cout << "使用法杖释放魔法" << std::endl;
}
};
---->角色产品
// 抽象产品:角色
class Character {
public:
virtual void attack() = 0;
};
// 具体产品:战士
class Warrior : public Character {
private:
Weapon* weapon;
public:
Warrior(Weapon* weapon) : weapon(weapon) {}
void attack() override {
std::cout << "战士";
weapon->use();
}
};
// 具体产品:法师
class Mage : public Character {
private:
Weapon* weapon;
public:
Mage(Weapon* weapon) : weapon(weapon) {}
void attack() override {
std::cout << "法师";
weapon->use();
}
};
先不说工厂,我们来分析下这两类产品,是否有联系;
战士--剑,法师--法杖,对吧,不同的角色对应着相应使用的武器,这就是其中存在的联系和逻辑关系(其实这就是与工厂方法模式的区别);
我们再来看一下工厂是什么样的;
// 抽象工厂
class AbstractFactory {
public:
virtual Weapon* createWeapon() = 0;
virtual Character* createCharacter(Weapon* weapon) = 0;
};
// 具体工厂:战士工厂
class WarriorFactory : public AbstractFactory {
public:
Weapon* createWeapon() override {
return new Sword();
}
Character* createCharacter(Weapon* weapon) override {
return new Warrior(weapon);
}
};
// 具体工厂:法师工厂
class MageFactory : public AbstractFactory {
public:
Weapon* createWeapon() override {
return new Staff();
}
Character* createCharacter(Weapon* weapon) override {
return new Mage(weapon);
}
};
我们会发现工厂整体上还是一种工厂对应着一种对象,那这和工厂方法模式有什么区别呢?
与工厂方法模式的区别
我们可以回头观察一下工厂方法模式,工厂方法模式的工厂是不是侧重于只创建一种对象;
而抽象方法模式,工厂中侧重于创建的是一系列对象,在同一个工厂中的对象彼此之间是相互依赖的,战士使用剑,法师使用法杖;战士不能没有剑,法师不能没有法杖;
为什么叫做抽象工厂,因为工厂中的对象不止一个,而且他们之间存在的依赖关系,而关系是看不见,摸不着的,与工厂方法模式相比更加复杂,谓之抽象!!!
完整代码演示:
namespace AbstractFactoryModule {
// 抽象产品:武器
class Weapon {
public:
virtual void use() = 0;
};
// 具体产品:剑
class Sword : public Weapon {
public:
void use() override {
std::cout << "使用剑进行攻击" << std::endl;
}
};
// 具体产品:法杖
class Staff : public Weapon {
public:
void use() override {
std::cout << "使用法杖释放魔法" << std::endl;
}
};
// 抽象产品:角色
class Character {
public:
virtual void attack() = 0;
};
// 具体产品:战士
class Warrior : public Character {
private:
Weapon* weapon;
public:
Warrior(Weapon* weapon) : weapon(weapon) {}
void attack() override {
std::cout << "战士";
weapon->use();
}
};
// 具体产品:法师
class Mage : public Character {
private:
Weapon* weapon;
public:
Mage(Weapon* weapon) : weapon(weapon) {}
void attack() override {
std::cout << "法师";
weapon->use();
}
};
// 抽象工厂
class AbstractFactory {
public:
virtual Weapon* createWeapon() = 0;
virtual Character* createCharacter(Weapon* weapon) = 0;
};
// 具体工厂:战士工厂
class WarriorFactory : public AbstractFactory {
public:
Weapon* createWeapon() override {
return new Sword();
}
Character* createCharacter(Weapon* weapon) override {
return new Warrior(weapon);
}
};
// 具体工厂:法师工厂
class MageFactory : public AbstractFactory {
public:
Weapon* createWeapon() override {
return new Staff();
}
Character* createCharacter(Weapon* weapon) override {
return new Mage(weapon);
}
};
}
void TestAbstractFactory()
{
using namespace AbstractFactoryModule;
// 创建战士工厂
AbstractFactory* warriorFactory = new WarriorFactory();
// 创建战士的武器
Weapon* sword = warriorFactory->createWeapon();
// 创建战士角色
Character* warrior = warriorFactory->createCharacter(sword);
warrior->attack();
// 创建法师工厂
AbstractFactory* mageFactory = new MageFactory();
// 创建法师的武器
Weapon* staff = mageFactory->createWeapon();
// 创建法师角色
Character* mage = mageFactory->createCharacter(staff);
// 法师攻击
mage->attack();
// 释放内存
delete warrior;
delete sword;
delete warriorFactory;
delete mage;
delete staff;
delete mageFactory;
}