文章目录
- 简单工厂模
- 什么是简单工厂模式?
- 如何实现简单工厂模式?
- 工厂方法
- 抽象工厂模式
- 总结
- 简单工厂模式
- 工厂方法
- 抽象工厂「Abstract Factory」
简单工厂模
什么是简单工厂模式?
简单工厂模式是一种创新型的设计模式,当有一个基类和若干个派生类形成多态时,用于无须知道类对象是如何被创建的。当用户要创建对象时,直接向工厂申请即可。
如何实现简单工厂模式?
#include<iostream>
#include<string>
#include<functional>
#include<string>
using namespace std;
//基类
class Car
{
public:
Car(string name)
:_name(name)
{}
//在派生类中,该接口必须被实现
virtual void show() = 0;
protected:
string _name;
};
//派生类
class BMW :public Car
{
public:
BMW(string name)
:Car(name)
{}
void show()
{
cout << "获取了一辆宝马汽车: " <<_name<< endl;
}
private:
};
//派生类
class AoDi :public Car
{
public:
AoDi(string name)
:Car(name)
{}
void show()
{
cout << "获取了一辆奥迪汽车: " <<_name<< endl;
}
};
enum car_type
{
bmw,
aodi,
};
//这就是一个简单工厂类。通过该类,我们不需要知道类对象创建的具体细节。使用时调用即可。
class SimplayFactory
{
public:
static Car* CreateCar(car_type ct, string name)
{
switch (ct)
{
case bmw:
return new BMW(name);
case aodi:
return new AoDi(name);
break;
default:
cerr << "输入错误" << endl ;
break;
}
}
};
int main()
{
Car* car1 = SimplayFactory::CreateCar(aodi, "x1");
car1->show();
}
但是这样实现也有缺点:奥迪和宝马不可能在同一个工厂了被创建。然后这个工厂类也不符合开闭的原则「拓展开放,实现关闭」。基于这样的缺点,工厂方法应运而生。
工厂方法
工厂方法的实现如下:
//工厂方法 基类
class Factory
{
public:
virtual Car* createCar(string name) = 0;
};
//不同工厂的具体实现 派生类
class BMWFactory :public Factory
{
public:
Car* createCar(string name)
{
return new BMW(name);
}
};
//不同工厂的具体实现 派生类
class AoDiFactory
{
Car* createCar(string name)
{
return new AoDi(name);
}
};
int main()
{
unique_ptr< Factory> bmwfaty(new BMWFactory());
unique_ptr<Car>p1(bmwfaty->createCar("x6"));
p1->show();
}
当我们想增加奔驰的创建工厂的话,根本不需要动宝马和奥迪的工厂,我们只需要从基类中继承实现一个派生类,然后重写creator即可.
但是,一个工厂往往不止制造一产品,我们知道奥迪的车灯很出名,那么奥迪的工厂可能在造车的同时还会生产车灯,如果按照我们的工厂模式的话,就需要创建很多的类,这时就需要抽象工厂模式「在一个工厂内部,允许创建若干种产品」。
抽象工厂模式
代码如下,我们总体上还是使用刚刚的代码。
#include<iostream>
#include<string>
#include<functional>
#include<string>
using namespace std;
//基类
class Car
{
public:
Car(string name)
:_name(name)
{}
//在派生类中,该接口必须被实现
virtual void show() = 0;
protected:
string _name;
};
//派生类
class BMW :public Car
{
public:
BMW(string name)
:Car(name)
{}
void show()
{
cout << "获取了一辆宝马汽车: " <<_name<< endl;
}
private:
};
//派生类
class AoDi :public Car
{
public:
AoDi(string name)
:Car(name)
{}
void show()
{
cout << "获取了一辆奥迪汽车: " <<_name<< endl;
}
};
class Light
{
public:
virtual void show(string name) = 0;
};
class BMWLight :public Light
{
public:
void show(string name)
{
cout << "BMW:" << name << endl;
}
};
class AoDiLight :public Light
{
public:
void show(string name)
{
cout << "AoDi:" << name << endl;
}
};
enum car_type
{
bmw,
aodi,
};
class Factory
{
public:
virtual Car* createCar(string name) = 0;
virtual Light* createCarLight() = 0;
};
class BMWFactory :public Factory
{
public:
Car* createCar(string name)
{
return new BMW(name);
}
Light* createCarLight()
{
return new BMWLight();
}
};
class AoDiFactory
{
public:
Car* createCar(string name)
{
return new AoDi(name);
}
Light* createCarLight()
{
return new AoDiLight();
}
};
int main()
{
unique_ptr< Factory> bmwfaty(new BMWFactory());
unique_ptr<Car>p1(bmwfaty->createCar("x6"));
unique_ptr<Light>l1(bmwfaty->createCarLight());
l1->show("a1");
p1->show();
}
总结
在历史进步的长河中,一种技术的出现,一定是为了解决前面技术带来的问题「弊端」。接下来,我们分析一下如上几种方案带来的问题:
简单工厂模式
优点
把对象的创建封装到一个接口函数里边,通过传入不同的标记,返回创建的对象。客户不用自己负责new对象。不用了解对象创建的详细过程。
缺点
提供创建对象实例的接口不闭合,不能对外修改关闭。
工厂方法
优点
Factory基类,提供了一个纯虚函数(创建产品)。定义派生类「具体产品的工厂」负责创建对应的产品,可以做到不同的产品,在不同的产品工厂里创建,能够对现有工厂以及产品的修改关闭。
缺点
实际上,很多产品都是有关联关系的,属于一个产品族,不应该放在 不同的工厂里创建,这样不符合实际的产品创建的创建逻辑,二是工厂类太多了,不好维护。
抽象工厂「Abstract Factory」
把有关联的,属于同一个产品系列的的所有产品的创建接口,放在同一个抽象工厂里边,派生类应负责常见该工厂内所有的产品。