一、简单工厂模式

简单工厂模式也被称为静态工厂模式,它是指由一个工厂对象决定创建哪一种产品的实例。
简单举个例子,在原始社会,我们需要自给自足。在工业革命之后,世界上出现了各种各样的代工厂、流水线,人们只需要买来需要的产品,并且知道如何使用就行了。那么简单工厂模式也是如此,它可以将产品的使用和生产完全分开,客户端只需要知道需要什么产品,如何来使用产品的就可以了,而具体的产品生产任务由具体的工厂类来实现。
在现实的工厂中,如果大量的、多种类型的产品都在一个工厂生产,会造成工厂负担过重、效率变低,且不利于工厂的管理。所以,简单工厂模式适用于工厂类负责创建的对象较少的场景,且客户端只需要传入工厂类的参数,对于如何创建对象不需要关心。
举例
以计算机专业的学生课程为例,计算机专业的学生要学习Java课程。我们先定义Course接口:

public interface Course {void getCourse();
}

创建一个Java课程的实现类javaCourse类:

public class JavaCourse implements Course{@Overridepublic void getCourse() {System.out.println("Java课程");}
}

客户端调用代码:

    public static void main(String[] args) {Course course = new JavaCourse();course.getCourse();}

在上面的代码中,父类Course指向子类JavaCourse的引用,应用层代码需要依赖JavaCourse。如果业务要进行扩展,学生要学习python、前端、大数据等课程,那么客户端的依赖就会变得越来越臃肿。因此,我们要想办法把这种依赖减弱,把创建细节隐藏起来。虽然在目前的代码中,创建对象的过程并不复杂,但从代码设计的角度来讲不易于扩展。现在,我们用简单工厂模式对代码进行优化。增加课程类PythonCourse:

public class PythonCourse implements Course {@Overridepublic void getCourse() {System.out.println("Python课程");}
}

创建工厂类CourseFactory:

public class CourseFactory {public static Course create(String name){if("java".equals(name)){return new JavaCourse();} else if("python".equals(name)){return new PythonCourse();} else{return null;}}
}

修改客户端调用代码如下:

    public static void main(String[] args) {JavaCourse course = (JavaCourse) CourseFactory.create("java");}

可以明显的看出,客户端的调用变简单了,只需要去向工厂去索求,而不需要自己实现创建的细节。但是如果未来还开设了其它课程,我们还需要根据要求来修改代码逻辑,不符合开闭原则,因此我们可以用反射技术继续优化我们的程序,这里就不再赘述。
简单工厂模式也有缺点:工厂类的职责相对过重,不易与扩展过于复杂的产品结构,只适用于工厂类负责创建的对象较少的场景。

二、工厂方法模式

工厂方法模式是指定义一个创建对象的接口,让这个接口的实现类负责创建具体的对象,工厂方法模式是简单工厂模式的进一步抽象和推广,它让类的实例化推迟到子类中进行。工厂方法模式使用了多态性,即保持了简单工厂模式的优点,又克服了它的缺点。在工厂方法模式中,用户只需要关心所需产品对应的工厂,无需关心创建细节,而且加入新的产品时符合开闭原则。
工厂方法模式主要解决了产品的扩展问题。在简单工厂模式中,随着产品链的丰富,如果每个课程的创建逻辑有区别,则工厂的职责会变得越来越多,有点像万能工厂,不便于维护。根据单一职责原则,我们将只能继续拆分,专门的工厂干专门的事。我们令Java课程由Java工厂创建,Python课程由Python工厂创建,对工厂本身也做一个抽象。来看代码,先创建CourseFactory接口:

public interface CourseFactory {Course create();
}

再分别创建子工厂,JavaCourseFactory类的代码如下:

public class JavaCourseFactory implements CourseFactory{@Overridepublic Course create() {return new JavaCourse();}
}

PythonCourseFactory类的代码如下:

public class PythonCourseFactory implements CourseFactory{@Overridepublic Course create() {return new PythonCourse();}
}

测试代码:

    public static void main(String[] args) {CourseFactory factory = new JavaCourseFactory();Course course = factory.create();course.getCourse();factory = new PythonCourseFactory();course = factory.create();course.getCourse();}

