简单工厂模式、工厂模式、抽象工厂模式比较

作者: 良知犹存

前言:

设计模式已经经历了很长一段时间的发展,它们提供了软件开发过程中面临的一般问题的最佳解决方案。学习这些模式有助于经验不足的开发人员通过一种简单快捷的方式来学习软件设计。

一般们会说设计模式一共有23种,总体来说设计模式分为三大类:

创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。

结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。

行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

今天主要是分析 简单工厂模式、工厂模式和抽象工厂模式的区别,所以这里就简单介绍一下设计模式的概念。

作者:良知犹存

转载授权以及围观:欢迎添加微信公众号:羽林君


网上的很多资料都是在阐述着:工厂模式的好处就是解耦。相信大家对解耦这个词也不陌生,那解耦究竟有什么好处呢?

  • 1.为了提高内聚(Cohesion)和松耦合(Coupling),们经常会抽象出一些类的公共接口以形成抽象基类或者接口。这样们可以通过声明一个指向基类的指针来指向实际的子类实现,达到了多态的目的。这里很容易出现的一个问题 n 多的子类继承自抽象基类,们不得不在每次要用到子类的地方就编写诸如 new ×××;的代码。这里带来两个问题:

    客户程序员必须知道实际子类的名称(当系统复杂后,命名将是一个很不好处理的问题,为了处理可能的名字冲突,有的命名可能并不是具有很好的可读性和可记忆性,就姑且不论不同程序员千奇百怪的个人偏好了)。程序的扩展性和维护变得越来越困难。

  • 2.还有一种情况就是在父类中并不知道具体要实例化哪一个具体的子类。这里的意思为:假设们在类 A 中要使用到类 B,B 是一个抽象父类,在 A 中并不知道具体要实例化那一个 B 的子类,但是在类 A 的子类 D 中是可以知道的。在 A 中们没有办法直接使用类似于 new ×××的语句,因为根本就不知道×××是什么。

以上两个问题也就引出了工厂模式的两个最重要的功能:
定义创建对象的接口,封装了对象的创建;
使得具体化类的工作延迟到了子类中。

对于工厂模式,为了使其能更好的解决多种情况的问题,将其分为三类:简单工厂模式(Simple Factory),工厂方法模式(Factory Method),抽象工厂模式(Abstract Factory)
GOAT
经常使用会遇到一些设计模式的使用,但是很少去细究里面的区别,这把就让来大家分享一下,认知中的这三种工厂模式。

简单工厂模式 {简单工厂模式}

们把被创建的对象称为"产品”,把创建产品的对象称为"工厂”。如果要创建的产品不多,只要一个工厂类就可以完成,这种模式叫"简单工厂模式”。

结构定义: {结构定义:}

是由一个工厂对象决定创建出哪一种产品类的实例。
简单工厂模式中包含的角色及其相应的职责如下:

工厂角色(Creator):这是简单工厂模式的核心,由它负责创建所有的类的内部逻辑。当然工厂类必须能够被外界调用,创建所需要的产品对象。

抽象(Product)产品角色:简单工厂模式所创建的所有对象的父类,注意,这里的父类可以是接口也可以是抽象类,它负责描述所有实例所共有的公共接口。

具体产品(Concrete Product)角色:简单工厂所创建的具体实例对象,这些具体的产品往往都拥有共同的父类。

定义一个创建产品对象的工厂接口,将产品对象的实际创建工作推迟到具体子工厂类当中。这满足创建型模式中所要求的"创建与使用相分离"的特点。

结构图如下 {结构图如下}

范例如下: {范例如下:}

C++实现 {c实现}

include <iostream>
using namespace std;

enum Product_Type
{
    Product1_,
    Product2_,
};
class AbstractProduct //抽象(Product)产品角色
{
public:
    AbstractProduct() {}
    virtual ~AbstractProduct() {}
    virtual void Show() = 0;
};

class Product1 : public AbstractProduct //具体产品(Concrete Product)角色
{
private:
    /* data */
public:
    Product1(/* args */);
    ~Product1();
    void Show()
    {
        std::cout<< "product1"<<std::endl;
    }
};

Product1::Product1()
{
}

