在上一篇文章中介绍了工厂模式,每个具体工厂负责生产一个专门的产品,其代码扩展性很好,这篇文章将介绍抽象工厂模式。
1.为什么要使用抽象工厂模式?
既然已经有了“工厂模式”,那为什么还会有抽象工厂模式呢?
这就涉及到创建“多类”对象了,在工厂方法模式中,每个具体工厂只负责创建单一的产品。但是如果有多类产品呢,比如说“手机”,一个品牌的手机有高端机、中低端机之分,这些具体的产品在工厂模式中都需要建立一个单独的工厂类,但是它们都是相互关联的,都共同属于同一个品牌,这就可以使用到【抽象工厂模式】。
抽象工厂模式可以确保一系列相关的产品被一起创建,这些产品能够相互配合使用,再举个例子,有一些家具,比如沙发、茶几、椅子,都具有古典风格的和现代风格的,抽象工厂模式可以将生产现代风格的家具放在一个工厂类中,将生产古典风格的家具放在另一个工厂类中,这样每个工厂类就可以生产一系列的家具。
2.抽象工厂模式的基本结构
抽象工厂模式包含多个抽象产品类,多个具体产品类,一个抽象工厂接口和多个具体工厂类,给个具体工厂杜泽创建一组相关的产品。
- 抽象产品接口
AbstractProduct
: 定义产品的接口,可以定义多个抽象产品接口,比如说沙发、椅子、茶几都是抽象产品。所谓抽象产品接口,其实就是表示生产产品的一个纯虚函数,具体实现由下面的具体产品类实现。 - 具体产品类
ConcreteProduct
: 实现抽象产品接口,产品的具体实现,古典风格和沙发和现代风格的沙发都是具体产品。 - 抽象工厂接口
AbstractFactory
: 声明一组用于创建产品的方法,每个方法对应一类产品。该接口也是纯虚函数,具体实现有具体工厂类完成。 - 具体工厂类
ConcreteFactory
: 实现抽象工厂接口,负责创建一组具体产品的对象,在本例中,生产古典风格的工厂和生产现代风格的工厂都是具体实例。
下面可以根据具体代码再理解上面的内容。
3.C++抽象工厂模式
【设计模式专题之抽象工厂模式】3. 家具工厂 (kamacoder.com)https://kamacoder.com/problempage.php?pid=1077
题目描述:
小明家新开了两个工厂用来生产家具,一个生产现代风格的沙发和椅子,一个生产古典风格的沙发和椅子,现在工厂收到了一笔订单,请你帮他设计一个系统,描述订单需要生产家具的信息。
输入描述:
输入的第一行是一个整数 N(1 ≤ N ≤ 100),表示订单的数量。
接下来的 N 行,每行输入一个字符串,字符串表示家具的类型。家具类型分为 "modern" 和 "classical" 两种。
输出描述:
对于每笔订单,输出字符串表示该订单需要生产家具的信息。
modern订单会输出下面两行字符串
modern chair
modern sofa
classical订单会输出下面两行字符串
classical chair
classical sofa
输入示例:
3
modern
classical
modern
输出示例:
modern chair
modern sofa
classical chair
classical sofa
modern chair
modern sofa
在上面的示例中,工厂收到了3笔订单,其中有2笔要求生产modern风格,1笔要求生产classical风格。根据输入的类型,每次订单生产的家具信息被输出到控制台上。
代码实现:
1.多个抽象产品类和多个具体产品类
根据题目,生产的产品有椅子和沙发两种,每种产品有现代和古典两种风格,那个椅子和沙发会各自对应一个抽象产品类,而现代椅子和古典椅子,现代沙发和古典沙发将是这两个抽象产品类的具体产品类。代码如下:
//抽象椅子类,里面包含生产接口produce()
class Chair{
public:
//抽象产品生产接口
virtual void produce() = 0;
};
//具体现代风格椅子类
class ModernChair : public Chair{
public:
//多态实现具体抽象产品生产接口的具体化
void produce() override{
cout<<"modern chair"<<endl;
}
};
//具体古典风格椅子类
class ClassicalChair : public Chair{
public:
//多态实现具体抽象产品生产接口的具体化
void produce() override{
cout<<"classical chair"<<endl;
}
};
//抽象沙发类
class Sofa{
public:
virtual void produce() = 0;
};
//具体现代沙发类
class ModernSofa:public Sofa{
public:
void produce() override{
cout<<"modern sofa"<<endl;
}
};
//具体古典沙发类
class ClassicalSofa:public Sofa{
public:
void produce() override{
cout<<"classical sofa"<<endl;
}
};
2.一个抽象工厂类和多个具体工厂类
抽象工厂定义了生产产品的动作接口,具体工厂可以生产同风格的多种产品。
/下面是抽象工厂类,声明一组用于创建产品的方法,每个方法对应一种产品
class AbstractFurnitureFactory{
public:
virtual Chair* createChair() = 0;
virtual Sofa* createSofa() = 0;
};
//有了抽象工厂,需要设计具体工厂类,每个类负责生产同一风格的多种不同产品
//具体现代风格家具工厂类
class ModernFurnitureFactory:public AbstractFurnitureFactory{
public:
//生产现代风格的椅子
Chair * createChair() override{
return new ModernChair();
}
//生产现代风格的沙发
Sofa* createSofa() override{
return new ModernSofa();
}
};
//具体古典风格家具工厂类
class ClassicalFurnitureFactory:public AbstractFurnitureFactory{
public:
//生产古典风格的椅子
Chair * createChair() override{
return new ClassicalChair();
}
//生产古典风格的沙发
Sofa* createSofa() override{
return new ClassicalSofa();
}
};
整体代码如下:
#include<iostream>
#include<string>
using namespace std;
//生产的产品大类有椅子chair和沙发sofa两种
//根据抽象工厂模式的要求,要有抽象产品类及其对应的具体产品类
//所以下面先创建chair和sofa的抽象产品类
//抽象椅子类,里面包含生产接口produce()
class Chair{
public:
virtual void produce() = 0;
};
//具体现代风格椅子类
class ModernChair : public Chair{
public:
void produce() override{
cout<<"modern chair"<<endl;
}
};
//具体古典风格椅子类
class ClassicalChair : public Chair{
public:
void produce() override{
cout<<"classical chair"<<endl;
}
};
//抽象沙发类
class Sofa{
public:
virtual void produce() = 0;
};
//具体现代沙发类
class ModernSofa:public Sofa{
public:
void produce() override{
cout<<"modern sofa"<<endl;
}
};
//具体古典沙发类
class ClassicalSofa:public Sofa{
public:
void produce() override{
cout<<"classical sofa"<<endl;
}
};
//下面是抽象工厂类,声明一组用于创建产品的方法,每个方法对应一种产品
class AbstractFurnitureFactory{
public:
virtual Chair* createChair() = 0;
virtual Sofa* createSofa() = 0;
};
//有了抽象工厂,需要设计具体工厂类,每个类负责生产同一风格的多种不同产品
//具体现代风格家具工厂类
class ModernFurnitureFactory:public AbstractFurnitureFactory{
public:
//生产现代风格的椅子
Chair * createChair() override{
return new ModernChair();
}
//生产现代风格的沙发
Sofa* createSofa() override{
return new ModernSofa();
}
};
//具体古典风格家具工厂类
class ClassicalFurnitureFactory:public AbstractFurnitureFactory{
public:
//生产古典风格的椅子
Chair * createChair() override{
return new ClassicalChair();
}
//生产古典风格的沙发
Sofa* createSofa() override{
return new ClassicalSofa();
}
};
int main()
{
//读取订单数量
int N;
cin>>N;
//处理订单
for(int i=0; i<N; ++i){
string furnitureType; //准备读取家具类型
cin>>furnitureType;
//创建相应风格的具体家具工厂
AbstractFurnitureFactory * factory = nullptr;
if(furnitureType == "modern"){
factory = new ModernFurnitureFactory();
}
else if(furnitureType == "classical"){
factory = new ClassicalFurnitureFactory();
}
//工厂去生产同风格的多个产品
//生产该风格的椅子
Chair * chair = factory->createChair();
//生产该风格的沙发
Sofa * sofa = factory->createSofa();
//输出信息
chair->produce();
sofa->produce();
//内存释放
delete chair;
delete sofa;
delete factory;
}
return 0;
}
简单工厂、工厂模式、抽象工厂模式的区别
-
简单工厂模式:一个工厂方法创建所有具体产品
-
工厂方法模式:一个具体工厂方法创建一个具体产品
-
抽象工厂模式:一个具体工厂方法可以创建一类具体产品
抽象工厂模式应用场景:
抽象工厂模式能够保证一系列相关的产品一起使用,并且在不修改客户端代码的情况下,可以方便地替换整个产品系列。但是当需要增加新的产品类时,除了要增加新的具体产品类,还需要添加新的抽象工厂接口,修改所有的具体工厂类的生产函数(使其也能够同时生产该类型的新产品),扩展性相对较差。因此抽象工厂模式特别适用于一系列相关或相互依赖的产品被一起创建的情况,典型的应用场景是使用抽象工厂模式来创建与不同数据库的连接对象。