设计模式~工厂模式
工厂模式
- 工厂模式是典型的继承多态。【继承多态】
- 工厂模式封装了对象的创建,即用户不逼自己调用产品的构造函数,是要通过相应的函数接口即可。
工厂模式的分类
- 简单工厂(Simple Factory)
- 工厂方法(Factory Method)
- 抽象工厂(Abstract Factory)
简单工厂
#include <iostream>
#include <memory>
#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;
}
};
// 奥迪
class Audi :public Car
{
public:
Audi(string name) :Car(name) {}
void show()
{
cout << "获取一个奥迪:" << _name << endl;
}
};
enum CarType { BMW,AUDI };
class SimpleFactory
{
public:
Car* createCar(CarType ct)
{
switch (ct)
{
case BMW:
return new Bmw("x6");
case AUDI:
return new Audi("A8");
default:
cerr << "传入参数错误" << ct << endl;
return nullptr;
}
}
};
int main()
{
// 智能指针
unique_ptr<SimpleFactory> factory(new SimpleFactory());
unique_ptr<Car> p1(factory->createCar(BMW));
unique_ptr<Car> p2(factory->createCar(AUDI));
p1->show();
p2->show();
return 0;
}
- 简单工厂将对象的创建封装到一个接口函数中,通过传入不同的类标识,然后返回不同的对象(汽车),可用不用知道对象创建的过程。
- 但是简单工厂的在设计上违背了软件设计的开闭原则,因为createCar这个函数,一旦有新的工厂,就需要修改。
- 同时也不符合实际情况,不同的品牌应该在不同的工厂。
工厂方法
#include <iostream>
#include <memory>
#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;
}
};
// 奥迪
class Audi :public Car
{
public:
Audi(string name) :Car(name) {}
void show()
{
cout << "获取一个奥迪:" << _name << endl;
}
};
// 工厂基类
class Factory
{
public:
virtual Car* createCar(string name) = 0;
};
// 宝马工厂
class BmwFactory:public Factory
{
Car* createCar(string name)
{
return new Bmw(name);
}
};
// 奥迪工厂
class AudiFactory :public Factory
{
Car* createCar(string name)
{
return new Audi(name);
}
};
int main()
{
unique_ptr<Factory> bmwfactory(new BmwFactory());
unique_ptr<Factory> audifactory(new AudiFactory());
unique_ptr<Car> p1(bmwfactory->createCar("X6"));
unique_ptr<Car> p2(audifactory->createCar("A8"));
p1->show();
p2->show();
return 0;
}
- 为工厂提供基类,不同产品的工厂由工厂基类派生,然后重写方法。这样的设计符合实际情况,不同的品牌有自己的工厂
- 但是这样的设计还是需要改进,因为同一种品牌可能由多种产品,如果按照工厂方法设计,会出现大量的工厂类,难以维护
抽象工厂
// 汽车基类
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;
}
};
// 奥迪
class Audi :public Car
{
public:
Audi(string name) :Car(name){}
void show()
{
cout << "获取一个奥迪:" << _name << endl;
}
};
// 车灯基类
class Light
{
public:
virtual void show() = 0;
};
// 宝马牌车灯
class BmwLight : public Light
{
public:
void show()
{
cout << "获取一个宝马牌车灯" << endl;
}
};
// 奥迪牌车灯
class AudiLight : public Light
{
public:
void show()
{
cout << "获取一个奥迪牌车灯" << endl;
}
};
// 工厂基类
class AbstractFactory
{
public:
virtual Car* createCar(string name) = 0;
virtual Light* createLight(string name) = 0;
};
// 宝马工厂
class BmwFactory :public AbstractFactory
{
Car* createCar(string name)
{
return new Bmw(name);
}
Light*createLight()
{
return new BmwLight();
}
};
// 奥迪工厂
class AudiFactory :public AbstractFactory
{
Car* createCar(string name)
{
return new Audi(name);
}
Light*createLight()
{
return new AudiLight();
}
};
int main()
{
unique_ptr<AbstractFactory> bmwfactory(new BmwFactory());
unique_ptr<AbstractFactory> audifactory(new AudiFactory());
unique_ptr<Car> p1(bmwfactory->createCar("X6"));
unique_ptr<Car> p2(audifactory->createCar("A8"));
unique_ptr<Light> l1(bmwfactory->createLight("X6"));
unique_ptr<Light> l2(audifactory->createLight("A8"));
p1->show();
p2->show();
l1->show();
l2->show();
return 0;
}
- 抽象工厂可以看作是工厂方法的改进,因为它将统一品牌的产品都设计在一个工厂生产,符合实际。
总结
- 工厂模式的典型的继承多态,使用基类的指针接收派生类对象,虚函数重写,代码复用和多态。
- 不同的场景可以使用不同的工厂模式,各有优缺点。
新手上路,如有错误,请指出!!!