工厂方法模式和抽象工厂模式

本文主要是记录学习设计模式当中的工厂方法和抽象工厂时碰到的疑惑和对答案的探讨

刚接触时的工厂方法模式和抽象工厂模式

工厂方法模式

类图

代码


//工厂public interface TVFactory {TV produce();
}public class TclTVFactory implements TVFactory{@Overridepublic TV produce() {System.out.println("TCL工厂生产了一台TCL电视");return new TclTV();}
}//产品public interface TV {void play();
}public class TclTV implements TV{@Overridepublic void play() {System.out.println("你好,我是TCL电视");}
}
public class Client {public static void main(String[] args) {TVFactory factory;TV tv;factory = new TclTVFactory();tv = factory.produce();tv.play();}
}

运行结果

TCL工厂生产了一台TCL电视
你好,我是TCL电视

根据上面的方法,当需要增加生产一个品牌的产品时,例如生产hisense电视,只需要再增加一个工厂类HisenseTVFactory实现TVFactory接口,和一个产品类HisenseTV实现TV接口即可,无需改动源代码,符合开闭原则。

抽象工厂模式

类图

代码

public interface Factory {TV produceTV();Fridge produceFridge();}public class TCLFactory implements Factory{@Overridepublic TV produceTV() {System.out.println("生产了TCL电视");return new TclTV();}@Overridepublic Fridge produceFridge() {System.out.println("生产了TCL冰箱");return new TclFridge();}
}public class HisenseFactory implements Factory{@Overridepublic TV produceTV() {System.out.println("生产了海信电视");return new HisenseTV();}@Overridepublic Fridge produceFridge() {System.out.println("生产了海信冰箱");return new HisenseFridge();}
}
public interface TV {void play();
}public class TclTV implements TV{@Overridepublic void play() {System.out.println("我是TCL电视");}
}public class HisenseTV implements TV{@Overridepublic void play() {System.out.println("我是海信电视");}
}public interface Fridge {void cooling();
}public class TclFridge implements Fridge{@Overridepublic void cooling() {System.out.println("我是TCL冰箱");}
}public class HisenseFridge implements Fridge{@Overridepublic void cooling() {System.out.println("我是海信冰箱");}
}
public class Client {public static void main(String[] args) {Factory factory;TV tv;Fridge fridge;factory = new HisenseFactory();tv = factory.produceTV();tv.play();fridge = factory.produceFridge();fridge.cooling();}
}

运行结果

生产了海信电视
我是海信电视
生产了海信冰箱
我是海信冰箱

由以上可知,抽象工厂模式增加产品族的时候是不需要修改原来的代码的符合开闭原则,但是增加产品等级结构,那就不适用了

学完工厂方法模式和抽象工厂模式后的问题

相信许多人和我一样,在学完上述两个模式后,再看到模式的分类,就会产生一个疑问

模式的分类就是工厂方法模式属于类模式,抽象工厂模式属于对象模式

看到这里我云里雾里的,什么是类模式什么是对象模式?好吧,以下是软设教材的概念

看到这里还是不懂,而且我发现用之前的工厂方法和抽象工厂方法的类图去套这条解释,我会发现,要么都是类模式要么都是对象模式,没有什么不同啊(都是增加一个抽象工厂/具体工厂和抽象产品/具体产品,client的调用也是一样的)

由此我开始了漫长的探索之路,直到我看到了这篇解释,突然豁然开朗,为避免歧义,我粘贴原文,有需要的自行复制翻译

The main difference between Abstract Factory and Factory Method is that Abstract Factory is implemented by Composition; but Factory Method is implemented by Inheritance.

Yes, you read that correctly: the main difference between these two patterns is the old composition vs inheritance debate.

UML diagrams can be found in the (GoF) book. I want to provide code examples, because I think combining the examples from the top two answers in this thread will give a better demonstration than either answer alone. Additionally, I have used terminology from the book in class and method names.

Abstract Factory

  1. The most important point to grasp here is that the abstract factory is injected into the client. This is why we say that Abstract Factory is implemented by Composition. Often, a dependency injection framework would perform that task; but a framework is not required for DI.
  2. The second critical point is that the concrete factories here are not Factory Method implementations! Example code for Factory Method is shown further below.
  3. And finally, the third point to note is the relationship between the products: in this case the outbound and reply queues. One concrete factory produces Azure queues, the other MSMQ. The GoF refers to this product relationship as a "family" and it's important to be aware that family in this case does not mean class hierarchy.
