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

2021-3-6 19:38 38558 26 6 分类: MCU/ 嵌入式 文集: 嵌入式


前言:
设计模式已经经历了很长一段时间的发展,它们提供了软件开发过程中面临的一般问题的最佳解决方案。学习这些模式有助于经验不足的开发人员通过一种简单快捷的方式来学习软件设计。
一般我们会说设计模式一共有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++实现
#include 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"<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实现
#!/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++实现
#include 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"<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实现
#!/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):具体工厂所创建的对象,就是此类。
结构图如下
C++实现
#include 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"<CreateProductA(); new_productA2->Show(); Factory1 *new_factory1 = new Factory1(); AbstractProductB *new_productB1 = new_factory1->CreateProductB(); new_productB1->Show(); }
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.由于采用该模式需要向应用中引入众多接口和类, 代码可能会比之前更加复杂。
结语
这就是我分享的简单工厂模式、工厂模式和抽象工厂模式的区别,如果大家有更好的想法和需求,也欢迎大家加我好友交流分享哈。
本公众号全部原创干货已整理成一个目录,回复[ 资源 ]即可获得。

作者: 良知犹存, 来源:面包板社区

链接: https://mbb.eet-china.com/blog/uid-me-3915172.html

版权声明:本文为博主原创,未经本人允许,禁止转载!

PARTNER CONTENT

文章评论3条评论)

登录后参与讨论

我的果果超可爱 2021-3-8 16:20

学习

火引冰薪 2021-3-8 09:29

高内聚,低耦合

欢迎点击,参与讨论   
机器人技术与应用      
https://mbb.eet-china.com/forum/topic/86914_1_1.html

curton 2021-3-7 01:19

学习了

面包板工业电子版块3月份活动,免费送20BB,欢迎留言!
https://mbb.eet-china.com/forum/topic/86917_1_1.html
相关推荐阅读
良知犹存 2021-05-12 19:49
C++解析一些特殊符号tab、换行符号
前言: 我们经常会遇到一些Linux内核信息需要,比如一个wifi数据,中间是用tab键盘隔开的,然后每一行用换行符进行区分,如下所示的数据 第一位置是:wifi名称 第二个位置是:信号强度 第三...
良知犹存 2021-05-10 09:57
C语言0数组\柔性数组使用介绍
前言: 上次看到一篇面试分享,里面有个朋友说,面试官问了char[0] 相关问题,但是自己没有遇到过,就绕过了这个问题。 我自己在这篇文章下面做了一些回复。 现在我想结合我自己的理解,解释一下这...
良知犹存 2021-02-06 09:24
一次小模块的使用过程-LC12S无线模块介绍
前言: 最近帮人做了个小设备,使用了无线模块、触摸芯片,主要功能就是把触摸按键的信号无线传到控制继电器输出,MCU是STM8系列的芯片,其中使用过程中调试无线模块LC21S觉得挺好用的,就写了这篇文...
良知犹存 2021-02-05 20:04
正点原子DS100拆解全过程-硬件工程师必备
前言:之前一篇只针对正点原子DS100手持示波器的使用介绍文章。可作为一个电子工程师,光使用不是我们的风格哈,我们还要拆开看看电路。开拆外壳首先,看下图,DS100不是使用螺母进行固定的,而是通过结构...
良知犹存 2021-01-18 14:16
STM32通过rosserial接入ROS通讯开发
作者:良知犹存 转载授权以及围观:欢迎添加微信公众号:羽林君 前言 主题:串口是一种设备间常用的通讯接口,rosserial将串口字符数据转发到标准ROS网络,并输出到rosout和其日志文件。本...
EE直播间
更多
我要评论
3
26
关闭 站长推荐上一条 /3 下一条