工厂方法模式适用于以下场景:

  1. 创建对象需要大量重复的代码
  2. 客户端(应用层)不依赖于产品类实例如何被创建、如何被实现等
  3. 一个类通过其子类来指定创建哪个对象

工厂方法模式也有缺点:

  1. 类的个数容易过多,增加复杂度
  2. 增加了系统的抽象性和理解难度
  3. 一个具体工厂只能创建一个具体的产品,虽然说解决了对工厂方法内的修改关闭,如果换一个产品的话也是需要修改具体的产品类。

三、抽象工厂模式

抽象工厂模式是指提供一个创建一系列相关或相互依赖的接口,无需指定它们的具体类。客户端(应用层)不依赖于产品类实例如何被创建、何如被实现等细节,强调的是一些列相关的产品对象(属于同一产品族)一起使用创建对象需要大量重复的代码,需要提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于具体实现。
在了解抽象工厂模式之前,我们先要了解一下产品组的概念:
产品族是指位于不同产品等级结构中,功能相关联的产品组成的家族。一般是位于不同的等级结构中的相同位置上。
仍以课程为例,现在学校有了新的标准,学生不仅可以获取到课程,还可以获取到图书资源。如果使用工厂方法模式,

如图所示,每个产品都要对应一个工厂。这本都是一个课程系列的产品,却要分成两个工厂来生产,这显然是没有必要的操作。
如果我们使用抽象工厂模式呢?

可以看出,一系列的产品只需要一个工厂去生产,更加符合我们的要求,减少了程序的负担。
Course接口如下:

public interface Course {void getCourse();
}

Book代码如下:

public interface Book {void getBook();
}

然后创建一个抽象工厂类CourseFactory:

public interface CourseFactory {Course createCourse();Book createBook();
}

接下来创建Java产品族的Java课程类javaCourse:

public class JavaCourse implements Course{@Overridepublic void getCourse() {System.out.println("Java Course");}
}

扩展产品等级Java图书资源类JavaBook:

public class JavaBook implements Book{@Overridepublic void getBook() {System.out.println("Java Book");}
}

创建Java产品族的具体工厂JavaCourseFactory:

public class JavaCourseFactory implements CourseFactory{@Overridepublic Course createCourse() {return new JavaCourse();}@Overridepublic Book createBook() {return new JavaBook();}
}

然后创建Python产品的Python课程类PythonCourse:

public class PythonCourse implements Course{@Overridepublic void getCourse() {System.out.println("Python Course");}
}

扩展产品等级Python图书资源类PythonBook:

public class PythonBook implements Book{@Overridepublic void getBook() {System.out.println("Python Book");}
}

创建Python产品族的具体工厂PythonCourseFactory:

public class PythonCourseFactory implements CourseFactory{@Overridepublic Course createCourse() {return new PythonCourse();}@Overridepublic Book createBook() {return new JavaBook();}
}

调用代码:

    public static void main(String[] args) {JavaCourseFactory factory = new JavaCourseFactory();factory.createCourse().getCourse();factory.createBook().getBook();}

上面的代码完整地描述了两个产品族:Java课程和Python课程,也描述了两个产品等级:课程资源和图书资源。抽象工厂模式非常完美清晰地描述了这样一层复杂的关系。但是,不知道大家有没有发现,如果我们再继续扩展产品等级,将源码Source也加入课程,那么我们的代码从抽象工厂到具体都要全部调整,很显然不符合开闭原则,由此可知抽象工厂模式也有缺点的:

  1. 规定了所有可能被创建的产品集合,产品族中扩展新的产品困难,需要修改抽象工厂的接口。
  2. 增加了系统的抽象性和理解难度。

总结

从上文来看,工厂模式好像也没有所说的那么晦涩难懂,从本文的角度来看确实如此。但是实际上,我认为工厂模式还是比较复杂的。在本文中,介绍了每种工厂模式的优缺点,那么在现实开发中,如何做到“取其精华,舍弃糟粕”呢?怎么才能做到像SpringIOC容器一样,功能强大且使用便捷呢?
在实际应用中,我们千万不能“犯强迫症”甚至“有洁癖”。在实际需求中,产品等级结构升级是非常正常的一件事情。只要不频繁升级,根据实际情况可以不遵循开闭原则。代码每半年升级一次或者每年升级一次又有何不可呢?我们要知道,原则可以帮我们较少不必要的麻烦,但必要的更新与升级缺一不可。

