《Java设计模式》之抽象工厂模式
场景问题
举个生活中常见的样例——组装电脑。我们在组装电脑的时候。通常须要选择一系列的配件,比方CPU、硬盘、内存、主板、电源、机箱等。
为讨论使用简单点。仅仅考虑选择CPU和主板的问题。
其实,在选择CPU的时候,面临一系列的问题。比方品牌、型号、针脚数目、主频等问题,仅仅有把这些问题都确定下来,才干确定详细的CPU。
同样。在选择主板的时候,也有一系列问题。比方品牌、芯片组、集成芯片、总线频率等问题,也仅仅有这些都确定了。才干确定详细的主板。
选择不同的CPU和主板,是每个客户在组装电脑的时候。向装机公司提出的要求。也就是我们每个人自己拟定的装机方案。
在终于确定这个装机方案之前。还须要总体考虑各个配件之间的兼容性。比方:CPU和主板,假设使用Intel的CPU和AMD的主板是根本无法组装的。因为Intel的CPU针脚数与AMD主板提供的CPU插口不兼容,就是说假设使用Intel的CPU根本就插不到AMD的主板中,所以装机方案是总体性的,里面选择的各个配件之间是有关联的。
对于装机project师而言。他仅仅知道组装一台电脑,须要对应的配件。但是详细使用什么样的配件,还得由客户说了算。也就是说装机project师仅仅是负责组装。而客户负责选择装配所须要的详细的配件。因此。当装机project师为不同的客户组装电脑时,仅仅须要依据客户的装机方案,去获取对应的配件,然后组装就可以。
使用简单工厂模式的解决方式
考虑客户的功能。须要选择自己须要的CPU和主板,然后告诉装机project师自己的选择,接下来就等着装机project师组装电脑了。
对装机project师而言,仅仅是知道CPU和主板的接口,而不知道详细实现,非常明显能够用上简单工厂模式或工厂方法模式。为了简单,这里选用简单工厂。
客户告诉装机project师自己的选择,然后装机project师会通过对应的工厂去获取对应的实例对象。
源码
CPU接口与详细实现
- ;
- ;
- ;
- ;
- ) {
- );
- ) {
- );
- ) {
- );
- ) {
- );
- , 1);
- ,而选择的主板是AMD。主板上的CPU插孔是。根本无法组装,这就是没有维护配件之间的关系造成的。该怎么解决问题呢?
引进抽象工厂模式
每个模式都是针对一定问题的解决方式。
抽象工厂模式与工厂方法模式的最大差别就在于。工厂方法模式针对的是一个产品等级结构;而抽象工厂模式则须要面对多个产品等级结构。
在学习抽象工厂详细实例之前,应该明确两个重要的概念:产品族和产品等级。
所谓产品族,是指位于不同产品等级结构中,功能相关联的产品组成的家族。比方AMD的主板、芯片组、CPU组成一个家族,Intel的主板、芯片组、CPU组成一个家族。
而这两个家族都来自于三个产品等级:主板、芯片组、CPU。一个等级结构是由同样的结构的产品组成,示意图例如以下:
显然,每个产品族中含有产品的数目,与产品等级结构的数目是相等的。产品的等级结构与产品族将产品依照不同方向划分。形成一个二维的坐标系。
横轴表示产品的等级结构,纵轴表示产品族,上图共同拥有两个产品族,分布于三个不同的产品等级结构中。
仅仅要指明一个产品所处的产品族以及它所属的等级结构,就能够唯一的确定这个产品。
上面所给出的三个不同的等级结构具有平行的结构。因此,假设採用工厂方法模式。就势必要使用三个独立的工厂等级结构来对付这三个产品等级结构。因为这三个产品等级结构的类似性,会导致三个平行的工厂等级结构。随着产品等级结构的数目的添加,工厂方法模式所给出的工厂等级结构的数目也会随之添加。例如以下图:
那么,能否够使用同一个工厂等级结构来对付这些同样或者极为类似的产品等级结构呢?当然能够的,并且这就是抽象工厂模式的优点。同一个工厂等级结构负责三个不同产品等级结构中的产品对象的创建。
能够看出,一个工厂等级结构能够创建出分属于不同产品等级结构的一个产品族中的全部对象。
显然,这时候抽象工厂模式比简单工厂模式、工厂方法模式更有效率。
对应于每个产品族都有一个详细工厂。而每个详细工厂负责创建属于同一个产品族。但是分属于不同等级结构的产品。
抽象工厂模式结构
抽象工厂模式是对象的创建模式,它是工厂方法模式的进一步推广。
假设一个子系统须要一些产品对象,而这些产品又属于一个以上的产品等级结构。那么为了将消费这些产品对象的责任和创建这些产品对象的责任切割开来。能够引进抽象工厂模式。这种话。消费产品的一方不须要直接參与产品的创建工作。而仅仅须要向一个公用的工厂接口请求所须要的产品。
通过使用抽象工厂模式,能够处理具有同样(或者类似)等级结构中的多个产品族中的产品对象的创建问题。例如以下图所看到的:
因为这两个产品族的等级结构同样,因此使用同一个工厂族也能够处理这两个产品族的创建问题,这就是抽象工厂模式。
依据产品角色的结构图,就不难给出工厂角色的结构设计图。
能够看出。每个工厂角色都有两个工厂方法,分别负责创建分属不同产品等级结构的产品对象。
源码
前面演示样例实现的CPU接口和CPU实现对象,主板接口和主板实现对象,都不须要变化。
前面演示样例中创建);
- );
- );
- );
- }
- }
装机project师类跟前面的实现相比,基本的变化是:从client不再传入选择CPU和主板的參数,而是直接传入客户已经选择好的产品对象。
这样就避免了单独去选择CPU和主板所带来的兼容性问题,客户要选就是一套。就是一个系列。
- package com.bankht.abstractFactory;
- /**
- * @author: 特种兵—AK47
- * @创建时间:2012-6-19 下午04:59:14
- *
- * @类说明 :装机project师
- */
- public class ComputerEngineer {
- /**
- * 定义组装机须要的CPU
- */
- private Cpu cpu = null;
- /**
- * 定义组装机须要的主板
- */
- private Mainboard mainboard = null;
- public void makeComputer(AbstractFactory af) {
- /**
- * 组装机器的基本步骤
- */
- // 1:首先准备好装机所须要的配件
- prepareHardwares(af);
- // 2:组装机器
- // 3:測试机器
- // 4:交付客户
- }
- private void prepareHardwares(AbstractFactory af) {
- // 这里要去准备CPU和主板的详细实现,为了演示样例简单。这里仅仅准备这两个
- // 但是。装机project师并不知道怎样去创建。怎么办呢?
- // 直接找对应的工厂获取
- this.cpu = af.createCpu();
- this.mainboard = af.createMainboard();
- // 測试配件是否好用
- this.cpu.calculate();
- this.mainboard.installCPU();
- }
- }
client代码:
- package com.bankht.abstractFactory;
- import org.junit.Test;
- /**
- * @author: 特种兵—AK47
- * @创建时间:2012-6-19 下午05:01:04
- *
- * @类说明 :客户測试类
- */
- public class Client {
- @Test
- public void test() {
- // 创建装机project师对象
- ComputerEngineer cf = new ComputerEngineer();
- // 客户选择并创建须要使用的产品对象
- AbstractFactory af = new AmdFactory();
- // 告诉装机project师自己选择的产品,让装机project师组装电脑
- cf.makeComputer(af);
- }
- }
抽象工厂的功能是为一系列相关对象或相互依赖的对象创建一个接口。一定要注意,这个接口内的方法不是随意堆砌的,而是一系列相关或相互依赖的方法。比方上面样例中的主板和CPU,都是为了组装一台电脑的相关对象。不同的装机方案,代表一种详细的电脑系列。
因为抽象工厂定义的一系列对象一般是相关或相互依赖的,这些产品对象就构成了一个产品族。也就是抽象工厂定义了一个产品族。
这就带来非常大的灵活性,切换产品族的时候,仅仅要提供不同的抽象工厂实现就能够了。也就是说如今是以一个产品族作为一个总体被切换
在什么情况下应当使用抽象工厂模式
1.一个系统不应当依赖于产品类实例怎样被创建、组合和表达的细节,这对于全部形态的工厂模式都是重要的。
2.这个系统的产品有多于一个的产品族,而系统仅仅消费当中某一族的产品。
3.同属于同一个产品族的产品是在一起使用的,这一约束必须在系统的设计中体现出来。(比方:Intel主板必须使用Intel CPU、Intel芯片组)
4.系统提供一个产品类的库。全部的产品以同样的接口出现。从而使client不依赖于实现。
抽象工厂模式的起源
抽象工厂模式的起源或者最早的应用,是用于创建分属于不同操作系统的视窗构建。
比方:命令按键(Button)与文字框(Text)都是视窗构建,在UNIX操作系统的视窗环境和Windows操作系统的视窗环境中,这两个构建有不同的本地实现,它们的细节有所不同。
在每个操作系统中。都有一个视窗构建组成的构建家族。在这里就是Button和Text组成的产品族。
而每个视窗构件都构成自己的等级结构,由一个抽象角色给出抽象的功能描写叙述。而由详细子类给出不同操作系统下的详细实现。
能够发如今上面的产品类图中。有两个产品的等级结构。各自是Button等级结构和Text等级结构。同一时候有两个产品族。也就是UNIX产品族和 Windows产品族。UNIX产品族由UNIX Button和UNIX Text产品构成;而Windows产品族由Windows Button和Windows Text产品构成。
系统对产品对象的创建需求由一个project的等级结构满足,当中有两个详细project角色,即UnixFactory和WindowsFactory。 UnixFactory对象负责创建Unix产品族中的产品,而WindowsFactory对象负责创建Windows产品族中的产品。这就是抽象工厂模式的应用,抽象工厂模式的解决方式例如以下图:
显然,一个系统仅仅能够在某一个操作系统的视窗环境下执行,而不能同一时候在不同的操作系统上执行。所以,系统实际上仅仅能消费属于同一个产品族的产品。
在现代的应用中,抽象工厂模式的使用范围已经大大扩大了,不再要求系统仅仅能消费某一个产品族了。
因此。能够不必理会前面所提到的原始用意。
抽象工厂模式的优点
- 分离接口和实现
client使用抽象工厂来创建须要的对象,而client根本就不知道详细的实现是谁。client仅仅是面向产品的接口编程而已。也就是说,client从详细的产品实现中解耦。
- 使切换产品族变得easy
因为一个详细的工厂实现代表的是一个产品族。比方上面样例的从Intel系列到AMD系列仅仅须要切换一下详细工厂。
抽象工厂模式的缺点
- 不太easy扩展新的产品
假设须要给整个产品族加入一个新的产品。那么就须要改动抽象工厂,这样就会导致改动全部的工厂实现类。
《Java设计模式》之抽象工厂模式的更多相关文章
- Java设计模式之【工厂模式】(简单工厂模式,工厂方法模式,抽象工厂模式)
Java设计模式之[工厂模式](简单工厂模式,工厂方法模式,抽象工厂模式) 工厂模式出现的原因 在java中,创建一个对象最简单的方法就是使用new关键字.但在一些复杂的业务逻辑中,创建一个对象不只需 ...
- Java开发中的23中设计模式详解(一)工厂方法模式和抽象工厂模式
一.设计模式的分类 总体来说设计模式分为三大类: 创建型模式,共五种:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式. 结构型模式,共七种:适配器模式.装饰器模式.代理模式.外观模式.桥接 ...
- 重学 Java 设计模式:实战抽象工厂模式
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获!
- Java设计模式学习记录-抽象工厂模式
前言 上篇博客介绍了简单工厂模式和工厂方法模式,这次介绍抽象工厂模式,抽象工厂模式和工厂方法模式的区别在于需要创建对象的复杂程度上. 抽象工厂模式 抽象工厂模式是围绕着一个超级工厂创建其他工厂.这个超 ...
- java设计模式-----3、抽象工厂模式
抽象工厂模式是所有形态的工厂模式中最为抽象和最具一般性的一种形态.抽象工厂模式是指当有多个抽象角色时,使用的一种工厂模式.抽象工厂模式可以向客户端提供一个接口,使客户端在不必指定产品的具体的情况下,创 ...
- Java设计模式(3)——创建型模式之抽象工厂模式(Abstract Factory)
一.概述 抽象工厂模式是指当有多个抽象角色时,使用的一种工厂模式.抽象工厂模式可以向客户端提供一个接口,使客户端在不必指定产品的具体情况下,创建多个产品族中的产品对象. UML图: 其他的过多概念不再 ...
- java设计模式 -------- 创建模式 之 抽象工厂模式
本文是自己学习所做笔记,欢迎转载,但请注明出处:http://blog.csdn.net/jesson20121020 工厂方法模式和抽象工厂模式不好区分清楚: 工厂方法模式特点: 1. 一个抽象产品 ...
- JAVA中的工厂方法模式和抽象工厂模式
工厂方法模式: 定义:定义一个用于创建对象的接口,让子类决定实例化哪一个类,工厂方法使一个类的实例化延迟到其子类.类型:创建类模式类图: 类图知识点:1.类图分为三部分,依次是类名.属性.方法2.以& ...
- 【java设计模式】-03抽象工厂模式
抽象工厂 简述 抽象工厂模式(Abstract Factory Pattern):提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类.在抽象工厂模式中,接口是负责创建一个相关对象的工厂 ...
- [19/04/23-星期二] GOF23_创建型模式(工厂模式、抽象工厂模式)
一.工厂模式(分为:简单工厂模式.工厂方法模式.抽象工厂模式) 实现了创建者和调用者的分离 核心本质:1.实例化对象,用工厂方法代替new操作:2.将选择实现类.创建对象统一管理和控制,从而将调用者跟 ...
随机推荐
- 洛谷——P2957 [USACO09OCT]谷仓里的回声Barn Echoes
https://www.luogu.org/problem/show?pid=2957 题目描述 The cows enjoy mooing at the barn because their moo ...
- web显示winform,web打开winform,IE打开winform
前言:为什么要用ie打开winform 个人觉得,winform部署client太麻烦如金蝶··用友,winfrom打补丁太麻烦,加入新功能再部署很费时间:于是就想为什么不能用IE打开呢?这样就不须要 ...
- Qt样式表之盒子模型(以QSS来讲解,而不是CSS)
说起样式表,不得不提的就是盒子模型了,今天小豆君就来给大家介绍下盒子模型. 上图是一张盒子模型图. 对于一个窗口,其包括四个矩形边框.以中间的边框矩形(border)为基准,在border外侧的是外边 ...
- mysql 不能启动的两种错误提示及解决方法
在linux系统中安装mysql服务器详细步骤并解决ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using passw ...
- system.setting-全局变量数据监听
今天在setting里添加了一个新的变量,想要实现对这个变量的监听.现在记录下方法 首先就是明白一点,我们在system.setting里添加的变量,都会被保存在data/data/com.andro ...
- Incapsula免费日本CDN加速和CDNZZ香港CDN节点加速
Incapsula免费日本CDN加速和CDNZZ香港CDN节点加速 免费的CDN对于那些将空间放在美国的博客网站加速效果是最好的,CDN可以解决国内连接美国的网络线路经常抽风和访问速度时好时坏的问题, ...
- Bitmap-把方形图片处理为圆形
这个是直接在网上转载的,自己验证可靠 转载自http://my.oschina.net/zhouz/blog/213164 直接贴上代码 import android.graphics.Bitmap; ...
- rocketmq事务消息入门介绍
说明 周五的时候发了篇:Rocketmq4.3支持事务啦!!!,趁着周末的时候把相关内容看了下,下面的主要内容就是关于RocketMQ事务相关内容介绍了. 说明: 今天这篇仅仅是入门介绍,并没有涉及到 ...
- input输入框获得、失去焦点添加事件
onBlur:当输入框失去焦点后 onFocus:当输入框获得焦点后 这两个JavaScript事件是写在html标签中的例如: <input type="text" onB ...
- css实现简单的告警提示动画效果
需求:css实现简单的告警提示动画效果,当接收到实时信息的时候,页面弹出告警信息的动画效果 <!DOCTYPE html> <html lang="en"> ...