Product1::~Product1()
{
}
class Product2 : public AbstractProduct //具体产品(Concrete Product)角色
{
private:
    /* data */
public:
    void Show()
    {
        std::cout<< "product2"<<std::endl;
    }
};
class Factory  //工厂角色(Creator)
{
public:
    AbstractProduct *CreateProduct(Product_Type  type) 
    {
        switch (type)
        {
        case Product1_/* constant-expression */:
            /* code */
            return new Product1();
        case Product2_:
            return new Product2();
        default:
            return NULL;
        }
    }
};
int main(int argc, char **argv)
{
    Factory *new_factory = new Factory();
    AbstractProduct *new_product1 = new_factory->CreateProduct(Product1_);
    new_product1->Show();


    AbstractProduct *new_product2 = new_factory->CreateProduct(Product2_);
    new_product2->Show();

    delete new_factory,new_product1,new_product2;
    new_factory = NULL;    
    new_product1 = NULL;    
    new_product2 = NULL;    
}

python实现 {python实现}

!/usr/bin/python3

from enum import Enum

ProducType = Enum(('ProducType'),('product1_','product2_','product_3'))

class AbstractProduct(object):
    def show(self):
        pass
class Product1(AbstractProduct):
    def show(self):
        print("Product1")

class Product2(AbstractProduct):
    def show(self):
        print("Product2")

class AbcFactory(object):
    def crete_product(self):
        pass

class Factory(AbcFactory):
    def crete_product(self,type):
        product_type = {
            ProducType.product1_ : Product1(),
            ProducType.product2_ : Product2()
        }
        return product_type.get(type,None)
if __name__ == "__main__":
    new_factory = Factory()

    product1 = new_factory.crete_product(ProducType.product1_)
    product1.show()

    product2 = new_factory.crete_product(ProducType.product2_)
    product2.show()



们只需要调用不同的成员函数,工厂就帮们实例化出想要的对象,利用上转型对象,返回父类的方式实现了结果。可以发现简单工厂模式代码简单,但不符合OCP(面向对象设计的基本原则之一 OCP(开闭原则):一个软件的实体应当对扩展开放,对修改关闭)。

总结 : {总结-}

1、简单工厂模式最大的优点在于工厂类中可以判断客户的的选择来动态实例化相关的类,对于客户端来说,去除了具体产品的依赖。

2、缺点就是:很明显工厂类集中了对所有实例创建的逻辑,如果们要新增子类或者改变方法的话,就得每次都修改工厂类里面的代码,工厂类中的代码就会十分臃肿,这就等于说们不进开放了扩展,还开放了修改,这样就违反了开放-封闭原则。

你可能在不知不觉中已经用到过这种模式了,但简单工厂模式并不属于23种设计模式之一,下面介绍他的改进版本:工厂方法模式。

工厂模式 {工厂模式}

工厂方法模式是一种创建型设计模式, 其在父类中提供一个创建对象的方法, 允许子类决定实例化对象的类型。

工厂方法模式的结构组成: {工厂方法模式的结构组成:}

抽象工厂类厂(AbstractFactory):工厂方法模式的核心类,提供创建具体产品的接口,由具体工厂类实现。

具体工厂类(Producer):继承于抽象工厂,实现创建对应具体产品对象的方式。

抽象产品类(Factory):它是具体产品继承的父类(基类)。

具体产品类(Factory1):具体工厂所创建的对象,就是此类。

C++实现 {c实现-1}

include <iostream>
using namespace std;
class AbstractProduct
{
public:
    AbstractProduct() {}
    virtual ~AbstractProduct() {}
    virtual void Show() = 0;
};

class Product1 : public AbstractProduct
{
private:
    /* data */
public:
    Product1(/* args */);
    ~Product1();
    void Show()
    {
        std::cout<< "product1"<<std::endl;
    }
};

Product1::Product1(/* args */)
{
}

Product1::~Product1()
{
}
class Product2 : public AbstractProduct
{
private:
    /* data */
public:
    void Show()
    {
        std::cout<< "product2"<<std::endl;
    }
};
class Factory
{
public:
    virtual ~Factory(){};
    virtual AbstractProduct *CreateProduct() = 0;
};
class Factory1 : Factory
{
public:
    AbstractProduct * CreateProduct(void)
    {
        return new Product1();
    }

};
class Factory2 :Factory
{
public:
    AbstractProduct * CreateProduct(void)
    {
        return new Product2();
    } 
};
int main(int argc, char **argv)
{
    Factory1 *new_factory = new Factory1();
    AbstractProduct *new_product1 = new_factory->CreateProduct();
    new_product1->Show();
    delete new_factory;
    new_factory = NULL;

    Factory2 * new_factory2 = new Factory2();
    AbstractProduct *new_product2 = new_factory2->CreateProduct();
    new_product2->Show();
    delete new_factory2;
    new_factory2 = NULL;    
}

python实现 {python实现-1}

!/usr/bin/python3


class AbstractProduct(object):
    def show(self):
        pass
class Product1(AbstractProduct):
    def show(self):
        print("Product1")

