工厂模式是JAVA中最常用的设计模式之一,使用工厂模式后,创建对象的时候不在将创建逻辑暴露给客户端,而是通过实现接口的方式创建对象,这种设计模式也是对象实例化的最佳方式。

概述

工厂模式的三种形态

  • 简单工厂(Simple Factory)
  • 工厂方法(Factory Method)
  • 抽象工厂(Abstract Factory)

简单工厂

简单工厂模式属于工厂模式的小弟,未被收纳进GOF 23中,但是也被频繁使用

1.创建一个Animal接口

interface Shape {void draw();
}

2.创建DogPig实现Animal接口

class Circle implements Shape {public Circle() {System.out.println("创建圆形模型");}@Overridepublic void draw() {System.out.println("画了一个圆形");}
}class Square implements Shape {public Square() {System.out.println("创建了方形模型");}@Overridepublic void draw() {System.out.println("画了一个方形");}
}

3.创建工厂类SimpleFactory,定义一个基于参数信息实例化具体对象的方法

public class SimpleFactory {private final static String CIRCLE = "CIRCLE";private final static String SQUARE = "SQUARE";public static Shape getFactory(String type) {switch (type) {case CIRCLE:return new Circle();case SQUARE:return new Square();default:throw new NullPointerException("未描绘任何图形");}}public static void main(String[] args) {Shape circle = SimpleFactory.getFactory(CIRCLE);circle.draw();Shape square = SimpleFactory.getFactory(SQUARE);square.draw();}
}

4.日志

创建圆形模型
画了一个圆形
创建了方形模型
画了一个方形

分析: 从上述代码中可以发现,简单工厂拥有一定判断能力,构建结果取决于入参,使用起来也十分的方便,也正因为使用太过方便而导致高耦合的情况,所有对象实例化都需要依赖它,一旦出问题,影响的会是整个系统

使用场景: 创建简单,无复杂业务逻辑的对象

工厂方法

前面说到过简单工厂模式存在耦合,且违反了开闭原则,那么这一问题在工厂方法模式中可以很容易的解决掉,它可以做到添加新的产品而不破坏已有代码

工厂方法模式:定义一个创建对象的接口,由它的实现类来决定具体实现,其模式又被称为工厂模式(Factory Pattern)

1.新增ImageReaderFactory抽象工厂接口,用来构建具体的对象

interface ImageReader {void read();
}
interface ImageReaderFactory {ImageReader create();
}

2.相比单一实例化的简单工厂模式而言,方法工厂模式更加的灵活,针对不同的产品(图片读取器)提供不同的工厂。

class JpgReader implements ImageReader {public JpgReader() {System.out.println("创建Jpg读取器");}@Overridepublic void read() {System.out.println("读取Jpg文件");}
}class PngReader implements ImageReader {public PngReader() {System.out.println("创建Png读取器");}@Overridepublic void read() {System.out.println("读取Png文件");}
}
class JpgFactory implements ImageReaderFactory {@Overridepublic ImageReader create() {System.out.println("实例化Jpg文件工厂");return new JpgReader();}
}class PngFactory implements ImageReaderFactory {@Overridepublic ImageReader create() {System.out.println("实例化Png文件工厂");return new PngReader();}
}

3.创建测试类,当然实际使用过程中,实现工厂方法除了可以实例化具体对象,还可以初始化某些资源配置,比如连接池、创建文件等

public class MethodFactory {public static void main(String[] args) {ImageReaderFactory png = new PngFactory();ImageReader pngReader = png.create();pngReader.read();ImageReaderFactory jpg = new JpgFactory();ImageReader jpgReader = jpg.create();jpgReader.read();}
}

4.日志

实例化Png文件工厂
创建Png读取器
读取Png文件
实例化Jpg文件工厂
创建Jpg读取器
读取Jpg文件

优点:

  • 屏蔽了客户端实例化对象的细节,用户只需要关心自己使用的工厂即可。
  • 加入新的产品(图片读取器),无需更改现有代码,提高系统扩展性,符合开闭原则
  • 具备多态性,又被称为多态工厂模式

缺点: 每次需要编写新的对象和对象工厂类,随业务发展,一定程度上增加了系统复杂度

抽象工厂

  • 抽象工厂模式是为创建一组对象提供提供的解决方案,与工厂方法模式相比,抽象工厂模式中的具体工厂不只是创建某一种产品,而是负责一组(产品族)。
  • 抽象工厂模式(Abstract Factory Pattern):提供了创建一系列相互依赖对象的接口,无需指定具体类
  • 抽象工厂模式是围绕着一个超级工厂工作,创造其它的工厂类,也被称为工厂的工厂,这种类型的设计模式是创造性的模式,因为这种模式提供了创建对象的最佳方法之一。

起源

