博主声明:

转载请在开头附加本文链接及作者信息,并标记为转载。本文由博主 威威喵 原创,请多支持与指教。

本文首发于此   博主:威威喵  |  博客主页:https://blog.csdn.net/smile_running

工厂模式是比较常用的设计模式之一,通常用于对象的创建操作。联想我们实际生活中的工厂,在制造产品的时候,使用是一种严格的流程,用机器把复杂的工序简单化,而我们就不需要去了解这个东西如何被创建出来,只需要把创建的物品,通过简单的加工、包装一下就可以使用。

工厂模式就是这个样子的,我们不需要知道那个物品究竟如何被创建出来的,更不需知道经过哪些复杂的操作步骤,只要我们知道如何使用即可。工厂模式的定义:属于创建型模式,它提供了一种创建对象的最佳方式。在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。

    工厂模式的写法就是:定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。工厂模式分三种:简单工厂、工厂方法、抽象工厂。每一种都有细微的变化,需要根据实际场景决定如何选择。

简单工厂写法

接下来,我们通过一个 茶厂 的案例来使用简单工厂、工厂方法、抽象工厂这三种方式写一下代码。步入正题,话说某地有一个制作茶叶的公司,它的旗下有一个规模不大的茶厂,这个茶厂中拥有三台机器,分别是小型、中型、大型机器,每台机器的产量都是不一样的,而且耗电也有差距,所以为了节省资金,公司都会根据当天待加工的茶叶量进行选择运作的机器。

机器是一个枚举类型,机器代码:

package com.xww.dp.factory;/*** 制茶的机器* * @author xww**/
public enum Mechine {SmallMechine, MiddleMechine, BigMechine
}

这家公司规模比较小,由于技术资金和技术有限,目前只能生产红茶、绿茶、白茶、龙井茶这四个品种,它是一个接口:

package com.xww.dp.factory;/*** 茶公司的主要生产茶品种情况** @author xww**/
public interface TeaCompany {void hongCha();// 红茶void lvCha();// 绿茶void baiCha();// 白茶void longJing();// 龙井
}

因为茶厂中有三台机器,每一台的产量和耗电量都是不同的,那么机器就需要实现这个接口,只有实现接口才能执行上面所说的不同品种的茶的生产功能。
小型机器:

package com.xww.dp.factory;/*** 小型机器* * @author xww**/
public class SmallMechineFactory implements TeaCompany {public SmallMechineFactory() {}@Overridepublic void hongCha() {System.out.println("生产了 0.5t 红茶");}@Overridepublic void lvCha() {System.out.println("生产了 0.6t 绿茶");}@Overridepublic void baiCha() {System.out.println("生产了 0.4t 白茶");}@Overridepublic void longJing() {System.out.println("生产了 0.2t 龙井茶");}}

中型机器:

package com.xww.dp.factory;/*** 中型机器* * @author xww**/
public class MiddleMechineFactory implements TeaCompany {public MiddleMechineFactory() {}@Overridepublic void hongCha() {System.out.println("生产了 1t 红茶");}@Overridepublic void lvCha() {System.out.println("生产了 1.2t 绿茶");}@Overridepublic void baiCha() {System.out.println("生产了 0.8t 白茶");}@Overridepublic void longJing() {System.out.println("生产了 0.5t 龙井茶");}}

大型机器:

package com.xww.dp.factory;/*** 大型机器* * @author xww**/
public class BigMechineFactory implements TeaCompany {public BigMechineFactory() {}@Overridepublic void hongCha() {System.out.println("生产了 2.2t 红茶");}@Overridepublic void lvCha() {System.out.println("生产了 3.5t 绿茶");}@Overridepublic void baiCha() {System.out.println("生产了 2t 白茶");}@Overridepublic void longJing() {System.out.println("生产了 1.5t 龙井茶");}}

这样的话,每一台机器就拥有了制作茶叶的功能了,因为工厂模式规定,不能暴露对象的创建,通过一个接口的方式来指定要创建的对象,所以这里不能在外部直接 new 每一台机器了,而是通过一个 Factory 类来创建不同的机器。