class Product2(AbstractProduct):
    def show(self):
        print("Product2")

class Factory(object):
    def create_product(self):
        pass
class Factory1(Factory):
    def create_product(self):
        return Product1()

class Factory2(Factory):
    def create_product(self):
        return Product2()

if __name__ == "__main__":
    new_product1 = Factory1().create_product()
    new_product1.show()
    new_product2 = Factory2().create_product()
    new_product2.show()

工厂方法模式优缺点 {工厂方法模式优缺点}

  • 1.你可以避免创建者和具体产品之间的紧密耦合。

  • 2.单一职责原则。 你可以将产品创建代码放在程序的单一位置, 从而使得代码更容易维护。

  • 3.开闭原则。 无需更改现有客户端代码, 你就可以在程序中引入新的产品类型。

  • 4.应用工厂方法模式需要引入许多新的子类, 代码可能会因此变得更复杂。最好的情况是将该模式引入创建者类的现有层次结构中。

抽象工厂模式 {抽象工厂模式}

抽象工厂模式是一种创建型设计模式, 它能创建一系列相关的对象, 而无需指定其具体类。是更多一重的工厂模式中。

结构定义(类似工厂模式): {结构定义(类似工厂模式):}

抽象工厂类厂(AbstractFactory):工厂方法模式的核心类,提供创建具体产品的接口,由具体工厂类实现。

具体工厂类(Producer):继承于抽象工厂,实现创建对应具体产品对象的方式。

抽象产品类(Factory):它是具体产品继承的父类(基类)。

具体产品类(Factory1):具体工厂所创建的对象,就是此类。

结构图如下 {结构图如下-1}

C++实现 {c实现-2}

include <iostream>
using namespace std;
class AbstractProductA
{
public:
    AbstractProductA() {}
    virtual ~AbstractProductA() {}
    virtual void Show() = 0;
    virtual void Disp() = 0;
};

class ProductA1 : public AbstractProductA
{
private:
    /* data */
public:
    ProductA1(){}
    ~ProductA1(){}
    void Show()
    {
        std::cout<< "productA1 show"<<std::endl;
    }
    void Disp()
    {
        std::cout<< "productA1 Disp"<<std::endl;
    }
};
class ProductA2: public AbstractProductA
{
private:
    /* data */
public:
    ProductA2(){}
    ~ProductA2(){}
    void Show()
    {
        std::cout<< "productA2 show"<<std::endl;
    }
    void Disp()
    {
        std::cout<< "productA2 Disp"<<std::endl;
    }
};
class AbstractProductB
{
public:
    AbstractProductB() {}
    virtual ~AbstractProductB() {}
    virtual void Show() = 0;
    virtual void Disp() = 0;
};

class ProductB1 : public AbstractProductB
{
public:
    void Show()
    {
        std::cout<< "productB2 show"<<std::endl;
    }
    void Disp()
    {
        std::cout<< "productB2 Disp"<<std::endl;
    }
};
class Factory
{
public:
    virtual AbstractProductA *CreateProductA(void) = 0;

    virtual AbstractProductB *CreateProductB(void) = 0;
};
class Factory1 :Factory
{
public:
    AbstractProductA * CreateProductA(void)
    {
        return new ProductA1();
    }
    AbstractProductB * CreateProductB(void)
    {
        return new ProductB1();
    } 
};
class Factory2:Factory
{
public:
    AbstractProductA * CreateProductA(void)
    {
        return new ProductA2();
    }
    AbstractProductB * CreateProductB(void)
    {
        return NULL;
    } 
};

int main(int argc, char **argv)
{
    Factory2 *new_factory2 = new Factory2();
    AbstractProductA *new_productA2 = new_factory2->CreateProductA();
    new_productA2->Show();

    Factory1 *new_factory1 = new Factory1();
    AbstractProductB *new_productB1 = new_factory1->CreateProductB();
    new_productB1->Show();
}

python 实现 {python-实现}

!/usr/bin/python3


class AbstractProductA(object):
    def show(self):
        pass
    def disp(self):
        pass

class ProductA1(AbstractProductA):
    def show(self):
        print("ProductA1 show")
    def disp(self):
        print("productA1 disp")
class ProductA2(AbstractProductA):
    def show(self):
        print("ProductA2 show")
    def disp(self):
        print("productA2 disp")


class AbstractProductB(object):
    def show(self):
        pass

    def disp(self):
        pass
class ProductB1(AbstractProductB):
    def show(self):
        print("ProductB1 show")
    def disp(self):
        print("productB1 disp")

class ProductB2(AbstractProductB):
    def show(self):
        print("ProductB2 show")
    def disp(self):
        print("productB2 disp")

