设计模式之简单工厂模式、工厂模式、抽象工厂模式

        简单工厂模式、工厂模式、抽象工厂模式,为常见且常用的三种设计模式,下面我将这三种设计模式放在一起,讲解每种设置模式的概念、特点、使用场景(使用Qt实现),以及三种设计模式的区别。

目录

一、简单工厂模式

1.概念

2.代码示例

二、工厂模式

1.概念

2.代码示例

三、抽象工厂模式

1.概念

2.代码示例

四、总结


一、简单工厂模式

1.概念

        简单工厂模式(Simple Factory Pattern)是一种创建型设计模式,它提供了一个单一的工厂类,用于创建不同类型的对象,根据客户端的需求来决定创建哪种具体类型的对象。简单工厂模式将对象的创建过程封装在一个工厂类中,客户端只需要向工厂类请求需要的对象,而无需了解对象的具体创建细节。

        以下是简单工厂模式的核心组成部分和使用方法:

        产品类(Product):产品是需要被创建的对象,通常包含多个属性和方法。

        工厂类(Factory):工厂类包含一个或多个创建产品对象的方法,根据客户端的请求来选择并创建具体的产品对象。

        使用简单工厂模式的步骤如下:

        (1)创建产品类,定义产品的属性和方法。

        (2)创建工厂类,包含一个或多个方法,用于创建不同类型的产品对象。

        (3)在客户端中,通过工厂类来创建产品对象,传递一个参数或条件给工厂类,以指示需要创建哪种具体类型的产品对象。

        (4)工厂类根据客户端的请求,调用相应的创建方法来实例化产品对象,并将其返回给客户端。

        简单工厂模式的使用场景包括:

  • 对象的创建过程相对简单:当对象的创建过程不太复杂,只涉及一些简单的初始化操作时,简单工厂模式是一个适合的选择。

  • 对象的种类不太多:当需要创建的对象种类不是特别多,且不经常发生变化时,可以考虑使用简单工厂模式。

  • 客户端不需要关心对象的创建细节:简单工厂模式将对象的创建过程封装在工厂类中,客户端只需调用工厂类的方法来创建对象,无需关心对象的具体创建过程。

  • 对象的创建过程需要统一管理:如果需要对对象的创建过程进行集中管理和维护,简单工厂模式可以提供一个统一的入口点。

        简单工厂模式的主要优点是隐藏了对象创建的复杂性,使客户端代码更加简洁和可维护。然而,它的扩展性相对较差,因为每次新增类型的对象都需要修改工厂类。如果系统需要支持多种不同类型的对象,并且这些对象的创建过程较为复杂,可以考虑使用工厂方法模式或抽象工厂模式,这两种模式更具扩展性。

2.代码示例

// Operation.h

#ifndef OPERATION_H
#define OPERATION_H
#include <QString>

class Operation
{
public:
    Operation();
    double getNumberA();
    double getNumberB();
    void setNumberA(double number);
    void setNumberB(double number);

    virtual double getResult() = 0;

private:
    double m_numberA;
    double m_numberB;
};

class OperationAdd : public Operation
{
public:
    double getResult();
};

class OperationSub : public Operation
{
public:
    double getResult();
};

class OperationMul : public Operation
{
public:
    double getResult();
};

class OperationDiv : public Operation
{
public:
    double getResult();
};

class OperationFactory
{
public:
    static Operation* creatorOperate(QString operate);
};

#endif // OPERATION_H
// Operation.cpp

#include "operation.h"

Operation::Operation()
{

}

double Operation::getNumberA()
{
    return m_numberA;
}

double Operation::getNumberB()
{
    return m_numberB;
}

void Operation::setNumberA(double number)
{
    m_numberA = number;
}

void Operation::setNumberB(double number)
{
    m_numberB = number;
}

double OperationAdd::getResult()
{
    double result = 0;
    result = getNumberA() + getNumberB();
    return result;
}

double OperationSub::getResult()
{
    double result = 0;
    result = getNumberA() - getNumberB();
    return result;
}

double OperationMul::getResult()
{
    double result = 0;
    result = getNumberA() * getNumberB();
    return result;
}

double OperationDiv::getResult()
{
    double result = 0;
    if(getNumberB() == 0)
        return 0;
    result = getNumberA() / getNumberB();
    return result;
}

