简单工厂模式

1、背景

  • 我开一家披萨店,当客户需要某种披萨并且我这家店里也能做的时候,我就会为其提供所需要的披萨(当然是要钱的哈哈),如果其所需的我这没有,则是另外的情况,后面会谈。这时候,我这家
    披萨店就可以看做工厂(Factory),而生产出来的披萨被成为产品(Product),披萨的名称则被称为参数,工厂可以根据参数的不同返回不同的产品,这就是简单工厂模式
  • 工厂模式有一种非常形象的描述,建立对象的类就如一个工厂,而需要被建立的对象就是一个个产品;在工厂中加工产品,使用产品的人,不用在乎产品是如何生产出来的。从软件开发的角度来说,这样就有效的降低了模块之间的耦合。

2、定义

在这里插入图片描述
ProductA、ProductB和ProductC继承自Product虚拟类,Show方法是不同产品的自描述;Factory依赖于ProductA、ProductB和ProductC,Factory根据不同的条件创建不同的Product对象。

1、定义:

  • 定义一个工厂类,他可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类。
    • 简单工厂模式中用于被创建实例的方法通常为静态(static)方法,因此简单工厂模式又被成为静态工厂方法(Static Factory Method)

2、组成环节:

  • 1、Factory(工厂):核心部分,负责实现创建所有产品的内部逻辑,工厂类可以被外界直接调用,创建所需对象
    • 工厂类是整个模式的关键.包含了必要的逻辑判断,根据外界给定的信息,决定究竟应该创建哪个具体类的对象.通过使用工厂类,外界可以从直接创建具体产品对象的尴尬局面摆脱出来,仅仅需要负责“消费”对象就可以了
  • 2、Product(抽象类产品):工厂类所创建的所有对象的父类,封装了产品对象的公共方法,所有的具体产品为其子类对象
  • 3、ProductA、ProductB…(具体产品):简单工厂模式的创建目标,所有被创建的对象都是某个具体类的实例。它要实现抽象产品中声明的抽象方法

3、特征

  • 1、简单工厂模式的核心思想就是:有一个专门的类(工厂类)来负责创建实例的过程。
    • 把产品看着是一系列的类的集合,这些类是由某个抽象类或者接口派生出来的一个对象树。而工厂类用来产生一个合适的对象来满足客户的要求。
  • 2、如果简单工厂模式所涉及到的具体产品之间没有共同的逻辑,那么我们就可以使用接口来扮演抽象产品的角色;
    • 由于对象的创建过程是我们不需要去关心的,而我们注重的是对象的实际操作,所以,我们需要分离对象的创建和操作两部分,如此,方便后期的程序扩展和维护。
  • 3、如果具体产品之间有功能的逻辑或,我们就必须把这些共同的东西提取出来,放在一个抽象类中,然后让具体产品继承抽象类。
  • 4.在程序中,需要创建的对象很多,导致对象的new操作多且杂时,需要使用简单工厂模式;

缺点:

  • 5、工厂类集中了所有实例的创建逻辑,违反了高内聚责任分配原则,将全部创建逻辑集中到了一个工厂类中;它所能创建的类只能是事先考虑到的,如果需要添加新的类,则就需要改变工厂类
  • 6、当系统中的具体产品类不断增多时候,可能会出现要求工厂类根据不同条件创建不同实例的需求.这种对条件的判断和对具体产品类型的判断交错在一起,很难避免模块功能的蔓延

场景:

  • 1、工厂类负责创建的对象比较少;
  • 2、客户只知道传入工厂类的参数,对于如何创建对象(逻辑)不关心;

4、应用

对于一个只拥有加减乘除运算的简单计算器:

  • 1、设计一个Operation的父类 —— Product
  • 2、构造加减乘除四个类继承父类重写运算函数GetResult。—— ProductA、ProductB…(具体产品)
  • 3、定义工厂类中的工厂函数,其根据用户的输入new出相应的对象实例并返回其父类的指针。—— Factory(工厂)
    在这里插入图片描述
//简单工厂模式的核心是,对于一个父类的多个继承子类,
//工厂对象的工厂函数根据用户输入,自动new出一个子类对象并返回其父类的指针
//这样利用父类的指针执行父类的虚函数,就可以动态绑定子类的重写函数,从而实现多态。
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include  <memory>

using namespace std;

class Operation
{
private:
	double A, B;
public:
	double GetA() const { return A; }
	double GetB() const { return B; }
	void SetA(double x) { A = x; }
	void SetB(double y) { B = y; }
	double virtual GetResult() { return 0; }
	Operation() :A(0), B(0) {}
};

class Add : public Operation
{
public:
	double GetResult()
	{
		return GetA() + GetB();
	}
};

class Sub : public Operation
{
public:
	double GetResult()
	{
		return GetA() - GetB();
	}
};

class Mul : public Operation
{
public:
	double GetResult()
	{
		return GetA()*GetB();
	}
};

class Div : public Operation
{
public:
	double GetResult()
	{
		if (GetB() == 0)
		{
			throw exception("Error!Division by zero");
		}		
		else
			return GetA() / GetB();
	}
};

class SimpleFactory
{
public:
	static Operation * CreateOpeartor(char ch)
	{
			Operation * p;
			switch (ch)
			{
			case '+':
				p = new Add();
				break;
			case '-':
				p = new Sub();
				break;
			case '*':
				p = new Mul();
				break;
			case '/':
				p = new Div();
				break;
			}
			return p;
	}
};

int main(int argc, char *argv[])
{
	try 
	{
		double A = 0;
		double B = 0;
		char ch = '\0';
		cin >> A >> ch >> B;

		std::shared_ptr<Operation> op(SimpleFactory::CreateOpeartor(ch));
		op->SetA(A);
		op->SetB(B);
		cout << op->GetResult() << endl;
	}
	catch(exception ex)
	{
		cout << ex.what() << endl;
	}
	return 0;
}

在这里插入图片描述

参考

1、https://www.cnblogs.com/ygsworld/p/10649491.html、
2、程杰《大话设计模式》
3、https://blog.csdn.net/weiwenlongll/article/details/6918164
4、https://www.cnblogs.com/jostree/p/4251756.html

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