文章参考于《Spring5核心原理与30个类手写实战》谭勇德 著

Spring中常用的设计模式——工厂模式相关推荐

  1. 学习笔记【Spring中常用的设计模式】

    文章目录 简介 一. Spring用到的设计模式类别 1. 创建型模式 2. 结构性模式 3. 行为型模式 二. 设计模式详解 1. 工厂模式 1.1 简单工厂模式 1.2 工厂方法模式 1.3 抽象 ...

  2. 六大常用软件设计模式—工厂模式

    当当当当~~~~欢迎大家阅读,今天我们学习六大常用软件设计模式中的工厂模式​​​​​​​ 工厂模式 (Factory Pattern) 一:工厂模式的定义 就是建立一个工厂类,对实现了同一接口的一些类 ...

  3. Spring 中常用的设计模式对比

    各设计模式对比及编程思想总结 设计模式 一句话归纳 举例 工厂模式(Factory) 只对结果负责,封装创建过程. BeanFactory.Calender 单例模式(Singleton) 保证独一无 ...

  4. Spring中常见的设计模式

    Spring中常见的设计模式 1.Java设计模式 设计模式(Design Pattern)是解决特定问题的一系列套路.它不是语法规定,而是一套用来提高代码可复用性.可维护性.可读性.稳健性以及安全性 ...

  5. Spring中的部分设计模式

    目录: 目录 设计模式在应用中遵循六大原则: a.开闭原则 b.里氏代换原则 c.依赖倒转原则 d.接口隔离原则 e.迪米特法则(最少知道原则) f.合成复用原则 设计模式之间的关系图 1.工厂模式( ...

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

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

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

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

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

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

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

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

最新文章

  1. 2015.11.11
  2. 设置更改root密码(远程,本地)、连接mysql、mysql常用命令
  3. 第十六届智能车竞赛线上全国总决赛远程组委会监督腾讯会议
  4. 中兴通讯与寒武纪合作 加速5G时代边缘智能
  5. 宝塔无法安装php memcached,宝塔面板安装Memcached缓存加速wordpress
  6. SAP License:SAP合同类型的使用
  7. Matlab读取图像数据并写入TXT
  8. 针对使用ng-lint,eslint,tslint,生成报告以及环境安装的一系列问题及解决办法
  9. 《微积分:极限与连续》——连续的两种定义
  10. ASP.NET的六大对象介绍
  11. nodejs开发环境安装-连载【1】-企业级系统开发实战连载系列 -技术栈 :vue、element-ui、qt、c++、sqlite
  12. 牵一只蜗牛去散步……
  13. [小作品]小小梦想初级物理摸拟系统
  14. 利用MATLAB求解积分
  15. 你若运行,便是晴天!
  16. matlab直观数据处理,霍尔效应实验的MATLAB数据处理
  17. Visual Studio 2015 Bowser Link的功能不停的向服务端发送请求
  18. matlab 怎么使用mathtype,教你怎样在Authorea里面使用MathType
  19. 微型计算机2019年度金奖产品,【MC 2019年度评选获奖产品展播】华硕/ROG DIY精品斩获多个大奖...
  20. 拆长虹iho3000_(CA版)四川长虹iho-3000t晶晨s905l-b刷全网通系统教程可救砖头

热门文章

  1. 为Linux部署红旗紫光输入法
  2. 毕业设计-基于深度学习的数字病理图像分割
  3. 物联网卡系统php,物联网卡开发文案
  4. 移动端浏览器触摸事件@touchstart=“touchstart“ @touchend=“touchend“ @touchmove=“touchmove“
  5. 移动web开发 手机输入框弹出的问题
  6. MATLAB求解方程和多元方程组
  7. 贴吧顶贴php脚步,【技术贴安卓按键精灵】贴吧顶贴脚本源码分享
  8. 推荐一款开源的音乐下载神器,8个平台VIP任你选
  9. 游戏中的答题活动也可以通过远程代答么?
  10. 【开发工具】【JTAG】JTAG基础【一】