C++设计模式Learning:抽象工厂

写在前面

我们知道,设计模式的终极目标是高内聚,低耦合,好的软件代码必然离不开好的设计。最近在学习设计模式这块的内容,参考的书籍是程杰的《大话设计模式》,这本书对于初学者来说比较友好,易上手,博客里的内容是参考本书以及网络资源整理的。

博客更新基本上是边学边写的过程,写这个专题一是为了作为自己的知识备忘,二是希望能给正在学习设计模式的童鞋一些参考,博客中内容有纰漏或错误之处,还请指出,谢谢。

基本定义

抽象工厂,属于创建型模式。抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口,而无需指定他们具体的类。

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 里加代码,又要在具体的里面加代码。

使用场景:

当需要创建的对象是一系列相互关联或相互依赖的产品族时,便可以使用抽象工厂模式。说的更明白一点,就是一个继承体系中,如果存在着多个等级结构(即存在着多个抽象类),并且分属各个等级结构中的实现类之间存在着一定的关联或者约束,就可以使用抽象工厂模式。假如各个等级结构中的实现类之间不存在关联或约束,则使用多个独立的工厂来对产品进行创建,则更合适一点。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
桥接模式和抽象工厂是两个不同的设计模式,但是可以结合使用。下面我来简单介绍一下如何在C++中实现桥接模式和抽象工厂。 首先,我们需要定义桥接模式中的抽象类和实现类。假设我们要实现一个图形库,可以绘制不同类型的图形,包括圆形、矩形和三角形。我们可以定义一个抽象类Shape,表示图形的基本属性和方法: ```cpp class Shape { public: virtual void draw() = 0; virtual ~Shape() {} }; ``` 然后,我们定义三个实现类,分别表示圆形、矩形和三角形: ```cpp class Circle : public Shape { public: void draw() override { cout << "Draw Circle." << endl; } }; class Rectangle : public Shape { public: void draw() override { cout << "Draw Rectangle." << endl; } }; class Triangle : public Shape { public: void draw() override { cout << "Draw Triangle." << endl; } }; ``` 接下来,我们需要实现桥接模式中的桥接类,它将抽象类和实现类进行桥接。假设我们要支持不同的绘制方式,包括OpenGL和DirectX。我们可以定义一个抽象类DrawAPI,表示绘制的基本属性和方法: ```cpp class DrawAPI { public: virtual void draw() = 0; virtual ~DrawAPI() {} }; ``` 然后,我们定义两个实现类,分别表示OpenGL和DirectX的绘制方式: ```cpp class OpenGLAPI : public DrawAPI { public: void draw() override { cout << "Draw using OpenGL." << endl; } }; class DirectXAPI : public DrawAPI { public: void draw() override { cout << "Draw using DirectX." << endl; } }; ``` 最后,我们需要使用抽象工厂创建图形和绘制方式的组合。我们可以定义一个抽象工厂类AbstractFactory,表示图形和绘制方式的组合: ```cpp class AbstractFactory { public: virtual Shape* createShape() = 0; virtual DrawAPI* createDrawAPI() = 0; virtual ~AbstractFactory() {} }; ``` 然后,我们定义两个具体的工厂类,分别表示OpenGL和DirectX的图形和绘制方式的组合: ```cpp class OpenGLFactory : public AbstractFactory { public: Shape* createShape() override { return new Circle(); } DrawAPI* createDrawAPI() override { return new OpenGLAPI(); } }; class DirectXFactory : public AbstractFactory { public: Shape* createShape() override { return new Rectangle(); } DrawAPI* createDrawAPI() override { return new DirectXAPI(); } }; ``` 最后,我们可以使用这些类来绘制图形。例如,我们可以使用OpenGL和圆形来绘制一个图形: ```cpp AbstractFactory* factory = new OpenGLFactory(); Shape* shape = factory->createShape(); DrawAPI* api = factory->createDrawAPI(); api->draw(); shape->draw(); ``` 输出结果为: ``` Draw using OpenGL. Draw Circle. ``` 这就是桥接模式和抽象工厂C++中的实现。通过使用桥接模式和抽象工厂,我们可以将抽象类和实现类进行解耦,从而实现更加灵活和可扩展的设计。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值