工厂模式的分类
1、核心功能:根据“需求”生产“产品”。不需要关注对象的生成过程。简化名称,便于使用。
2、分类:实际上根据业务情景不同分为不同的实现方式。一般分3种:简单工厂模式(不属于23中模式中的一种)、工厂方法模式、抽象工厂模式。
简单工厂模式
1、核心思想:同一个“工厂”中生产多个“产品”。比如我们现在要得到苹果,香蕉,梨这三种水果。我们可以让他们在同一工厂中进行生产。只需要给他们对应得编号。1代表苹果,2代表香蕉,3代表梨。如下图所示:
2、代码实现:
class Fruit
{
public:
Fruit(std::string nm)
:mname(nm){}
virtual void operation() = 0;
protected:
std::string mname;
};
class apple : public Fruit
{
public:
Apple(std::string name)
:Fruit(name){}
void operation()
{
std::cout << "this is an apple!" << std::endl;
}
};
class Banana : public Fruit
{
public:
Banana(std::string name)
:Fruit(name){}
void operation()
{
std::cout<<"this is a banana!" << std::endl;
}
};
class Factory
{
public:
Fruit* createFruit(int flag)
{
switch(flag)
{
case 1:
return new Apple("apple");
break;
case 2:
return new Banana("banana");
break;
default:
return NULL;
break;
}
}
};
int main()
{
Factory fa;
Fruit* pf = fa.createFruit(1);//产苹果(把数字改为2得话就是产香蕉)
pf->operation();
return 0;
}
3、简单工厂模式的缺点
(1)比如来了更多的需求,3,4,5,6,7,8等,需要再写switch case或者 if else中维护工厂中的判断语句,造成的后果就是可能这个工厂类会非常非常长,各种判断全部挤在一起,给扩展和维护带来麻烦,就是说,工厂和产品还没有完全解耦,绑定在一起的。
得出结论:
简单工厂通过构造时传入的标识来生产产品,不同产品都在同一个工厂中生产,会随着产品的增加而增加,给扩展和维护带来麻烦。
(2)违背了开放–封闭的原则
- 开放原则:新版本设计时可以使用旧版本的代码。
- 封闭原则:不能修改旧版本的代码。
工厂方法模式
1、由上述的工厂的模式可以引出工厂方法模式。
工厂方法模式就是改变上述工厂模式中的一个工厂生产一种产品的模式,而是改成当想要生产什么产品就建立相应的工厂进行生产。
如下图所示:
2、代码实现
class Factory
{
public:
Factory(std::string name)
:mname(name){}
virtual Fruit* createFruit() = 0;
protected:
std::string mname;
};
class F1 : public Factory//产品F1
{
public:
F1(std::stding name)
:Factory(name){}
Fruit* createFruit()
{
return new Apple("apple");
}
};
class F2 : public Factory//产品F2
{};
...其他产品
int main()
{
Factory pf = new F1("f1");//生产苹果(改为F2和f1生产香蕉)
Fruit* pf = pfa->createFruit();
pf->operation();
return 0;
}
3、工厂方法模式的缺点
在上述代码中,已将工厂类分开,不再将所有产品都在同一工厂中生产,解决了简单工厂中不停的switch case问题。如果来了一个C产品,我们只需要写一个C工厂,一个C产品,在调用时用C工厂生产C产品即可,即A和B工厂和产品完全不受影响。
但仍存在问题:
当业务需求是需要生产产品族的时候,工厂就不再适合了,什么是产品族和产品等级结构呢?比如:
三星的洗衣机、电视机、冰箱就是三星这个工厂的产品族。
产品等级结构:例如洗衣机的等级结构中有三星的、四门子的、LG、海尔、三菱等等 。
抽象工厂模式
1、由上述的工厂方法模式引出抽象工厂模式。
工厂方法模式无法解决产品族和产品等级结构的问题。所以我们使用抽象工厂模式。
2、代码实现
class A//A族的产品
{
public:
A(std::string nm)
:mname(nm){}
virtual void operation() = 0;
protected:
std::string mname;
};
class A1 : public A
{
public:
A1(std::string nm)
:A(nm){}
virtual void operation()
{
std::cout << "a1" << std::endl;
}
};
class A2 : public B
{
public:
A2(std::string nm)
:A(nm){}
virtual void operation()
{
std::cout << "a2" <<std::endl;
}
};
class B//B族的产品(和A族产品设计一样)
{};
class AbastractFactory
{
public:
AbstractFactory(std::string nm)
:mname(nm)
{}
virtual A* createA() = 0;
virtual B* createB() = 0;
protected:
std::string mname;
};
class Factory_1 : public AbstractFactory//1号工厂产1号产品
{
public:
Factory_1(std::string name)
:AbstractFactory(name)
{}
virtual A* createA() //A族产线
{
return new A1("a1");
}
virtual B* createB()//B族产线
{
return new B1("b1");
}
};
class Factory_2 : public AbstractFactory//2号工厂产2号产品
{};//方法和工厂1相似
int main()
{
AbstractFactory* paf = new Factory_1("f1");//产一号产品就建一号工厂(要想生产2号产品就建2号工厂。改为Factory_2和f2)
A* pa = paf->createA();
B* pb = paf->createB();
pa->operation();
pb->operation();
return 0;
}
总结
- 可以看出,在工厂模式中,一个工厂生产一个产品,所有的具体产品都是由同一个抽象产品派生来的,不存在产品等级结构和产品族的概念;
- 而在抽象工厂中,同一个等级的产品是派生于一个抽象产品(即产品接口),一个抽象工厂派生不同的具体工厂,每个具体工厂生产自己的产品族(包含不同产品等级)。一个工厂生产多个产品,它们是一个产品族,不同的产品族的产品派生于不同的抽象产品(或产品接口)。
归纳总结
工厂模式其实是三种模式
- 实现越来越复杂。
- 简单工厂通过构造时传入的标识来生产产品,不同产品都在同一个工厂中生产,这种判断会随着产品的增加而增加,给扩展和维护带来麻烦。
- 工厂模式无法解决产品族和产品等级结构的问题
- 抽象工厂模式中,一个工厂生产多个产品,它们是一个产品族,不同的产品族的产品派生于不同的抽象产品(或产品接口)。