欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 房产 > 建筑 > 设计模式-工厂模式

设计模式-工厂模式

2025/4/19 5:16:59 来源:https://blog.csdn.net/2301_80418172/article/details/147118144  浏览:    关键词:设计模式-工厂模式

目录

工厂模式是用来干什么的?

工厂模式有哪几种?

 简单工厂模式

缺点

工厂方法模式

使用模版创建工厂优化代码

抽象工厂模式

与工厂方法模式的区别


工厂模式是用来干什么的?

工厂模式是一种设计模式,用于创建对象实例的方法。它通过定义一个用于创建对象的接口,但让子类决定实例化哪个类来创建对象。这种模式使得一个类的实例化延迟到子类中,从而让子类来决定创建哪个类的实例。

工厂模式有哪几种?

工厂模式有三种常见的实现方式:简单工厂模式、工厂方法模式和抽象工厂模式。

  1. 简单工厂模式:由一个工厂类来决定创建哪个具体类的实例。客户端只需传递一个参数给工厂类,由工厂类根据参数的不同来创建不同的实例。

  2. 工厂方法模式:定义一个工厂创建对象的接口,但由子工厂类来决定具体实例化哪个类。每个子类都会对应创建一个特定的工厂对象。

  3. 抽象工厂模式:提供一个创建一系列相关或相互依赖对象的接口,而无需指定具体类。客户端使用工厂接口来创建一系列相关的对象,而不需要关心具体实现类。

 简单工厂模式

简单工厂模式也叫静态工厂模式,具体是只使用一个工厂,根据用户传递的产品参数创建对应的产品;

下面我以水果工厂为例说明:

//水果类--抽象类
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;
}

运行结果:

缺点

  1. 违背开闭原则:每次新增一个产品类型,都需要修改简单工厂的代码以支持新产品的创建,违背了开闭原则,即系统的设计应该是对扩展开放,对修改关闭。

  2. 职责过重:简单工厂模式将产品的创建和对象的选择逻辑放在同一个工厂类中,导致工厂类职责过重,难以维护和扩展。

  3. 可扩展性差:当需要新增产品类型时,需要修改简单工厂类的代码,容易引起其他部分代码的影响,使系统的扩展性变差。

  4. 单一职责原则:简单工厂模式中的工厂类不仅负责创建对象,还要负责选择具体产品类型,违反了单一职责原则。

  5. 系统复杂度增加:随着产品类型的增加,简单工厂模式的工厂类会变得越来越复杂,使得系统整体变得复杂难以维护。

针对这些缺点,可以考虑使用其他设计模式,如工厂方法模式、抽象工厂模式等来解决问题。

工厂方法模式

工厂方法模式每次新增对象不会影响到其他的产品生产,这里采用的策略是一个产品对应一个工厂,一种工厂只生产一种产品;所以就会有多个工厂;

话不多说,直接看代码:
(---前面的产品类与上面的是一样的)

//------------------------工厂部分------------------------------
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;
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词