抽象工厂模式的起源或者最早的应用,是用于创建分属于不同操作系统的视窗构建。比如:命令按键(Button)与文字框(Text)都是视窗构建,在UNIX操作系统的视窗环境和Windows操作系统的视窗环境中,这两个构建有不同的本地实现,它们的细节有所不同。

在每一个操作系统中,都有一个视窗构建组成的构建家族。在这里就是Button和Text组成的产品族。而每一个视窗构件都构成自己的等级结构,由一个抽象角色给出抽象的功能描述,而由具体子类给出不同操作系统下的具体实现。

可以发现在上面的产品类图中,有两个产品的等级结构,分别是Button等级结构和Text等级结构。同时有两个产品族,也就是UNIX产品族和Windows产品族。UNIX产品族由UNIX Button和UNIX Text产品构成;而Windows产品族由Windows Button和Windows Text产品构成。

系统对产品对象的创建需求由一个工程的等级结构满足,其中有两个具体工程角色,即UnixFactory和WindowsFactory。UnixFactory对象负责创建Unix产品族中的产品,而WindowsFactory对象负责创建Windows产品族中的产品。这就是抽象工厂模式的应用,抽象工厂模式的解决方案如下图:

显然,一个系统只能够在某一个操作系统的视窗环境下运行,而不能同时在不同的操作系统上运行。所以,系统实际上只能消费属于同一个产品族的产品。

在现代的应用中,抽象工厂模式的使用范围已经大大扩大了,不再要求系统只能消费某一个产品族了。因此,可以不必理会前面所提到的原始用意。

摘抄自《JAVA与模式》之抽象工厂模式:http://www.cnblogs.com/java-my-life/archive/2012/03/28/2418836.html

需求: 开发一款《王者荣耀》,支持多操作系统和多控制方式操作控制界面控制,并提供相应的工厂类来封装这些类的初始化过程

1.创建不同的操作系统接口

interface Linux {void controller();
}interface Windows {void controller();
}

2.基于不同操作系统实现控制逻辑

class LinuxController implements Linux {@Overridepublic void controller() {System.out.println("Linux 控制 《王者荣耀》");}
}class WindowsController implements Windows {@Overridepublic void controller() {System.out.println("Windows 控制 《王者荣耀》");}
}

3.创建一个工厂类,基于接口分别实现操作控制界面控制两种方式的工厂

interface AbstractFactory {Linux installLinux();Windows installWindows();
}class OperationFactory implements AbstractFactory {@Overridepublic Linux installLinux() {System.out.println("安装Linux操作控制系统");return new LinuxController();}@Overridepublic Windows installWindows() {System.out.println("安装Windows操作控制系统");return new WindowsController();}
}class InterfaceFactory implements AbstractFactory {@Overridepublic Linux installLinux() {System.out.println("安装Linux界面控制系统");return new LinuxController();}@Overridepublic Windows installWindows() {System.out.println("安装Windows界面控制系统");return new WindowsController();}
}

4.创建《王者荣耀》进行测试

public class KingGlory {public static void main(String[] args) {AbstractFactory operationFactory = new OperationFactory();operationFactory.installLinux().controller();operationFactory.installWindows().controller();System.out.println("========================================================");AbstractFactory interfaceFactory = new InterfaceFactory();interfaceFactory.installLinux().controller();interfaceFactory.installWindows().controller();}
}

5.日志

安装Linux操作控制系统
Linux 控制 《王者荣耀》
安装Windows操作控制系统
Windows 控制 《王者荣耀》
========================================================
安装Linux界面控制系统
Linux 控制 《王者荣耀》
安装Windows界面控制系统
Windows 控制 《王者荣耀》

分析

使用抽象工厂模式来定义的一系列对象通常是相关或相互依赖的,这些产品对象就构成了一个产品族,也就是抽象工厂定义了一个产品族。这就带来非常大的灵活性,切换产品族的时候,只要提供不同的抽象工厂实现就可以了,也就是说现在是以一个产品族作为一个整体被切换,从上文中可以发现,如果我们需要切换控制方式,只需要变更下对应的工厂类即可

优点:

  • 分离接口和实现:客户端使用抽象工厂来创建需要的对象,而客户端根本就不知道具体的实现是谁,客户端只是面向产品的接口编程而已。也就是说,客户端从具体的产品实现中解耦。
  • 切换产品族变得容易:对于增加新的产品族,抽象工厂模式很好地支持了开闭原则,只需要增加具体产品并对应增加一个新的具体工厂,对已有代码无须做任何修改(如:新增一种手柄操作支持)。

缺点:

  • 不易扩展新产品:如果需要给整个产品族添加一个新的产品,那么就需要修改抽象工厂,这样就会导致修改所有的工厂实现类(如:新增一种操作系统的支持,那么Factory代码需要全部修改)。

使用场景:

  • 一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节,这对于所有形态的工厂模式都是重要的。
  • 这个系统的产品有多于一个的产品族,而系统只消费其中某一族的产品。
  • 同属于同一个产品族的产品是在一起使用的,这一约束必须在系统的设计中体现出来。
  • 系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于实现。

