设计模式-工厂模式

发布于:2025-04-12 ⋅ 阅读:(34) ⋅ 点赞:(0)

目录

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

工厂模式有哪几种?

 简单工厂模式

缺点

工厂方法模式

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

抽象工厂模式

与工厂方法模式的区别


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

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

工厂模式有哪几种?

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

  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;
}


网站公告

今日签到

点亮在社区的每一天
去签到