public class Client {private final AbstractFactory_MessageQueue factory;public Client(AbstractFactory_MessageQueue factory) {// The factory creates message queues either for Azure or MSMQ.// The client does not know which technology is used.this.factory = factory;}public void sendMessage() {//The client doesn't know whether the OutboundQueue is Azure or MSMQ.OutboundQueue out = factory.createProductA();out.sendMessage("Hello Abstract Factory!");}public String receiveMessage() {//The client doesn't know whether the ReplyQueue is Azure or MSMQ.ReplyQueue in = factory.createProductB();return in.receiveMessage();}
}public interface AbstractFactory_MessageQueue {OutboundQueue createProductA();ReplyQueue createProductB();
}public class ConcreteFactory_Azure implements AbstractFactory_MessageQueue {@Overridepublic OutboundQueue createProductA() {return new AzureMessageQueue();}@Overridepublic ReplyQueue createProductB() {return new AzureResponseMessageQueue();}
}public class ConcreteFactory_Msmq implements AbstractFactory_MessageQueue {@Overridepublic OutboundQueue createProductA() {return new MsmqMessageQueue();}@Overridepublic ReplyQueue createProductB() {return new MsmqResponseMessageQueue();}
}

Factory Method

  1. The most important point to grasp here is that the is the client. In other words, the client is a subclass whose parent defines the . This is why we say that Factory Method is implemented by Inheritance.ConcreteCreatorfactoryMethod()
  2. The second critical point is to remember that the Factory Method Pattern is nothing more than a specialization of the Template Method Pattern. The two patterns share an identical structure. They only differ in purpose. Factory Method is creational (it builds something) whereas Template Method is behavioral (it computes something).
  3. And finally, the third point to note is that the (parent) class invokes its own . If we remove from the parent class, leaving only a single method behind, it is no longer the Factory Method pattern. In other words, Factory Method cannot be implemented with less than two methods in the parent class; and one must invoke the other.CreatorfactoryMethod()anOperation()
public abstract class Creator {public void anOperation() {Product p = factoryMethod();p.whatever();}protected abstract Product factoryMethod();
}public class ConcreteCreator extends Creator {@Overrideprotected Product factoryMethod() {return new ConcreteProduct();}
}

再配合软设教材的两个类图,这才发现两者的区别

工厂方法模式

抽象工厂模式

好了,就说到这里了,剩下的就靠大家自己体会领悟了,再见^_^

附录:

参考书籍

《软件设计师教程》

相关论坛

https://stackoverflow.com/questions/46041363/why-is-factory-method-a-class-pattern-while-an-abstract-factory-an-object-patte
https://stackoverflow.com/questions/5739611/what-are-the-differences-between-abstract-factory-and-factory-design-patterns#
https://blog.csdn.net/lovelion/article/details/9319481

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/13962.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

NVR小程序接入平台EasyNVR多品牌NVR管理工具/设备:RTMP协议摄像头的接入

随着安防技术的不断进步,越来越多的摄像头开始支持RTMP(Real Time Messaging Protocol)协议,这种协议使得视频流的实时传输和分发变得更加高效和便捷。NVR小程序接入平台EasyNVR作为一款功能强大的流媒体服务器,支持多…

硬件基础20 数模转换器D/A DAC

目录 一、DAC基本原理 二、倒T形电阻网络D/A转换器 三、权电流型D/A转换器 四、重要技术指标与参数 1、分辨率/位数 2、转换精度 (1)、比例系数误差 (2)、失调误差 3、转换速度 4、温度系数 五、DAC的应用 1、数字式可…

Memory consistency model 梳理目录

(图片来源:https://mp.weixin.qq.com/s/uz4fZgJSRNm-MIRdXgBMmw) 闲聊内存模型(Memory Model)https://blog.csdn.net/zhangshangjie1/article/details/143743250?sharetypeblogdetail&sharerId143743250&sharereferPC&sharesourcezhangshangjie1&…

WPF Prism框架

Prism 是一个开源框架,专门用于开发可扩展、模块化和可测试的企业级 XAML 应用程序,适用于 WPF(Windows Presentation Foundation)和 Xamarin Forms 等平台。它基于 MVVM(Model-View-ViewModel)设计模式&am…

智能零售柜商品识别

项目源码获取方式见文章末尾! 600多个深度学习项目资料,快来加入社群一起学习吧。 《------往期经典推荐------》 项目名称 1.【基于CNN-RNN的影像报告生成】 2.【卫星图像道路检测DeepLabV3Plus模型】 3.【GAN模型实现二次元头像生成】 4.【CNN模型实现…

SSH远程连接工具详解

SSH远程连接工具指的是基于SSH(Secure Shell)协议进行远程连接和管理的工具。SSH是一种加密的网络协议,用于在不安全的网络环境中安全地传输数据,并实现远程访问和管理。以下是对远程SSH工具的详细解释: 一、SSH协议概…

卷积层的堆叠、Stacking堆叠法

3个3x3的卷积层串联的效果则相当于1个7x7的卷积层。那为什么选择使用3个3x3的卷积层而不是使用1个7x7的卷积层呢? (1)3个串联的3x3的卷积层,拥有比1个7x7的卷积层更少的参数,参数量是后者的(3x3x3 ) /&…

【模块一】kubernetes容器编排进阶实战之containerd安装及nerdctl客户端⼯具

安装containerd apt/yum安装 #验证仓库版本 [rootk8s-node3 ~]#apt-cache madison containerd containerd | 1.7.12-0ubuntu2~22.04.1 | https://mirrors.aliyun.com/ubuntu jammy-updates/main amd64 Packages containerd | 1.6.12-0ubuntu1~22.04.3 | https://mirrors.aliy…

公司电脑加全屏水印怎么加(怎么打水印满屏)?4个方法精选!包教包会!

在企业管理中,为了保护公司机密信息的安全,给公司电脑添加全屏水印已成为一种常见的安全措施。 全屏水印不仅可以震慑潜在的窥探者,还能在信息不慎泄露时提供追溯线索。 那么,如何给公司电脑添加全屏水印呢? 以下是4…

public or static包下的 html 丢了(404)? 你快回来! 我一人承受不来

没想到吧,我把html还是放到了jar包中~ 环境: Spring Boot 版本 2.XJava 版本 1.8.0 及以上 问题: public or static包下的 html 丢了(404)? 话不多说先上图 我的目录结构是这样的 src └─…

使用多种机器学习调参模型进行二分类建模的全流程,代做分析辅导

使用多种机器学习调参模型进行二分类建模的全流程教程 机器学习全流程分析各个模块用到的总的参数文件 0. 分析参数文件 参数文件名称:total_analysis_params_demo.xlsx ,很多分析模块都是这个总的参数文件,我的这个总的参数文件如果有更新…

国家博物馆数据的爬取(包括xlsx文件、csv文件、图片爬取)

1、请求html数据 右键检查这里静态的数据被注释掉了,只能读取一条数据 import json import pandas as pd import requests from bs4 import BeautifulSoup import csv from urllib.parse import quote # 起始网址 header={User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; …

云技术基础介绍

云技术介绍 一、云技术历史 二、云服务 三、公有云服务商 四、云分类 1. 服务层级 IaaS (基础设施即服务) PaaS (平台即服务) SaaS (软件即服务) 2. 云部署模式的分类 公有云 (Public Cloud) 私有云 (Private Cloud) 混合云 (Hybrid Cloud) 社区云 (Community Clo…

常用的c++新特性-->day09

原子变量 C11提供了一个原子类型std::atomic,通过这个原子类型管理的内部变量就可以称之为原子变量,我们可以给原子类型指定bool、char、int、long、指针等类型作为模板参数(不支持浮点类型和复合类型)。 原子变量会把线程对数据的…

新的服务器Centos7.6 安装基础的环境配置(新服务器可直接粘贴使用配置)

常见的基础服务器配置之Centos命令 正常来说都是安装一个docker基本上很多问题都可以解决了,我基本上都是通过docker去管理一些容器如:mysql、redis、mongoDB等之类的镜像,还有一些中间件如kafka。下面就安装一个 docker 和 nginx 的相关配置…

RAG与知识库搭建,手把手教你构建RAG系统

0. 简介 自从发现可以利用自有数据来增强大语言模型(LLM)的能力以来,如何将 LLM 的通用知识与个人数据有效结合一直是热门话题。关于使用微调(fine-tuning)还是检索增强生成(RAG)来实现这一目标…

【数据结构】10.线索二叉树

一、线索二叉树的产生 采用先序、中序、后序三种方法遍历二叉树后都可以得到一个线性序列,序列上的每一个结点(除了第一个和最后一个)都有一个前驱和一个后继,但是,这个线性序列只是逻辑的概念,不是物理结…

java实现中小企业的erp系统

项目介绍 技术架构: springboot3jdk17mybatis-plusmysql8kotlinvueuniappelementui等

企业软文营销如何以差异化卖点助力品牌市场曝光?媒介盒子分享

对于市场竞争日益激烈的现下,企业想要获取优势,从市场中脱颖而出并能吸引到更多的消费者,学会创建或找寻到自身的差异点是至关重要的。常言讲“物以稀为贵”,对于消费者而言,品类相同中的品牌需要去以“不同”来获取用…

探索Pillow库:Python图像处理的瑞士军刀

文章目录 **探索Pillow库:Python图像处理的瑞士军刀**1. 背景:为何选择Pillow?2. Pillow是什么?3. 如何安装Pillow?4. 五个简单的库函数使用方法4.1 打开图像4.2 显示图像4.3 转换图像格式4.4 调整图像大小4.5 旋转图像…