【设计模式】:工厂模式详解(C++)

1.相关概念

  • 设计模式:设计模式(Design Pattern)是一套被反复使用、多数人知晓的、经过分类的、代码设计经验的总结。
  • 使用设计模式的目的:为了代码可重用性、让代码更容易被他人理解、保证代码可靠性。 设计模式使代码编写真正工程化;设计模式是软件工程的基石脉络,如同大厦的结构一样。
  • 耦合:耦合关系是指某两个事物之间如果存在一种相互作用、相互影响的关系,那么这种关系就称"耦合关系"。耦合高是指模快A和模快B之间的关联过高。
  • 开闭原则:对扩展开放,对修改封闭。一个软件应该通过扩展来实现变化,而不是通过修改已有的代码来实现变化的。

2.工厂模式分类

  • 简单工厂模式
  • 工厂方法模式
  • 抽象工厂模式

3.简单工厂模式

  • 描述 : 忍辱其名,此模式很简单,而且使用在业务简单的情况下
    在这里插入图片描述
  • 角色:

1.工厂类角色:本角色含有一定的商业逻辑和判断逻辑,根据客户传的不同参数去实现不同的行为,在C++中往往由一个具体的类实现
2.抽象产品角色:它一般是具体产品继承的父类或者实现的接口。在C++中使用抽象类实现
3.具体的产品角色:工厂类所创建的对象就是此角色的实例。在C++中是由一个具体类实现

  • 问题:使用开闭原则分析简单工厂模式
  • 缺点:扩展性差,需要改变工厂类的代码,违反开闭原则。比如现在工厂中增加了一款车型,只需要增加一个类去继承Car抽象类实现Run方法,在工厂类中添加一个新的匹配项(修改了工厂类的代码,违反了开闭原则)。
  • 优点:一定程度上降低了代码的耦合度。当客户端需要产品对象时,只需要将要求告诉工厂,让工厂帮助生产对象,而不必关心生产产品的具体细节。
  • 代码实现:
/**
 * 简单工厂模式
 */ 
#include <iostream>
#include <string>

using namespace std;

// 定义车的接口(抽象)
class Car
{
    public:
        virtual void Run() = 0;
};
// 具体的宝马类(实现)
class BMWCar :public Car 
{
    public:
        virtual void Run()
        {
            cout << "i am bmw" << endl;
        }
};
// 具体的奥迪类(实现)
class AoDiACar : public Car 
{
    public:
        virtual void Run()
        {
            cout << "i am aodi" << endl;
        }
};

// 生产卡车的类
class Factory 
{
    public:
        // 根据客户端不同需求生产宝马或者奥迪
        // 客户端传参,工厂类利用参数判断生产那个产品
        static Car* ProductCar(string mess)
        {
            if(mess == "宝马"){
                return new BMWCar;
            }else if(mess == "奥迪"){
                return new AoDiACar;
            }else{
                cout << "没有您需要的车型" << endl;
                return nullptr;
            }
        }
};
int main()
{
    // 客户端
    Factory::ProductCar("奥迪")->Run();
    Factory::ProductCar("宝马")->Run();
    Factory::ProductCar("其他")->Run();
    // 释放(C++中没有JVM,堆上的内存需要程序员手动释放,否则会出现内存泄露)
    return 0;
}

2.工厂方法模式

  • 描述:定义一个创建对象的工厂接口,而不是一个工厂类,让子类去决定实例化哪一个对象,将实际工作交给子类。
    在这里插入图片描述
  • 角色:

1.抽象工厂角色:这是工厂方法模式的核心。是具体工厂角色必须实现的接口或者必须继承的父类。在C++中它由抽象类来实现
2.具体的工厂角色:它含有和具体业务逻辑相关的代码,创建对应的具体产品的对象,在C++中使用具体的类来实现
3.抽象的产品角色:它是具体产品继承的父类或者是实现的接口,在C++中使用抽象类实现
4.具体的产品角色:具体工厂角色所创建的对象就是此角色的实例,在C++中使用具体的类来实现

  • 问题:工厂方法模式足以应对我们可能遇到的大部分业务需求。但是当产品种类非常多时会导致过多的具体产品类和具体的工厂类,从而增加系统的负担。
  • 缺点:在增加一个新产品的时候,需要增加一个产品类和工厂类,当产品种类过多,会给系统增加负担,并且每个工厂只生产一种产品,太过单一。
  • 优点:主要是解决简单工厂在扩展时违反开闭原则的缺点。工厂方法模式的扩展性比较好,比如现在新扩展有个具体产品类(大众),只需要在增加一个具体工厂类去实现工厂接口,创建新的产品类对象,不需要修改其他业务代码。更加符合开闭原则,新增一个产品时,只需要增加相应的具体产品类和相应的工厂类即可;符合单一职责原则,每个具体工厂类只负责创建对应的产品即可。
  • 代码实现:
/**
 * 工厂方法模式
 */ 
#include <iostream>
#include <string>

using namespace std;
// 抽象车类
class Car 
{
    public:
        virtual void Run() = 0;
};
// 具体的宝马类(实现)
class BMWCar : public Car
{
    public:
        virtual void Run()
        {
            cout << " i am bmw" << endl;
        }
};
// 具体的奥迪类(实现)
class AoDiCar : public Car
{
    public:
        virtual void Run()
        {
            cout << " i am aodi" << endl;
        }
};
// 抽象工厂类
class CarFactory
{
    public:
        virtual Car* ProductCar() = 0;
};
// 具体生产宝马的工厂(实现)
class BMWFactory : public CarFactory
{
    public:
        virtual Car* ProductCar()
        {
            return new BMWCar;
        }
};
// 具体生产奥迪的工厂(实现)
class AoDiFactory : public CarFactory
{
    public:
        virtual Car* ProductCar()
        {
            return new AoDiCar;
        }
};

int main()
{
    // 客户端
    CarFactory* carA = new AoDiFactory;
    carA->ProductCar()->Run();
    CarFactory* carB = new BMWFactory;
    carB->ProductCar()->Run();

    // 释放堆上的内存
    return 0;
}

3.抽象工厂模式

  • 描述:给客户端提供一个接口,可以创建多个产品族中的产品对象。如果工厂的产品来自多个等级结构,则属于抽象工厂模式。
    在这里插入图片描述
  • 角色:

1.抽象工厂角色:这是抽象工厂的核心,是具体工厂角色必须实现的接口或者必须继承的父类。在C++中使用抽象类实现
2.具体工厂角色:它含有和具体业务逻辑相关的代码,创建对应的具体产品的对象,在C++中使用具体的类实现
3.抽象产品角色:它是具体产品继承的父类或者是实现的接口,在C++中使用抽象类实现
4.具体产品角色:具体工厂角色所创建的对象就是此角色的实例,在C++中使用具体的类实现

  • 代码实现:
/**
 * 抽象工厂模式
 */ 
#include <iostream>
#include <string>

using namespace std;

// 卡车抽象类
class Trunk_A
{
    public:
        virtual void Run() = 0;
};
// 轿车抽象类
class Sedan_A
{
    public:
        virtual void Run() = 0;
};
// 具体的宝马卡车产品类
class BmwTrunk : public Trunk_A 
{
    public:
        virtual void Run()
        {
            cout << "宝马卡车" << endl;
        }
};
// 具体的宝马轿车产品类
class BmwSedan : public Sedan_A 
{
    public:
        virtual void Run()
        {
            cout << "宝马轿车" << endl;
        }
};
// 具体的奥迪卡车产品类
class AodiTrunk : public Trunk_A 
{
    public:
        virtual void Run()
        {
            cout << "奥迪卡车" << endl;
        }
};
// 具体的奥迪轿车产品类
class AodiSedan : public Sedan_A 
{
    public:
        virtual void Run()
        {
            cout << "奥迪轿车" << endl;
        }
};

// 抽象工厂类
class CarFactory
{
    public:
        virtual Trunk_A* productTrunk() = 0;
        virtual Sedan_A* productSedan() = 0;
};

// 宝马工厂类(一个工厂是生产一个产品族的工厂而不是生产单一的产品)
class BmwFactory : public CarFactory 
{
    public:
        virtual Trunk_A* productTrunk()
        {
            return new BmwTrunk;
        }
        virtual Sedan_A* productSedan()
        {
            return new BmwSedan;
        }
};
// 奥迪工厂类
class AodiFactory : public CarFactory 
{
    public:
        virtual Trunk_A* productTrunk()
        {
            return new AodiTrunk;
        }
        virtual Sedan_A* productSedan()
        {
            return new AodiSedan;
        }
};

int main()
{
    // 客户端
    CarFactory* bm = new BmwFactory();
    bm->productTrunk()->Run();
    bm->productSedan()->Run();
    return 0;
}

5.总结

  • 无论简单工厂模式、工厂方法模式、还是抽象工厂模式,它们都属于工厂模式,在形式和特点上也是极为相似的,它们的最终目的都是为了解耦。
  • 使用工厂模式时,只需要关心降低耦合度的目的是否达到了,其他的则不必关心。
发布了221 篇原创文章 · 获赞 200 · 访问量 19万+

猜你喜欢

转载自blog.csdn.net/hansionz/article/details/89556508