package com.xww.dp.factory;/*** 工厂类,提供对象创建的方法* * @author xww**/
public class TeaFactory {// 私有化private TeaFactory() {}public static TeaCompany createTeaFractory(Mechine mechine) {switch (mechine) {case SmallMechine:return new SmallMechineFactory();case MiddleMechine:return new MiddleMechineFactory();case BigMechine:return new BigMechineFactory();}return null;}}

然后呢,我们的客户端就可以这样调用:

package com.xww.dp.factory;/*** 工厂模式 —— 简单工厂* * 有什么问题呢? 如果工厂引进新的机器,那么需要在 enum 里面加一个机器,还有添加一个类,修改两个地方。* * @author xww* @博客 ;https://blog.csdn.net/smile_running?t=1*/
public class SimpleFactoryClient {public static void main(String[] args) {TeaCompany company = TeaFactory.createTeaFractory(Mechine.SmallMechine);company.hongCha();company.lvCha();company.baiCha();company.longJing();}
}

通过传入不同的枚举 Mechine 制作茶叶的机器,就可以方便的切换对象。

好了,以上就是简单工厂的创建对象的方式。下面来看看一般的工厂方法如何进行修改,工厂方法呢,指的是每一种茶都代表一种产品,所谓一种产品,其就是一个类,一个类通常都是单一的职责,所以要对简单工厂的修改,也非常简单。

工厂方法写法

继续回到我们的茶厂,说到这个茶公司啊,由于营业了两三年,收益不错,老板对公司进行了规模升级,同时引入了新的一台超级机器,产量比之前的机器更大。

根据老板对公司的升级操作,我们的代码也要添加一台超级机器。不过这里不再使用简单工厂,而是运用工厂方法来写,代码与之间有差异,需要修改几处地方。

首先,TeaFactory 已经变成了接口的形式,这是一个巨大的变化,这里的返回值,就是我们的茶公司接口对象。

package com.xww.dp.factory;/*** 工厂类,提供对象创建的方法* * @author xww**/
public interface TeaFactory {TeaCompany createCompany();
}

接下来,为每一台机器创建一个实例对象:

package com.xww.dp.factory;/*** 小型机器创建* * @author xww**/
public class SmallMechineFactoryCreater implements TeaFactory {@Overridepublic TeaCompany createCompany() {return new SmallMechineFactory();}}
package com.xww.dp.factory;/*** 中型机器创建* * @author xww**/
public class MiddleMechineFactoryCreater implements TeaFactory {@Overridepublic TeaCompany createCompany() {return new MiddleMechineFactory();}}
package com.xww.dp.factory;/*** 大型机器创建* * @author xww**/
public class BigMechineFactoryCreater implements TeaFactory {@Overridepublic TeaCompany createCompany() {return new BigMechineFactory();}}

这一步骤主要目的:为了与 enum 进行解耦,因为我们在新加入的超级机器时,必定要在枚举类中加入新的代码,而且还有在创建对象的方法里面也要做出相应的添加,不仅修改了两处地方,而且违背了我们尽量不要去修改原有的代码,所以能别修改就尽量少修改。

那么把 TeaFactory 类改为接口的形式,无异于多了很多的实现类出来,比如上面的三个机器,就要多出三个类去实现这个接口,从而创建对象,工厂方法势必会多出很多类来。而刚刚我们提到老板引进了新的超级机器,所以用工厂方法至少避免了修改原有的代码,我们只需要新建一个类,实现 TeaFactory 接口即可:

package com.xww.dp.factory;/*** 超级机器创建* * @author xww**/
public class SuperMechineFactoryCreater implements TeaFactory {@Overridepublic TeaCompany createCompany() {return new SuperMechineFactory();}}

然后,客户端与要做出相应的变化。

package com.xww.dp.factory;/*** 简单工厂 - 每个工厂对应一个对象实例类* * @author xww**/
public class GerneralFactoryClient {public static void main(String[] args) {TeaFactory teaFactory = new MiddleMechineFactoryCreater();TeaCompany company = teaFactory.createCompany();company.hongCha();company.lvCha();company.baiCha();company.longJing();}
}

这样的话,我们就从简单工厂转变到工厂方法的写法了,而简单工厂用到的一个枚举类型,就不需要再使用了。工厂方法就是每一个工厂对应一个产品,它们之间的创建方式,都是通过接口来实现的。不过工厂方法也暴露了一个缺点,就是类太多了,就如上面一样,每引进一台机器就要创建一个新的类,那我引进几十台呢,我调用的时候都不知道要 new 哪一个类,几十个类根本不清楚要实例化哪一个工厂类,这就有点懵了,而且类越来越多的话更不好办,那么下面来看看抽象工厂如何解决这个问题。

抽象工厂写法

既然工厂模式有三种方式,那它必定有其存在的道理,工厂方法可以解决简单工厂对类的修改问题,而抽象工厂的出现也就是为了解决工厂方法类繁重的问题,我们并不知道要实例化的类有哪几个,这让我们怎么用。所以,抽象工厂就解决了这个问题,把类的创建隐藏起来,通过 static 方法让我们可以选择需要的工厂对象。

所以呢,代码又需要做大改动了,我们通过工厂方法创建的 4 个机器 FactoryCreater 类就不需要了,因为抽象工厂正是为了解决这个问题,那它们就没有必要存在了。因为少了这 4 个类,我们的 TeaFactory 要大改版,不再是 interface 类型,而是 class 类型,并且提供 static 方法给外部调用:

package com.xww.dp.factory;/*** 工厂类,提供对象创建的方法* * @author xww**/
public class TeaFactory {private static TeaCompany createCompany(Class<? extends TeaCompany> company) {try {return (TeaCompany) company.newInstance();} catch (Exception e) {e.printStackTrace();}return null;}public static TeaCompany createSmallMechineFactory() {return createCompany(SmallMechineFactory.class);}public static TeaCompany createMiddleMechineFactory() {return createCompany(MiddleMechineFactory.class);}public static TeaCompany createBigMechineFactory() {return createCompany(BigMechineFactory.class);}public static TeaCompany createSuperMechineFactory() {return createCompany(SuperMechineFactory.class);}}

这里通过类的反射拿到对象的实例,也没有用到枚举类型,在原来简单工厂的基础上稍微修改即可。然后是客户端的调用:

package com.xww.dp.factory;/*** 抽象工厂 —— 解决工厂方法类多的问题* * @author xww* @博客 : https://blog.csdn.net/smile_running?t=1*/
public class AbstractFactoryClient {public static void main(String[] args) {TeaCompany company = TeaFactory.createSuperMechineFactory();company.hongCha();company.lvCha();company.baiCha();company.longJing();}
}

看上去,是不是有点像 Java 线程池的创建方式呢,几种线程池的实例化,也用了工厂设计模式来提供对象的创建的,从而屏蔽了内部的实现代码和复杂的操作,工厂模式是一种创建对象较好的方式。

那么至此,工厂模式的三种方式都介绍完了,也是经常使用的一种设计模式,在源码中也有很多都利用这种设计模式来创建对象的。

【设计模式】工厂模式相关推荐

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

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

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

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

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

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

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

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

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

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

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

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

