写在前面
我们知道,设计模式的终极目标是高内聚,低耦合,好的软件代码必然离不开好的设计。最近在学习设计模式这块的内容,参考的书籍是程杰的《大话设计模式》,这本书对于初学者来说比较友好,易上手,博客里的内容是参考本书以及网络资源整理的。
博客更新基本上是边学边写的过程,写这个专题一是为了作为自己的知识备忘,二是希望能给正在学习设计模式的童鞋一些参考,博客中内容有纰漏或错误之处,还请指出,谢谢。
基本定义
抽象工厂,属于创建型模式。抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口,而无需指定他们具体的类。
UML图
抽象工厂包含的角色通常工厂方法一样,有以下4个要素组成,但是抽象工厂中方法个数不同,抽象产品的个数也不同。
包含以下几类角色:
AbstractFactory:抽象工厂角色(接口)。提供创建不同产品的方法接口CreateProduct1,CreateProduct2,...,由具体工厂角色实现。
ConcreteFactory:具体工厂角色。用于实现抽象工厂的抽象方法(CreateProduct1,CreateProduct2,...),完成具体产品的创建,这种具体工厂存在多个。
Product:抽象产品角色,是所有具体产品的父类,定义了产品的规范,主要特性和功能接口等。抽象工厂模式有多个抽象产品。
ConcreteProduct:具体产品角色,实现抽象产品类中定义的接口,具体产品由具体工厂来创建。
抽象工厂模式实例
场景:小明想买个台式机,这里假设台式机由主机+显示器+外设组成,此时可以用抽象工厂模式来模拟生产台式机的工厂,下面展开内容。
UML图
代码实现
1. 台式机工厂(抽象工厂)
class PcFactory {
public:
virtual Host* CreateHost() = 0;
virtual Display* CreateDisplay() = 0;
virtual Peripherals* CreatePeripherals() = 0;
};
2. 联想台式机工厂(具体工厂1)
class LenovoFactory : public PcFactory {
public:
Host* CreateHost()
{
std::cout << "Create Lenovo Host." << std::endl;
return new LenovoHost();
}
virtual Display* CreateDisplay()
{
std::cout << "Create Lenovo Display." << std::endl;
return new LenovoDisplay();
}
virtual Peripherals* CreatePeripherals()
{
std::cout << "Create Lenovo Peripherals." << std::endl;
return new LenovoPeripherals();
}
};
3. 戴尔台式机工厂(具体工厂2)
class DellFactory : public PcFactory {
public:
Host* CreateHost()
{
std::cout << "Create DellHost." << std::endl;
return new DellHost();
}
virtual Display* CreateDisplay()
{
std::cout << "Create Dell Display." << std::endl;
return new DellDisplay();
}
virtual Peripherals* CreatePeripherals()
{
std::cout << "Create Dell Peripherals." << std::endl;
return new DellPeripherals();
}
};
4. 抽象主机/联想主机/戴尔主机
class Host {
public:
virtual void ComputeSomething() = 0;
};
class LenovoHost : public Host {
public:
void ComputeSomething() {
std::cout << "LenovoHost Compute Something." << std::endl;
}
};
class DellHost : public Host {
public:
void ComputeSomething() {
std::cout << "DellHost Compute Something." << std::endl;
}
};
5. 抽象显示器/联想显示器/戴尔显示器
class Display {
public:
virtual void ShowSomething() = 0;
};
class LenovoDisplay : public Display {
public:
void ShowSomething() {
std::cout << "LenovoDisplay Show Something." << std::endl;
}
};
class DellDisplay : public Display {
public:
void ShowSomething() {
std::cout << "DellDisplay Show Something." << std::endl;
}
};
6. 抽象外设/联想外设/戴尔外设
class Peripherals {
public:
virtual void ClickSomething() = 0;
};
class LenovoPeripherals : public Peripherals {
public:
void ClickSomething() {
std::cout << "LenovoPeripherals Click Something." << std::endl;
}
};
class DellPeripherals : public Peripherals {
public:
void ClickSomething() {
std::cout << "DellPeripherals Click Something." << std::endl;
}
};
7. 客户端测试代码
int main(int argc, char* argv[])
{
PcFactory* lenovoFac = new LenovoFactory();
//组装电脑
Host* host = lenovoFac->CreateHost();
Display* display = lenovoFac->CreateDisplay();
Peripherals* peripherals = lenovaFac->CreatePeripherals();
//运行电脑
host->ComputeSomething();
display->ShowSomething();
peripherals->ClickSomething();
return 0;
}
测试结果
优缺点和使用场景
优点:
1.具体产品在应用层的代码隔离,无需关系创建的细节。
2. 将一个系列的产品统一到一起创建。
缺点:
1. 类数量可能较多,增加系统复杂度。
2. 产品族扩展非常困难,要增加一个系列的某一产品,既要在抽象的 Creator 里加代码,又要在具体的里面加代码。
使用场景:
当需要创建的对象是一系列相互关联或相互依赖的产品族时,便可以使用抽象工厂模式。说的更明白一点,就是一个继承体系中,如果存在着多个等级结构(即存在着多个抽象类),并且分属各个等级结构中的实现类之间存在着一定的关联或者约束,就可以使用抽象工厂模式。假如各个等级结构中的实现类之间不存在关联或约束,则使用多个独立的工厂来对产品进行创建,则更合适一点。