Operation* OperationFactory::creatorOperate(QString operate)
{
    Operation* oper = nullptr;
    if(operate == "+")
    {
        OperationAdd* operAdd = new OperationAdd();
        oper = operAdd;
    }
    else if(operate == "-")
    {
        OperationSub* operSub = new OperationSub();
        oper = operSub;
    }
    else if(operate == "*")
    {
        OperationMul* operMul = new OperationMul();
        oper = operMul;
    }
    else if(operate == "/")
    {
        OperationDiv* operDiv = new OperationDiv();
        oper = operDiv;
    }
    else
    {
        oper = new OperationAdd();
    }
    return oper;
}
// main.cpp

#include <QCoreApplication>
#include <iostream>
#include "operation.h"

using namespace std;

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    Operation* oper = nullptr;
    double numberA;
    double numberB;
    char operation;
    cout << "Please input numberA: ";
    cin >> numberA;
    cout << "Please input operator symbol: ";
    cin >> operation;
    cout << "Please input numberB: " ;
    cin >> numberB;
    oper = OperationFactory::creatorOperate(QString(operation));
    oper->setNumberA(numberA);
    oper->setNumberB(numberB);
    double result = oper->getResult();
    cout << result;

    return a.exec();
}

        该示例为计算器,输入数值A,输入计算符号+、 -、 *、 /,输入数值B,在OperationFactory工厂中,创建执行相应算法的对象,然后进行数据赋值,计算得到结果并输出。

3.代码分析

        工厂类中包含了必要的逻辑判断,根据客户端的选择条件,动态实例化相关的类,客户端摆脱了与具体产品的依赖。

        增加新产品时,除了需要编写新产品相关业务代码,还需扩展原有工厂创建产品处的逻辑代码。

二、工厂模式

1.概念

        工厂方法模式(Factory Method Pattern)是一种创建型设计模式,它提供了一种将对象的创建过程延迟到子类的方式。工厂方法模式将对象的实例化委托给子类,每个具体子类都负责创建特定类型的对象。这使得客户端代码与具体对象的创建过程解耦,同时支持了灵活的对象创建和扩展。

        以下是工厂方法模式的核心组成部分和使用方法:

        产品类(Product):产品是需要被创建的对象,通常包含多个属性和方法。

        抽象工厂类(Factory):抽象工厂类定义了一个抽象的工厂方法,该方法返回一个抽象产品类型。工厂类可以包含多个工厂方法,每个方法负责创建不同类型的产品。

        具体工厂类(Concrete Factory):具体工厂类实现了抽象工厂类中定义的工厂方法,负责具体的产品创建。每个具体工厂类通常对应一种具体产品类型。

        使用工厂方法模式的步骤如下

        (1)创建产品类,定义产品的属性和方法。

        (2)创建抽象工厂类,定义一个或多个抽象的工厂方法,用于创建不同类型的产品。

        (3)创建具体工厂类,实现抽象工厂类中定义的工厂方法,负责创建具体的产品对象。

        (4)在客户端中,使用具体工厂类来创建产品对象,无需关心具体产品的创建过程。客户端只需调用工厂方法来获取产品对象。

        工厂方法模式的使用场景包括

  • 需要创建一组相关但不同类型的对象:工厂方法模式适用于创建一组相关的对象,每个对象具有共同的接口但有不同的实现。

  • 客户端需要与具体对象的创建过程解耦:工厂方法模式将对象的创建委托给具体工厂类,客户端只需与抽象工厂类和产品类交互,无需了解具体对象的创建过程。

  • 支持扩展:工厂方法模式支持添加新的产品类型和具体工厂类,而无需修改现有的代码,从而实现系统的可扩展性。

  • 实现多态性:工厂方法模式促使客户端使用多态性来处理不同类型的产品对象,从而增强了代码的灵活性和可维护性。

  • 复杂对象的构建:当对象的构建过程比较复杂,包括多个步骤或需要特定的配置时,工厂方法模式可以更好地管理这些复杂性。

        工厂方法模式的主要优点是支持灵活的对象创建和扩展,使系统更具可维护性和可扩展性。它适用于需要创建一组相关对象,同时需要降低客户端与具体对象创建细节之间的耦合度的情况。不过,工厂方法模式可能会引入较多的类和接口,因此在设计时需要权衡和考虑是否真正需要这种分离。

2.代码示例

// operationfactory.h

#ifndef OPERATIONFACTORY_H
#define OPERATIONFACTORY_H