  7. java设计模式工厂模式_Java中的桥梁设计模式

    java设计模式工厂模式 Today we will look into Bridge Design Pattern in java. When we have interface hierarchi ...

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

    java设计模式工厂模式 Facade Design Pattern is one of the Structural design patterns (such as Adapter pattern ...

  9. 设计模式-工厂模式(学习)

    设计模式-工厂模式(学习) 在程序的世界里,就像射雕英雄传一样,我们的技能就像是武功一样,我们只有不断去学习练习才能有机会像郭靖一样成为"天下第一". 我认为技能和武功是很类似的, ...

  10. 设计模式-工厂模式的3中不同实现[JAVA]

    设计模式-工厂模式的3中不同实现[JAVA] 工厂模式简介 In Factory pattern, we create object without exposing the creation log ...

最新文章

  1. JW Player使用简介
  2. CentOS6.8 x86_64bit MySQL简单语句应用
  3. 线程中应该注意的问题
  4. pyhton3 适配器模式编写
  5. 图像的放大与缩小(2)——双线性插值放大与均值缩小
  6. shell脚本练习(12.8)
  7. 2、基于wsgiref模块DIY一个web框架
  8. 将网桥的配置写进去/etc/sysconfig/network-scripts/ifcfg-xxx
  9. android 绘图软件,安卓最强大的绘图软件 妙笔生花最新评测
  10. 软件测试 学习之路 html基础
  11. 年度总结 | 小小的年度大总结!太精辟!
  12. 扎克伯格夏威夷州大肆买地引发当地不满 被批搞“新殖民主义”
  13. vue使用过程中的一些问题
  14. webrtc java api_java – 使用WebSockets实现WebRTC信令
  15. 2. wordpress 友情链接的备份和导入
  16. 完美卸载SQL Server2014数据库
  17. Web前端工程师VS前端工程师,谁的薪资更上一筹?
  18. [FAQ06649] Latin输入法怎么默认勾选几种语言?
  19. 【云原生之Docker实战】使用Docker部署siyuan个人笔记系统
  20. Localize Folders and Reports

热门文章

  1. mysql的pom文件在哪_Maven中pom文件详解
  2. Linux云服务器安装可视化图形界面
  3. 计算机网络技术思维导图幕布全整理(附网页版链接)
  4. springboot系列(二十六):如何实现word模板单页导出?这你得会|超级详细,建议收藏
  5. mac上好用的压缩_Mac上好用的解压缩软件有哪些?推荐四款免费的mac解压缩工具...
  6. 如何从水经注万能地图下载器35款地图中选择合适的地图下载
  7. 2021年11款最佳的开源 Kubernetes 工具
  8. Mac数据图表软件|让你的论文数据更加直观漂亮
  9. 【信息论】信源与信源熵(一)
  10. 在标准宽带光纤上实现量子加密