参考:https://zhuanlan.zhihu.com/p/476420041
什么是工厂?负责创建对象,实现其细节的类被称为工厂(Factory)。
简单工厂是对工厂最基础的实现方式,其实都不能算作是一种设计模式,而是更像是一种编程习惯。
简单工厂的目的是将“类实例化的操作”与“使用对象的操作”分开,让使用者不用知道具体参数就可以实例化出所需要的“产品”类,从而避免了在客户端代码中显式指定,实现了解耦。 即使用者可直接消费产品而不需要知道其生产的细节。
简单工厂实现的逻辑是创建一个factory类,在类成员函数中通过判断传进来的参数用new方法生成不同的product,将product返回。
代码示例
#include
#include "Product.cpp"
using namespace std;
class SimpleFactory{
public:
Product* getProduct(PRODUCT_TYPE type){
Product* product = nullptr;
switch(type){
case APPLE:
product = new AppleProduct(5);
break;
case BANANA:
product = new BananaProduct(2);
break;
case PEAR:
product = new PearProduct(3);
break;
default:
cout << "No this product." << std::endl;
}
return product;
}
};
int main(){
SimpleFactory *factory = new SimpleFactory();
Product* apple = factory->getProduct(APPLE);
Product* banana = factory->getProduct(BANANA);
Product* pear = factory->getProduct(PEAR);
delete apple;
delete banana;
delete pear;
}
这种方法的缺点很明显,当product的种类变多时,需要不断地进入SimpleFactory里修改里面的分支语句。这种做法违背了开闭原则(对扩展开放,对修改关闭)。并且此工厂类集中了所有产品的创建逻辑,职责过重,一旦不能正常工作,整个系统都要受到影响。
静态工厂类似于简单工厂,区别就是里面的创建方法采用了设为成了static。这样做的好处可以不需要实例化此类便可调用该静态方法。并且静态方法可以访问类中的私有成员,这样这个类的构造函数是private属性时,外界没法直接调用构造函数创建此对象,但是可以通过此静态方法创建此对象。这样做对创建对象进行了更严格的控制。
#include
#include
using namespace std;
template
class Lists{
public:
Lists(){} //私有构造函数,防止通过构造函数直接创建对象
public:
static Lists* newList(){
return new Lists;
}
vector v;
};
int main(){
// Lists l1; //error
Lists* l1 = Lists::newList();
l1->v.push_back(100.99);
std::cout << l1->v[0] << std::endl;
}
工厂模式其实就是把SimpleFactory里的分支语句每一条拎出来单独封装成工厂的子类。这样原先由工厂负责判断生产的逻辑转移成由子类决定如何生产。这样保证了开闭原则——当有新的产品加入时不需要去修改factory类,而只是增加生产此产品的工厂类。
需要创建什么样的产品则实例化相应的子工厂。
示例代码
#include
#include "Product.cpp"
using namespace std;
class Factory{
public:
virtual Product* getProduct()=0;
};
class AppleFactory : public Factory{
Product* getProduct(){
Product* product = new AppleProduct(5);
return product;
}
};
class BananaFactory : public Factory{
Product* getProduct(){
Product* product = new BananaProduct(2);
return product;
}
};
class PearFactory : public Factory{
Product* getProduct(){
Product* product = new PearProduct(3);
return product;
}
};
int main(){
Factory* fApple = new AppleFactory();
Factory* fBanana = new BananaFactory();
Factory* fPear = new PearFactory();
Product* apple = fApple->getProduct();
Product* banana = fBanana->getProduct();
Product* pear = fPear->getProduct();
delete apple;
delete banana;
delete pear;
delete fApple;
delete fBanana;
delete fPear;
}
抽象工厂模式跟工厂模式很类似,可以说是同一套逻辑。唯一的变化是工厂模式针对的是一种产品,而抽象工厂处理的是一族产品。
比方说,之前你的任务是得到一种水果,当你需要苹果这个产品的时候,你去找苹果厂;当你需要梨时,你去找梨厂。而现在你接到的任务是你需要做一个水果拼盘,水果拼盘的组成是苹果、香蕉和梨。你可以决定是找佳沃生产或者找百果园生产。这个时候工厂的生产目的是一族产品而不是单一的产品了。于是可以写一个抽象的Factory类,再具体实现一个佳沃Factory类和一个百果园Factory。每个子Factory都会可以生产apple,banana和pear三种水果。如果你想要佳沃生产的水果拼盘,可以找JFactory,如果想要百果园生产的水果拼盘,则找PFactory。
代码实例
#include
using namespace std;
enum PRODUCT_TYPE{APPLE, BANANA, PEAR};
class Product{
public:
Product(){}
virtual ~Product(){};
};
class AppleProduct : public Product{};
class JApple : public AppleProduct{
public:
JApple(){
std::cout << "get an apple from JOYVIO." << std::endl;
}
virtual ~JApple(){
std::cout << "eat an apple from JOYVIO." << std::endl;
}
};
class PApple : public AppleProduct{
public:
PApple(){
std::cout << "get an apple from Pagoda." << std::endl;
}
virtual ~PApple(){
std::cout << "eat an apple from Pagoda." << std::endl;
}
};
class BananaProduct : public Product{};
class JBanana : public BananaProduct{
public:
JBanana(){
std::cout << "get an banana from JOYVIO." << std::endl;
}
virtual ~JBanana(){
std::cout << "eat an banana from JOYVIO." << std::endl;
}
};
class PBanana : public BananaProduct{
public:
PBanana(){
std::cout << "get an banana from Pagoda." << std::endl;
}
virtual ~PBanana(){
std::cout << "eat an banana from Pagoda." << std::endl;
}
};
class PearProduct : public Product{};
class JPear : public PearProduct{
public:
JPear(){
std::cout << "get an pear form JOYVIO." << std::endl;
}
virtual ~JPear(){
std::cout << "eat an pear from JOYVIO." << std::endl;
}
};
class PPear : public PearProduct{
public:
PPear(){
std::cout << "get an pear from Pagoda." << std::endl;
}
virtual ~PPear(){
std::cout << "eat an pear from Pagoda." << std::endl;
}
};
class Factory{
public:
virtual Product* getApple()=0;
virtual Product* getBanana()=0;
virtual Product* getPear()=0;
};
class JFactory : public Factory{
public:
Product* getApple(){
return new JApple;
}
Product* getBanana(){
return new JBanana;
}
Product* getPear(){
return new JPear;
}
};
class PFactory : public Factory{
public:
Product* getApple(){
return new PApple;
}
Product* getBanana(){
return new PBanana;
}
Product* getPear(){
return new PPear;
}
};
int main(){
PFactory* factory = new PFactory;
Product* a = factory->getApple();
Product* b = factory->getBanana();
Product* p = factory->getPear();
delete factory;
delete a;
delete b;
delete p;
}
当你用工厂模式,如果你需要添加一种水果,比如你要的是菠萝。这个时候你创建了菠萝这个类,所需要的是再创建一个生产菠萝的子类继承基类Factory。工厂模式可以做到在你添加产品或者删除产品的时候,无须对原有类进行修改,遵守了开闭原则。
抽象工厂模式是在添加一族产品的时候无须对原有类进行修改。设想你现在不满足于佳沃和百果园的水果,你想从小蔡家进水果,这个时候在创建了小蔡家相应的产品后,只需要再创建一个专门用来生产小蔡家水果的factory。同样做到了开闭原则。但是如果需要添加产品种类,还是得对原有类进行修改。比如说你的水果拼盘不再是苹果、香蕉和梨三种搭配,而是需要菠萝,草莓...