class Operation
{
public:
    Operation();
    double getNumberA();
    double getNumberB();
    void setNumberA(double number);
    void setNumberB(double number);

    virtual double getResult() = 0;

private:
    double m_numberA;
    double m_numberB;
};

class OperationAdd : public Operation
{
public:
    double getResult();
};

class OperationSub : public Operation
{
public:
    double getResult();
};

class OperationMul : public Operation
{
public:
    double getResult();
};

class OperationDiv : public Operation
{
public:
    double getResult();
};

class OperationFactory
{
public:
    virtual Operation* createOperation() = 0;
};

class OperationAddFactory : public OperationFactory
{
public:
    Operation* createOperation();
};

class OperationSubFactory : public OperationFactory
{
public:
    Operation* createOperation();
};

class OperationMulFactory : public OperationFactory
{
public:
    Operation* createOperation();
};

class OperationDivFactory : public OperationFactory
{
public:
    Operation* createOperation();
};

#endif // OPERATIONFACTORY_H
// operationfactory.cpp

#include "operationfactory.h"

Operation::Operation()
{

}

double Operation::getNumberA()
{
    return m_numberA;
}

double Operation::getNumberB()
{
    return m_numberB;
}

void Operation::setNumberA(double number)
{
    m_numberA = number;
}

void Operation::setNumberB(double number)
{
    m_numberB = number;
}

double OperationAdd::getResult()
{
    double result = 0;
    result = getNumberA() + getNumberB();
    return result;
}

double OperationSub::getResult()
{
    double result = 0;
    result = getNumberA() - getNumberB();
    return result;
}

double OperationMul::getResult()
{
    double result = 0;
    result = getNumberA() * getNumberB();
    return result;
}

double OperationDiv::getResult()
{
    double result = 0;
    if(getNumberB() == 0)
        return 0;
    result = getNumberA() / getNumberB();
    return result;
}

Operation* OperationAddFactory::createOperation()
{
    return new OperationAdd();
}

Operation* OperationSubFactory::createOperation()
{
    return new OperationSub();
}

Operation* OperationMulFactory::createOperation()
{
    return new OperationMul();
}

Operation* OperationDivFactory::createOperation()
{
    return new OperationDiv();
}
// main.cpp

#include <QCoreApplication>
#include <iostream>

#include "operationfactory.h"

using namespace std;

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    double numberA;
    double numberB;
    char operationC;
    QString operationStr;
    cout << "Please input numberA: ";
    cin >> numberA;
    cout << "Please input operator symbol: ";
    cin >> operationC;
    operationStr = QString(operationC);
    cout << "Please input numberB: " ;
    cin >> numberB;

    OperationFactory *factory = nullptr;

    if(operationStr == "+")
    {
        factory = new OperationAddFactory();
    }
    else if(operationStr == "-")
    {
        factory = new OperationSubFactory();
    }
    else if(operationStr == "*")
    {
        factory = new OperationMulFactory();
    }
    else if(operationStr == "/")
    {
        factory = new OperationDivFactory();
    }
    else
    {
        cout << "Input symbol error!";
    }

    Operation *operation = factory->createOperation();
    operation->setNumberA(numberA);
    operation->setNumberB(numberB);
    double result = operation->getResult();
    cout << result;

    return a.exec();
}

3.代码分析

        把简单工厂的创建产品逻辑判断,移动到客户端代码中,使产品的实例化延迟到其子类。

三、抽象工厂模式

