设计模式之工厂模式(三)
上一次我们已经通过代码,简单的认识了工厂方法模式,具体的思路请移步到设计模式之工厂模式(二),进行查看。这次,让我们通过设计模式的思想,来好好认识下工厂方法模式。
创建者和产品
所有工厂模式都用来封装对象的创建。工厂方法模式(Factory Method Pattern)通过让子类决定该创建的对象是什么,来达到将对象创建的过程封装的目的。让我们来看看这些类图,以了解有哪些组成元素:
另一个观点:平行的类层级
上面已经看到,将一个orderPizza()方法和一个工厂方法联合起来,就可以成为一个框架。除此之外,工厂方法将生产知识封装进各个创建者,这样的做法,也可以被视为是一个框架。
让我们来看看这两个平行的类层级,并认清它们的关系:
定义工厂方法模式
工厂方法模式定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。
工厂方法模式能够封装具体类型的实例化。看下面的类图,抽象的Creator提供了一个创建对象的方法的接口,也称为“工厂方法”。在抽象的Creator中,任何其他实现的方法,都可能使用到这个工厂方法所制造出来的产品,但只有子类真正实现这个工厂方法并创建产品。
对象依赖
假设你从未听过工厂模式,那么按照之前的,如果要开一家纽约和芝加哥的披萨店,并且有各种风味的披萨对象,你是否可以想象这个类所以来的具体披萨对象有几种呢?如果又增加了一种加州风味,又会有依赖多少个对象呢?不妨让你看看:
public lass DependentPizzaStore {public Pizza createPizza(String style, String type) {Pizza pizza = null;if(style.equals("NY")) {if(type.equals("cheese")) {pizza = new NYStyleCheesePizza();} else if(tpye.equals("clam")) {pizza = new NYStyleClamPizza();} else if(type.equals("pepperoni")) {pizza = new NYStylePrpperoniPizza();}} else if(style.equals("Chicago")) {if(type.equals("cheese")) {pizza = new ChicagoStyleCheesePizza();} else if(tpye.equals("clam")) {pizza = new ChicagoStyleClamPizza();} else if(type.equals("pepperoni")) {pizza = new ChicagoStylePrpperoniPizza();}} else {System.out.println("Error: invalid type of pizza");return null;}}
}
复制代码
当你直接实例化一个对象时,就是在依赖它的具体类。如果把这个版本的披萨店和它的依赖对象画成一张画,看起来是这样的:
依赖倒置原则
从上面看到了,我们代码里减少对于具体类的依赖是一件好事。事实上,有一个OO设计原则就正式阐明了这一点;这个原则甚至还有一个又响亮又正式的名称:“依赖倒置原则”。要依赖抽象,不要依赖具体类。
这个原则和“针对接口编程,不针对实现编程”类似,但是这个原则,更强调“抽象”。这个原则说明了:不能让高层组件依赖低层组件,而且,不管高层或低层组件,“两者”都应该依赖于抽象。
所谓“高层”组件, 是是由其他低层组件定义行为的类。例如,PizzaStore是个高层组件,因为他的行为是由披萨定义的;PizzaStore创建所有不同的披萨对象,准备、烘烤、切片、装盒;而披萨本身属于低层组件。PizzaStore依赖这些具体披萨类。
原则的应用
非常依赖披萨店的主要问题在于:它依赖每个披萨类型。因为它是在自己的orderPizza()方法中,实例化这些具体类型的。
如何在orderPizza()方法中,将这些实例化对象的代码独立出来?我们都知道,工厂方法刚好派上用场了。应用了工厂方法之后,类图就改成了下面这个样子:
在应用工厂方法之后,你注意到了没,高层组件(PizzaStore)和低层组件(也就是这些披萨)都依赖了Pizza抽象。想要遵循依赖倒置原则,工厂方法并非是唯一的技巧,但却是最有威力的技巧之一了。
依赖倒置,究竟倒置在哪里?
在依赖倒置原则中的倒置指的是和一般OO设计的思考方式相反。看看上面的图,你会注意到低层组件现在竟然依赖高层的抽象。同样地,高层组件现在也依赖相同的抽象。以前绘制的依赖图都是自上而下的,现在却倒置了,而且高层和低层模块现在都依赖这个抽象。
依赖倒置,还需要倒置你的思考方式。之前如果你需要设计一个披萨店,会从顶端开始,然后往下到具体类。现在就需要倒置你的想法,别从顶端开始,而是从披萨开始,然后想到抽象化一个Pizza类。继而想到必须要靠一个工厂来将这些类取出披萨店,不同的披萨类型都只能依赖一个抽象,同样的披萨店也会依赖这个抽象。
就这样,我们倒置了一个商店依赖具体类的设计,而且也倒置了你的思考方式。但是,也需要避免在OO设计中违反依赖倒置原则:
- 变量不可以持有具体类的引用:如果使用new,就会持有具体类的引用。你可以改用工厂来避开这样的做法
- 不要让类派生自具体类:如果派生自具体类,你就会依赖具体类。请派生自一个抽象(接口或抽象类)
- 不要覆盖基类中已实现的方法:如果覆盖基类已实现的方法,那么你的基类就不是一个真正适合被继承的抽象。基类中已实现的方法,应该由所有的子类共享
所以,这篇我们就在这里结束了。为什么呢,因为在下一篇,我们需要遵循这个设计原则,重新来整理整理我们的披萨店。我们要让披萨店的设计变得更棒:具有弹性的框架,而且遵循设计原则。这篇偏向理论知识了,请各位好好理解理解,看看创建者和产品类,看看依赖倒置原则,我们下篇再见咯。
爱生活,爱学习,爱感悟,爱挨踢
转载于:https://juejin.im/post/5cbd42956fb9a032060c2615
设计模式之工厂模式(三)相关推荐
- JavaScript设计模式--简单工厂模式例子---XHR工厂
JavaScript设计模式--简单工厂模式例子---XHR工厂 第一步,Ajax操作接口(目的是起一个接口检测作用) (1)引入接口文件 //定义一个静态方法来实现接口与实现类的直接检验 //静态方 ...
- 三角形圆形创建与擦除java_设计模式---------------简单工厂模式
设计模式---------------简单工厂模式 一.题目(Question) 使用简单工厂模式设计一个可以创建不同几何形状(如圆形.方形和三角形等)的绘图工具,每个几何图形都要有绘制draw()和 ...
- Java 设计模式之工厂模式(二)
原文地址:Java 设计模式之工厂模式(二) 博客地址:http://www.extlight.com 一.背景 本篇内容是 Java 设计模式创建型模式的第二篇.上一篇主题为 <Java 设计 ...
- php工厂模式和单例模式,php 设计模式之工厂模式、单例模式、注册树模式
php 设计模式之工厂模式.单例模式.注册树模式 在软件工程中,创建型设计模式承担着对象创建的职责,尝试创建适合程序上下文的对象,对象创建设计模式的产生是由于软件工程设计的问题,具体说是向设计中增加复 ...
- 教你如何一篇博客读懂设计模式之—--工厂模式
一篇博客读懂设计模式之-工厂模式 工厂模式在我们日常开发的时候经常用到,相信大家都有了一定的了解,工厂模式是一种创建对象的设计模式,它提供一种创建对象的最佳方式. 主要过程是: 定义一个创建对象的接口 ...
- 系统架构技能之设计模式-抽象工厂模式
一.上篇回顾 上篇我们主要讲述了简单工厂模式和工厂模式.并且分析了每种模式的应用场景和一些优缺点,我们现在来回顾一下: 简单工厂模式:一个工厂负责所有类型对象的创建,不支持无缝的新增新的类型对象的创建 ...
- java设计模式之工厂模式(UML类图分析+代码详解)
大家好,我是一名在算法之路上不断前进的小小程序猿!体会算法之美,领悟算法的智慧~ 希望各位博友走过路过可以给我点个免费的赞,你们的支持是我不断前进的动力!! 加油吧!未来可期!! 本文将介绍java设 ...
- java 设计模式 路由器_java设计模式2————工厂模式
java设计模式2----工厂模式 1.工厂模式介绍: 1.1.实现了创建者与调用者的分离 1.2.详细分类: 简单工厂模式 工厂方法模式 抽象工厂模式 1.3.所遵循的OOP原则: 开闭原则:对扩展 ...
- 设计模式之工厂模式(Factory)
设计模式之工厂模式 设计模式之工厂模式 简介 代码准备 需求一 需求二 简单工厂 工厂方法 抽象工厂 需求三 总结 设计模式之工厂模式 简介 工厂顾名思义就是创建产品,根据产品是具体产品还是具体工厂可 ...
最新文章
- vue渲染大量数据如何优化_Vue3 Compiler 优化细节,如何手写高性能渲染函数
- C语言-数组名真的不是指针
- centos7已有数据硬盘挂载_实战2T以上盘GPT分区工具使用挂载教程
- POJ 2342 (树形DP)
- 多种时间格式字符串转换为Date对象
- IDirect3DDevice9::SetClipPlane
- ubuntu 安装 最新 PyMOL [源码安装][免费]
- linux gns3使用教程,Linux下GNS3报错解决方法
- 整个社会总嫌自己不够“快”,为啥?
- Intellij如何把JAR包加入到项目运行环境中
- 鸿蒙os 实测,鸿蒙体验怎么样_鸿蒙OS实测体验
- 自定义Xshell高亮
- Apache Http Server安全漏洞解决
- dcos 1.7 安装
- pyhton 将ASCII码转换为字符char(),将字符转换为ASCII码ord()
- 从技术 Leader 的招聘需求看,如何转岗为当前紧缺的大数据相关人才?
- android 自定义音量调节,Android——自定义音量调节控件
- 微信企业号开发—通讯录
- H323加载H264插件时出现找不到dll文件问题解决
- 详解Unity中的粒子系统Particle System (六)
热门文章
- python字符编码
- React Native移动开发实战-4-Android平台的适配
- 《写给大家看的设计书:实例与创意(修订版)》—1你已经知道多少了?
- 【博客美化】08.添加扩大/缩小浏览区域大小 按钮
- MYSQL的索引类型:PRIMARY, INDEX,UNIQUE,FULLTEXT,SPAIAL 有什么区别?各适用于什么场合?...
- 【百度地图API】暑假放假回老家——城市切换功能
- ubuntu 12.10 php55安装过程
- Ubuntu 10.04 lucid 安装 MariaDB 5.5
- 迷你图标集大集合:5000+ 30套免费的图标
- 微软将迎来迄今最大补丁日 一次修补49个漏洞