class Factory(object):
    def crete_product1(self):
        pass
    def crete_product2(self):
        pass

class FactoryA(object):
    def crete_product1(self):
        return ProductA1()

    def crete_product2(self):
        return ProductA2()

class FactoryB(object):
    def crete_product1(self):
        return ProductB1()

    def crete_product2(self):
        return ProductB2()

if __name__ == "__main__":
    new_factory = FactoryA()
    new_product1 = new_factory.crete_product1()
    new_product1.show()

    new_product2 = new_factory.crete_product2()
    new_product2.disp()

抽象工厂模式优缺点 {抽象工厂模式优缺点}

  • 1.你可以确保同一工厂生成的产品相互匹配。可以避免客户端和具体产品代码的耦合。

  • 2.单一职责原则。 你可以将产品生成代码抽取到同一位置, 使得代码易于维护。

  • 3.开闭原则。 向应用程序中引入新产品变体时, 你无需修改客户端代码。

  • 4.由于采用该模式需要向应用中引入众多接口和类, 代码可能会比之前更加复杂。

结语

这就是分享的简单工厂模式、工厂模式和抽象工厂模式的区别,如果大家有更好的想法和需求,也欢迎大家加好友交流分享哈。

—END—
在这里插入图片描述

推荐阅读

【1】C++的智能指针你了解吗?

【2】嵌入式底层开发的软件框架简述

【3】CPU中的程序是怎么运行起来的 必读

【4】cartographer环境建立以及建图测试

【5】阶段性文章总结分析

本公众号全部原创干货已整理成一个目录,回复[ 资源 ]即可获得。

原文作者:良知犹存

原文链接:https://www.cnblogs.com/conscience-remain/p/14491976.html

更多推荐

更多
  • Pharo敏捷人工智能-第一部分:神经网络
    Apache CN

  • Pharo敏捷人工智能-第二部分:遗传算法
    Apache CN

  • Pharo敏捷人工智能-# 第三部分:神经进化 第三部分:神经进化
    Apache CN

  • Azure数据工程指南-二十四、数据治理的权限 创建 azure 预览帐户,探索 azure 预览,探索词汇表,浏览资产,以编程方式使用预览,摘要,管理凭证和访问,创建扫描, 许多组织需要建立数据治理流程、标准和方法,并且已经能够使用内部 SQL Server 工具(如 Master
    Apache CN

  • Azure数据工程指南-二十二、Synapse 分析工作区 创建 Synapse 分析工作区,使用 Spark 探索样本数据,用 SQL 查询数据,用 SQL 创建外部表,摘要, 微软 Azure 数据平台的众多新增功能已经围绕许多类似的产品及其在现代 Azure 数据平台中的用途产生了兴奋和困
    Apache CN

  • Azure数据工程指南-二十三、数据块中的机器学习 创建 MLflow 实验,安装 MLflow 库,创建笔记本,选择性测井,自动记录,摘要, 寻求利用机器学习(ML)和人工智能能力的组织和开发人员花费大量时间构建 ML 模型,并寻求一种方法来简化他们的机器学习开发生命周期,以跟踪实验,
    Apache CN

  • Azure数据工程指南-二十一、将 Apache Spark 的 GraphFrame API 用于图形分析 安装 JAR 库,加载新数据表,将数据加载到数据块笔记本中,用顶点和边构建一个图,查询图表,寻找有图案的图案,用 PageRank 发现重要性,探索入度和出度度量,摘要,进行广度优先搜索,查找连接的组件, 图形技术使用户能够以图形的形式
    Apache CN

  • Azure数据工程指南-20 二十、部署 SQL 数据库先决条件,创建 Visual Studio SQL 数据库项目,安装 Visual Studio GitHub 扩展,导入 AdventureWorks 数据库,连接到 GitHub Repo 源代码控制,将
    Apache CN

  • Azure数据工程指南-十九、部署数据工厂更改 先决条件,创建 DevOps 持续集成构建管道,创建 DevOps 持续部署发布渠道,验证部署的数据工厂资源,摘要,Azure PowerShell 任务停止触发器,ARM 模板部署任务,Azure PowerShell 任务启动触发器
    Apache CN

  • Azure数据工程指南-十八、用于 Cosmos DB 的 Azure Synapse 链接 创建一个 Azure Cosmos DB 帐户,启用 Azure Synapse 链接,创建一个 Cosmos DB 容器和数据库,将数据导入 Azure Cosmos DB,在 Azure Synapse Analytics 中创建
    Apache CN

  • 近期文章

    更多
    文章目录

      推荐作者

      更多