1.概念

        抽象工厂模式(Abstract Factory Pattern)是一种创建型设计模式,它提供了一种方式来创建一组相关或依赖对象,而无需指定它们的具体类。抽象工厂模式基于工厂方法模式,不仅创建单一对象,而是创建一组对象,这组对象通常具有某种关联或共同的主题。

        以下是抽象工厂模式的核心组成部分和使用方法:

        抽象工厂接口(Abstract Factory):抽象工厂接口定义了一组用于创建相关对象的抽象方法,每个方法负责创建一种对象。通常,一个抽象工厂接口对应一个产品族,其中的方法对应不同类型的产品。

        具体工厂类(Concrete Factory):具体工厂类实现了抽象工厂接口,负责创建一组相关的对象。每个具体工厂类通常对应一种产品族,它实现了抽象工厂接口中的方法,从而创建具体的产品对象。

        抽象产品接口(Abstract Product):抽象产品接口定义了一组产品的通用接口,包括产品的属性和方法。

        具体产品类(Concrete Product):具体产品类实现了抽象产品接口,负责实现具体产品的属性和方法。

        使用抽象工厂模式的步骤如下:

        (1)创建抽象产品接口,定义产品的通用接口,包括属性和方法。

        (2)创建抽象工厂接口,定义一组抽象方法,每个方法用于创建不同类型的产品。

        (3)创建具体产品类,实现抽象产品接口,定义具体产品的属性和方法。

        (4)创建具体工厂类,实现抽象工厂接口中的方法,负责创建一组相关的产品对象。

        (5)在客户端中,选择合适的具体工厂类,然后使用工厂方法来创建一组相关的产品对象。

        抽象工厂模式的使用场景包括:

  • 需要创建一组相关的对象:当系统需要一组相关或依赖的对象,而这些对象通常一起使用或一起构建时,抽象工厂模式是一个适合的选择。

  • 客户端需要与具体对象的创建过程解耦:抽象工厂模式将对象的创建委托给具体工厂类,客户端只需与抽象工厂接口和抽象产品接口交互,无需了解具体对象的创建细节。

  • 支持产品族扩展:抽象工厂模式支持添加新的产品族(一组相关的产品),而不需要修改现有的代码,从而实现系统的可扩展性。

  • 强调一致性:抽象工厂模式强调创建一组产品的一致性,确保这组产品之间的关联和兼容性。

  • 复杂对象的构建:当对象的构建过程较为复杂,包括多个步骤或需要特定的配置时,抽象工厂模式可以更好地管理这些复杂性。

        抽象工厂模式有助于提高系统的灵活性和可维护性,同时支持一组相关对象的创建和管理。它适用于需要创建一组相关产品的情况,以及需要将对象的创建过程与客户端解耦的情况。不过,抽象工厂模式可能会引入多个接口和类,因此在设计时需要仔细权衡和考虑是否真正需要这种分离。

2.代码示例

// abstractfactory.h

#ifndef ABSTRACTFACTORY_H
#define ABSTRACTFACTORY_H

#include <QString>

//用户表
class User
{
public:
    int getId();
    void setId(int id);
    QString getName();
    void serName(QString name);

private:
    int m_id;
    QString m_name;
};

class IUser
{
public:
    virtual void Insert(User* user) = 0;
    virtual User* GetUser(int id) = 0;
};

class SqlserverUser : public IUser
{
public:
    void Insert(User *user);
    User* GetUser(int id);
};

class AccessUser : public IUser
{
public:
    void Insert(User *user);
    User* GetUser(int id);
};


//部门表
class Department
{
public:
    int getId();
    void setId(int id);
    QString getName();
    void setName(QString name);

private:
    int m_id;
    QString m_deptName;
};

class IDepartment
{
public:
    virtual void Insert(Department* department) = 0;
    virtual Department* GetDepartment(int id) = 0;
};

class SqlserverDepartment : public IDepartment
{
public:
    void Insert(Department* department);
    Department* GetDepartment(int id);
};

class AccessDepartment : public IDepartment
{
public:
    void Insert(Department* department);
    Department* GetDepartment(int id);
};

//工厂
class IFactory
{
public:
    virtual IUser* CreateUser() = 0;
    virtual IDepartment* CreateDepartment() = 0;
};

class SqlserverFactory : public IFactory
{
public:
    IUser* CreateUser();
    IDepartment* CreateDepartment();
};

class AccessFactory : public IFactory
{
public:
    IUser* CreateUser();
    IDepartment* CreateDepartment();
};


#endif // ABSTRACTFACTORY_H
// abstractfactory.cpp

#include "abstractfactory.h"

#include <QDebug>

int User::getId()
{
    return m_id;
}

void User::setId(int id)
{
    m_id = id;
}

QString User::getName()
{
    return m_name;
}

void User::serName(QString name)
{
    m_name = name;
}

void SqlserverUser::Insert(User *user)
{
    qDebug()<<"在SQL Server中给User表增加一条记录";
}

User* SqlserverUser::GetUser(int id)
{
    qDebug()<<"在SQL Server中给根据ID得到User表一条记录";
    return NULL;
}

void AccessUser::Insert(User *user)
{
    qDebug()<<"在Access中给User表增加一条记录";
}

User* AccessUser::GetUser(int id)
{
    qDebug()<<"在Access中给根据ID得到User表一条记录";
    return NULL;
}

