设计模式总览及工厂模式详解
2.架构师内功心法之设计模式
2.1.课程目标
1、通过对本章内容的学习,了解设计模式的由来。
2、介绍设计模式能帮我们解决哪些问题。
3、剖析工厂模式的历史由来及应用场景。
2.2.内容定位
不用设计模式并非不可以,但是用好设计模式能帮助我们更好地解决实际问题,设计模式最重要的
是解耦。设计模式天天都在用,但自己却无感知。我们把设计模式作为一个专题,主要是学习设计模式
是如何总结经验的,把经验为自己所用。学设计模式也是锻炼将业务需求转换技术实现的一种非常有效
的方式。
2.3.回顾软件设计原则
设计原则 | 解释 |
---|---|
开闭原则 | 对扩展开放,对修改关闭 |
依赖倒置原则 | 通过抽象使各个类或者模块不相互影响,实现松耦合。 |
单一职责原则 | 一个类、接口、方法只做一件事。 |
接口隔离原则 | 尽量保证接口的纯洁性,客户端不应该依赖不需要的接口。 |
迪米特法则 | 又叫最少知道原则,一个类对其所依赖的类知道得越少越好。 |
里氏替换原则 | 子类可以扩展父类的功能但不能改变父类原有的功能。 |
合成复用原则 | 尽量使用对象组合、聚合,而不使用继承关系达到代码复用的目的。 |
2.4.设计模式总览
写出优雅的代码
更好地重构项目
经典框架都在用设计模式解决问题
Spring就是一个把设计模式用得淋漓尽致的经典框架,其实从类的命名就能看出来,我来一一列举:
设计模式名称 | 举例 |
---|---|
工厂模式 | BeanFactory |
装饰器模式 | BeanWrapper |
代理模式 | AopProxy |
委派模式 | DispatcherServlet |
策略模式 | HandlerMapping |
适配器模式 | HandlerAdapter |
模板模式 | JdbcTemplate |
观察者模式 | ContextLoaderListener |
我们的课程中,会围绕 Spring 的 IOC、AOP、MVC、JDBC
这样的思路展开,根据其设计类型来设计讲解顺序:
类型 | 名称 | 英文 |
---|---|---|
创建型模式 | 工厂模式 | Factory Pattern |
单例模式 | Singleton Pattern | |
原型模式 | Prototype Pattern | |
结构型模式 | 适配器模式 | Adapter Pattern |
装饰器模式 | Decorator Patter | |
代理模式 | Proxy Pattern | |
行为性模式 | 策略模式 | Strategy Pattern |
模板模式 | Template Pattern | |
委派模式 | Delegate Pattern | |
观察者模式 | Observer Pattern |
3.工厂模式详解
3.1.工厂模式的历史由来
原始社会自给自足(没有工厂)、农耕社会小作坊(简单工厂,民间酒
坊)、工业革命流水线(工厂方法,自产自销)、现代产业链代工厂(抽象工厂,富士康)
3.2.简单工厂模式
3.2.1.定义
简单工厂模式(Simple Factory Pattern)是指由一个工厂对象决定创建出哪一种产品类的实例,
但它不属于GOF 23种设计模式。简单工厂适用于工厂类负责创建的对象较少的场景,且客户端只需要
传入工厂类的参数,对于如何创建对象的逻辑不需要关心。
3.2.2.demo
public class SimpleFactoryTest {public static void main(String[] args) {CourseFactory factory = new CourseFactory();ICourse course = factory.create(JavaCourse.class);course.record();}
}public class JavaCourse implements ICourse {public void record() {System.out.println("录制Java课程");}
}public class CourseFactory {public ICourse create(Class<? extends ICourse> clazz){// 反射try {if (null != clazz) {return clazz.newInstance();}}catch (Exception e){e.printStackTrace();}return null;}
}
<img src="http://woshiamiaojiang.gitee.io/image-hosting/SimpleFactory.png" style="zoom: 50%;" />
3.2.3.源码
Calendar.getInstance()
LoggerFactory.getLogger()
简单工厂模式在 JDK 源码也是无处不在,现在我们来举个例子,例如 Calendar 类,看
Calendar.getInstance()方法,下面打开的是Calendar的具体创建类:
private static Calendar createCalendar(TimeZone zone,Locale aLocale){CalendarProvider provider =LocaleProviderAdapter.getAdapter(CalendarProvider.class, aLocale).getCalendarProvider();if (provider != null) {try {return provider.getInstance(zone, aLocale);} catch (IllegalArgumentException iae) {// fall back to the default instantiation}}Calendar cal = null;if (aLocale.hasExtensions()) {String caltype = aLocale.getUnicodeLocaleType("ca");if (caltype != null) {switch (caltype) {case "buddhist":cal = new BuddhistCalendar(zone, aLocale);break;case "japanese":cal = new JapaneseImperialCalendar(zone, aLocale);break;case "gregory":cal = new GregorianCalendar(zone, aLocale);break;}}}if (cal == null) {// If no known calendar type is explicitly specified,// perform the traditional way to create a Calendar:// create a BuddhistCalendar for th_TH locale,// a JapaneseImperialCalendar for ja_JP_JP locale, or// a GregorianCalendar for any other locales.// NOTE: The language, country and variant strings are interned.if (aLocale.getLanguage() == "th" && aLocale.getCountry() == "TH") {cal = new BuddhistCalendar(zone, aLocale);} else if (aLocale.getVariant() == "JP" && aLocale.getLanguage() == "ja"&& aLocale.getCountry() == "JP") {cal = new JapaneseImperialCalendar(zone, aLocale);} else {cal = new GregorianCalendar(zone, aLocale);}}return cal;}
还有一个大家经常使用的 logback,我们可以看到 LoggerFactory 中有多个重载的方法
getLogger():
public static Logger getLogger(String name) {ILoggerFactory iLoggerFactory = getILoggerFactory();return iLoggerFactory.getLogger(name);}public static Logger getLogger(Class clazz) {return getLogger(clazz.getName());}
3.2.4.优缺点
- 优点
- 简单
- 缺点
- 工厂类的职责相对过重,不易于扩展过于复杂的产品结构。
3.3.工厂方法模式
3.3.1.定义
工厂方法模式(Factory Method Pattern)是指定义一个创建对象的接口,但让实现这个接口的类
来决定实例化哪个类,工厂方法让类的实例化推迟到子类中进行。在工厂方法模式中用户只需要关心所
需产品对应的工厂,无须关心创建细节,而且加入新的产品符合开闭原则。
3.3.2.demo
public class FactoryMethodTest {public static void main(String[] args) {// Python课程工厂ICourseFactory factory = new PythonCourseFactory();ICourse course = factory.create();course.record();// Java课程工厂factory = new JavaCourseFactory();course = factory.create();course.record();}
}public class JavaCourseFactory implements ICourseFactory {public ICourse create() {return new JavaCourse();}
}public interface ICourseFactory {ICourse create();
}public class JavaCourse implements ICourse {public void record() {System.out.println("录制Java课程");}
}public interface ICourse {void record();
}
<img src="http://woshiamiaojiang.gitee.io/image-hosting/FactoryMethod.png" style="zoom: 50%;" />
3.3.3.源码
ApplicationContext就是工厂方法模式
再来看看logback中工厂方法模式的应用,看看类图就OK了:
<img src="http://woshiamiaojiang.gitee.io/image-hosting/FactoryMethod2.png" style="zoom: 50%;" />
3.3.4.优缺点
- 工厂方法适用于以下场景:
- 创建对象需要大量重复的代码。
- 客户端(应用层)不依赖于产品类实例如何被创建、实现等细节。
- 一个类通过其子类来指定创建哪个对象。
- 工厂方法也有缺点:
- 类的个数容易过多,增加复杂度。
- 增加了系统的抽象性和理解难度。
3.4.抽象工厂模式
3.4.1.定义
抽象工厂模式(AbastractFactory Pattern)是指提供一个创建一系列相关或相互依赖对象的接口,无须指定他们具体的类。客户端(应用层)不依赖于产品类实例如何被创建、实现等细节,强调的是一
系列相关的产品对象(属于同一产品族)一起使用创建对象需要大量重复的代码。需要提供一个产品类
的库,所有的产品以同样的接口出现,从而使客户端不依赖于具体实现。
讲解抽象工厂之前,我们要了解两个概念产品等级结构和产品族,看下面的图:
<img src="http://woshiamiaojiang.gitee.io/image-hosting/image-20200225191403439.png" alt="image-20200225191403439" style="zoom:50%;" />
从上图中看出有正方形,圆形和菱形三种图形,相同颜色深浅的就代表同一个产品族,相同形状的代表
同一个产品等级结构。同样可以从生活中来举例,比如,美的电器生产多种家用电器。那么上图中,颜
色最深的正方形就代表美的洗衣机、颜色最深的圆形代表美的空调、颜色最深的菱形代表美的热水器,
颜色最深的一排都属于美的品牌,都是美的电器这个产品族。再看最右侧的菱形,颜色最深的我们指定
了代表美的热水器,那么第二排颜色稍微浅一点的菱形,代表海信的热水器。同理,同一产品结构下还
有格力热水器,格力空调,格力洗衣机。
再看下面的这张图,最左侧的小房子我们就认为具体的工厂,有美的工厂,有海信工厂,有格力工厂。
每个品牌的工厂都生产洗衣机、热水器和空调。
<img src="http://woshiamiaojiang.gitee.io/image-hosting/image-20200225191741688.png" alt="image-20200225191741688" style="zoom:50%;" />
3.4.2.demo
public class AbstractFactoryTest {public static void main(String[] args) {JavaCourseFactory factory = new JavaCourseFactory();factory.createNote().edit();factory.createVideo().record();}
}/*** 抽象工厂CourseFactory类:* 抽象工厂是用户的主入口* 在Spring中应用得最为广泛的一种设计模式* 易于扩展*/
public abstract class CourseFactory {public void init(){System.out.println("初始化基础数据");}protected abstract INote createNote();protected abstract IVideo createVideo();
}/*** 创建Java产品族的具体工厂JavaCourseFactory*/
public class JavaCourseFactory extends CourseFactory {public INote createNote() {super.init();return new JavaNote();}public IVideo createVideo() {super.init();return new JavaVideo();}
}/*** 创建Java产品族,Java视频JavaVideo类:Java视频*/
public class JavaVideo implements IVideo {public void record() {System.out.println("录制Java视频");}
}/*** 录播视频:IVideo接口*/
public interface IVideo {void record();
}/*** 扩展产品等级Java课堂笔记JavaNote类:Java笔记*/
public class JavaNote implements INote {public void edit() {System.out.println("编写Java笔记");}
}/*** 课堂笔记:INote接口*/
public interface INote {void edit();
}// 创建Python产品族的具体工厂PythonCourseFactory省略。。。
<img src="http://woshiamiaojiang.gitee.io/image-hosting/AbstractFactory.png" style="zoom: 33%;" />
上面的代码完整地描述了两个产品族Java课程和Python课程,也描述了两个产品等级视频和手记。抽象工厂非常完美清晰地描述这样一层复杂的关系。但是,不知道大家有没有发现,如果我们再继续扩展
产品等级,将源码 Source也加入到课程中,那么我们的代码从抽象工厂,到具体工厂要全部调整,很显然不符合开闭原则。
3.4.3.源码
AbstractFactory
AnnotationApplicationContext
Xml
适合长时间不变动的场景
3.4.3.优缺点
抽象工厂缺点
- 规定了所有可能被创建的产品集合,产品族中扩展新的产品困难,需要修改抽象工厂的接口。
- 增加了系统的抽象性和理解难度。
3.5.简单工厂 vs 工厂方法 vs 抽象工厂
简单工厂:产品的工厂
工厂方法:工厂的工厂
抽象工厂:复杂产品的工厂
简单工厂:工厂是一个实体类,内部直接根据逻辑创建对应的产品。
工厂方法:工厂首先有个接口定义规范。不同的产品使用不同的实体类工厂根据规范和需求创建对应的产品。这就是它们的区别。
工厂方法是生产一类产品,抽象工厂是生产一个产品族
3.6.作业
1、工厂类一定需要将构造方法私有化吗,为什么?
不一定。抽象工厂类就不能,否则父类的私有构造方法就不能被子类调用。
2、用工厂模式设计支付业务场景,包含跨境支付,支付宝、微信、银联支付,并画出类图。
/*** description: 支付接口*/
public interface IPay {/*** 支付方法*/void pay();
}/*** description: 支付宝支付*/
public class AliPay implements IPay {public void pay() {System.out.println("支付宝支付");}
}/*** description: 微信支付*/
public class WxPay implements IPay {public void pay() {System.out.println("微信支付");}
}/*** description: 银联支付*/
public class UniPay implements IPay {public void pay() {System.out.println("银联支付");}
}/*** description: 苹果支付*/
public class ApplePay implements IPay {public void pay() {System.out.println("苹果支付");}
}/*** description: 支付抽象工厂*/
public abstract class AbstractPayFactory {public void init() {System.out.println("初始化基础数据");}
}/*** description: 国内支付*/
public class ChinaPayFactory extends AbstractPayFactory {protected IPay createAliPay() {super.init();return new AliPay();}protected IPay createWxPay() {super.init();return new WxPay();}protected IPay createUniPay() {super.init();return new UniPay();}
}/*** description: 国外支付*/
public class ForeignPayFactory extends AbstractPayFactory {protected IPay createApplePay() {super.init();return new ApplePay();}
}/*** description: 抽象工厂方法测试*/
public class AbstractPayFactoryTest {public static void main(String[] args) {ChinaPayFactory chinaPayFactory = new ChinaPayFactory();chinaPayFactory.createAliPay().pay();chinaPayFactory.createWxPay().pay();chinaPayFactory.createUniPay().pay();ForeignPayFactory foreignPayFactory = new ForeignPayFactory();foreignPayFactory.createApplePay().pay();}
}
设计模式总览及工厂模式详解相关推荐
- getinstance方法详解_二、设计模式总览及工厂模式详解
二.架构师内功心法之设计模式 2.架构师内功心法之设计模式 2.1.课程目标 1.通过对本章内容的学习,了解设计模式的由来. 2.介绍设计模式能帮我们解决哪些问题. 3.剖析工厂模式的历史由来及应用场 ...
- java工厂模式静态工厂_Java设计模式之静态工厂模式详解
本文实例讲述了Java设计模式之静态工厂模式.分享给大家供大家参考,具体如下: 静态工厂模式(static factory)也叫简单工厂模式. 涉及到3个角色:工厂类角色,抽象产品类角色和具体产品类角 ...
- 设计模式之游戏--工厂模式详解
工厂模式 一.简单工厂模式 二.工厂方法模式 三.抽象工厂模式 使用总结 引入问题:在面向对象编程中,创建一个对象的最常用的方法是new一个对象实例,new对象操作符就是用来构造对象实例的,但是在一些 ...
- 23种设计模式之简单工厂模式,工厂方法模式,抽象工厂模式详解
工厂模式详解 1. 简单工厂模式 1.1 需求分析 1.2 使用传统方式实现 1.2.1 类图 1.2.2 代码实现 1.2.2.1 新建pizza抽象类 1.2.2.2 希腊披萨实现类 1.2.2. ...
- 设计模式之工厂模式详解(附应用举例实现)
文章目录 1 工厂模式介绍 2 工厂模式详解 2.1 简单工厂模式 2.1.1 简单工厂模式结构 2.1.2 简单工厂模式实现 2.1.3 简单工厂模式应用举例 2.2 工厂方法模式 2.2.1 工厂 ...
- 走穿java23种设计模式-15责任链模式详解
走穿java23种设计模式-15责任链模式详解 责任链模式是一种常见的行为模式. 一.责任链模式的现实场景 习伟过生日邀请了很多朋友到KTV一起庆祝,为了增加欢乐的气氛,习伟建议大家一起玩击鼓传花的游 ...
- 设计模式之享元模式详解
设计模式之享元模式详解 概述 享元模式定义: 运用共享技术来有效地支持大量细粒度对象的复用.它==通过共享已经存在的对象来大幅度减少需要创建的对象数量==.避免大量相似对象的开销,从而提高系统资源 ...
- C++简单工厂模式详解
C++简单工厂模式详解 1.问题引入 2.编写代码思路的迭代 2.1 main函数主体内编写全部代码 2.2 修改上述问题后的main函数代码 2.3 引入面向对象后的代码 2.4 加上继承和多态后的 ...
- 走穿java23种设计模式--18中介者模式详解
走穿java23种设计模式–18中介者模式详解 中介者模式也称调停者模式,是一种比较简单的模式. 一.中介者模式的现实场景 蔡良因为上次表白时对方只看重他的物质方面,所以他对女朋友这个问题有点失望.因 ...
- 设计模式之装饰器模式详解
设计模式之装饰器模式详解 文章目录 设计模式之装饰器模式详解 一.什么是装饰器模式 二.装饰器模式的角色组成 三.装饰器模式通用写法示例 四.装饰器模式业务中的应用举例 五.装饰器模式优缺点 一.什么 ...
最新文章
- stm32对c语言要求高吗?c语言什么水平可以学stm32?
- JGG:青岛大学苏晓泉团队利用条件致病菌指数评估环境微生物风险
- loj #6053 简单的函数 min_25筛
- ckeditor上传图片文件,研究了一天,终于...
- bootstrap-关闭按钮
- linux删去分区的文件夹,如何恢复 Linux 分区下误删的文件?
- 如何快速安全的插入千万条数据?
- 大学计算机spoc长安大学答案,2018春C语言程序设计 上(长安大学)
- 存储过程或视图的字符串查询
- MIT-JOS系列1:实模式和保护模式下的段寻址方式
- I.MX6 Surfaceflinger 机制
- asic面试题目 英伟达_免笔试!不限量!全球可编程图形处理技术领袖英伟达2021校园招聘火热进行中!...
- 被苹果摆了一道的高通,亮出了一张“小米”牌
- 5. DOM解析XML
- Loadrunner11 下载、安装及破解
- 2010.04.20 工作之路 - 明源軟件科技
- 彩球滑梯java_玩过这些手机游戏的人都老了 那些曾经风靡一时的手机游戏大盘点(二)...
- U大师U盘装系统——启动U盘制作(V1.2.0版)
- 有三类人永远做不了程序员
- CAD高版本转低版本的方法有哪些?