- 说点什么

全文代码:https://gitee.com/battcn/design-pattern/tree/master/Chapter1/battcn-factory

  • 个人QQ:1837307557
  • battcn开源群(适合新手):391619659

微信公众号:battcn(欢迎调戏)

一起学设计模式 - 工厂模式相关推荐

  1. 小猪学设计模式——工厂模式之抽象工厂

    这篇是工厂模式系列的最后一篇 转载于:https://www.cnblogs.com/smallerpig/p/3646150.html

  2. 【Java设计模式】简单学抽象工厂模式——你好,微信还是支付宝

    目录 说明 实现方式 自问自答 其他链接 说明 五大创建型模式之一,其他还有单例模式.原型模式.建造者模式.工厂模式. 抽象工厂模式(Abstract Factory Pattern):定义了一个in ...

  3. 设计模式-工厂模式三部曲

    设计模式-工厂模式三部曲(转) 转自:http://www.cnblogs.com/holyknight-zld/category/402079.html 工厂模式三部曲之一_简单工厂模式 转自:ht ...

  4. Java设计模式-工厂模式(3)抽象工厂模式

    在Java设计模式-工厂模式(2)工厂方法模式 我们知道了工厂方法模式解决了简单工厂模式中的缺陷,做到了满足开闭原则,但是时代是进步的,进而又产生新的问题,工厂难道只能生产一种东西吗.我们所见到的工厂 ...

  5. Java设计模式-工厂模式(2)工厂方法模式

    在Java设计模式-工厂模式(1)简单工厂模式 中我们介绍了简单工厂模式,提到了简单工厂模式违背了开闭原则,而"工厂方法模式"是对简单工厂模式的进一步抽象化,其好处是可以使系统在不 ...

  6. Java设计模式-工厂模式(1)简单工厂模式

    Java设计模式-工厂模式(1)简单工厂模式 一.前言 1)例子 2)类图关系 3)代码实现 二.简单工厂模式 2.1.概述: 2.2.类图关系: 2.3.代码修改: 2.4.优缺点 2.5.扩展-简 ...

  7. 设计模式---工厂模式

    设计模式---工厂模式 工厂方法模式 概述:工厂方法模式中抽象工厂负责定义创建对象的接口,具体创建工作由继承抽象工厂的具体类实现. 优点:客户端不需要再负责对象的创建,从而明确了各个类的职责,如果有新 ...

  8. java设计模式工厂模式_Java中的工厂设计模式

    java设计模式工厂模式 Welcome to the Factory Design Pattern in Java tutorial. Factory Pattern is one of the C ...

  9. java设计模式工厂模式_Java中的复合设计模式

    java设计模式工厂模式 Composite pattern is one of the Structural design pattern. Composite design pattern is ...

最新文章

  1. 微软获GPT-3独家授权,OpenAI创始人马斯克:与初衷相悖
  2. 2017 人工智能+内容生产研究报告【附下载】
  3. SpringBoot - 优雅的处理【长事务】
  4. php8vsgo,vscode编辑好go语言代码要怎么运行
  5. CocoaPods pod install/pod update更新慢的问题
  6. 交换机集群管理(锐捷)
  7. python数字转换成中文大写_python中如何将货币数字转化成汉字大写金额
  8. NetMeeting不能共享桌面的解决办法
  9. Linux就业技术指导:简历项目经验示例
  10. Ubuntu阿里源镜像
  11. Mini-USB接口的引脚定义与USB与miniUSB接口区别
  12. 存储数据迁移解决方案
  13. Fortran的全局变量(Common blocks)
  14. 运营_APP的常见盈利模式
  15. 关于统计检验中P值的解释
  16. spring boot 2.1学习笔记【异常】lombok.javac.apt.LombokProcessor could not be initialized
  17. 技术硬实力+服务软实力,声网助力出海企业破解水土不服难题
  18. c++ word文档操作
  19. 如何使用python_pygame设计一个接鸡蛋游戏
  20. python判断闰年_python——闰年的判断

热门文章

  1. c语言编译四个步骤,gcc编译的四个步骤
  2. 保留小数位数、取舍方式计算
  3. 中小学计算机课程标准及解读,中小学信息技术课程标准及解读.pdf
  4. linux设置文件为不可访问权限,Centos给文件设置了777权限仍不能访问解决方案
  5. XMLSOAP应用简介
  6. PL/SQL Developer常用命令快捷设置
  7. eCognition8分类初级教程
  8. Graph Decipher: A transparent dual-attention graph neural network 图解密器:一种透明的双注意图神经网络,用于理解节点分类的消息传递机制
  9. egg-mysql 初始_Egg学习_Setp1_初始化项目添加数据库
  10. 事业单位招聘信息在哪看