int Department::getId()
{
    return m_id;
}

void Department::setId(int id)
{
    m_id = id;
}

QString Department::getName()
{
    return m_deptName;
}

void Department::setName(QString name)
{
    m_deptName = name;
}

void SqlserverDepartment::Insert(Department *department)
{
    qDebug()<<"在SQL Server中给Department表增加一条记录";
}

Department * SqlserverDepartment::GetDepartment(int id)
{
    qDebug()<<"在SQL Server中根据ID得到Department表一条记录";
    return NULL;
}

void AccessDepartment::Insert(Department *department)
{
    qDebug()<<"在Access中给Department表增加一条记录";
}

Department * AccessDepartment::GetDepartment(int id)
{
    qDebug()<<"在Access中根据ID得到Department表一条记录";
    return NULL;
}

IUser* SqlserverFactory::CreateUser()
{
    return new SqlserverUser();
}

IDepartment* SqlserverFactory::CreateDepartment()
{
    return new SqlserverDepartment();
}

IUser* AccessFactory::CreateUser()
{
    return new AccessUser();
}

IDepartment* AccessFactory::CreateDepartment()
{
    return new AccessDepartment();
}
// main.cpp

#include <QCoreApplication>

#include "abstractfactory.h"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    User *user = new User();
    Department *dept = new Department();

//    IFactory *factory = new SqlserverFactory();
    IFactory *factory = new AccessFactory();

    IUser *iu = factory->CreateUser();

    iu->Insert(user);
    iu->GetUser(1);

    IDepartment *id = factory->CreateDepartment();
    id->Insert(dept);
    id->GetDepartment(1);

    return a.exec();
}

3.代码分析

        抽象工厂模式,让创建实例的过程与客户端分离,客户端通过抽象接口操纵实例。

四、总结

        简单工厂模式、工厂模式和抽象工厂模式是三种与对象创建相关的设计模式,它们有不同的用途和特点。以下是它们之间的主要区别:

  1. 简单工厂模式(Simple Factory Pattern)

    • 定义:简单工厂模式是一种创建型模式,它通过一个工厂类来创建对象,根据传递给工厂的参数或条件来决定创建哪种具体类型的对象。

    • 特点

      • 有一个单一的工厂类,负责对象的创建。
      • 客户端通过工厂类来创建对象,无需了解对象的具体创建过程。
      • 工厂类通常包括一个或多个创建对象的方法。
    • 用法:简单工厂模式通常用于隐藏对象的创建细节,使客户端代码与具体对象的创建解耦。但它的扩展性相对较差,因为每次新增类型的对象都需要修改工厂类。

  2. 工厂模式(Factory Method Pattern)

    • 定义:工厂模式是一种创建型模式,它定义一个接口,但将对象的实际创建延迟到子类中,从而允许不同的子类决定创建哪种具体类型的对象。

    • 特点

      • 包括一个抽象工厂接口,由具体的子类来实现。
      • 每个具体的子类负责创建一种具体类型的对象。
      • 客户端通过调用工厂方法来创建对象,无需关心对象的具体类型。
    • 用法:工厂模式允许在运行时选择不同的工厂子类来创建对象,从而支持扩展,但仍然需要修改工厂类结构以添加新的对象类型。

  3. 抽象工厂模式(Abstract Factory Pattern)

    • 定义:抽象工厂模式是一种创建型模式,它提供一个接口,用于创建一组相关或依赖对象,而不指定其具体类。它是工厂方法模式的扩展,用于创建一组相关的对象。

    • 特点

      • 包括一个抽象工厂接口,定义一组相关对象的创建方法。
      • 每个具体的工厂子类实现了抽象工厂接口,负责创建一组相关的对象。
      • 客户端通过工厂接口来创建一组相关的对象,无需关心对象的具体类。
    • 用法:抽象工厂模式适用于创建一组相关的对象,例如不同操作系统的界面组件(按钮、文本框等)。它允许客户端使用不同的工厂实现来创建对象,从而实现整体的替换。

        总之,简单工厂模式主要用于隐藏对象的创建细节,工厂模式允许不同的子类决定创建哪种对象,而抽象工厂模式用于创建一组相关的对象,并且提供了更高层次的抽象,使客户端能够创建整组对象而不必关心具体类的选择。选择使用哪种模式取决于你的具体需求和设计目标。

五、源码地址

https://github.com/Study-Young/DesignPatterns

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值