Java常用设计模式————工厂模式

简介:

工厂模式(Factory Pattern)是Java中最常用的设计模式之一,又称多态工厂模式、虚拟构造器模式。属于创建型模式。

在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。

主要作用:

将类的实例化(具体产品的创建)延迟到工厂类的子类(具体工厂)中完成,即由子类来决定应该实例化那一个类。

应用场景:

1.在编码时无法预见创建哪种类的实例。

2.系统不应依赖于产品类实例如何被创建、组合和表达的细节。

解决问题:

在简单工厂模式中,存在着一个重要的缺陷:工厂一旦需要生产新产品就需要修改工厂类的方法逻辑,违背了OCP原则(Open Closed Principle)。因此为了解决这一问题,工厂方法模式把具体产品的创建推迟到工厂类的子类(具体工厂)中,此时工厂类不再负责所有产品的创建,而只是给出具体工厂必须实现的接口,这样工厂方法模式在添加新产品的时候就不修改工厂类逻辑而是添加新的工厂子类,符合开闭原则,克服了简单工厂模式中的缺点。

实现步骤:

第一步:创建产品接口

package design.pattern.factory1;
/*** 抽象的产品类别* <br>类名:Car<br>* 作者: mht<br>* 日期: 2018年3月20日-下午11:41:50<br>*/
public interface Car {/** 跑*/public void run();/** 漂移*/public void dift();}

第二步:根据业务需要创建具体产品类:产品A产品B实现产品接口

package design.pattern.factory1;/*** 卡车类:实现车接口的具体车类* <br>类名:Truck<br>* 作者: mht<br>* 日期: 2018年3月20日-下午11:45:03<br>*/
public class Truck implements Car{@Overridepublic void run() {System.out.println("卡车跑...");}@Overridepublic void dift() {System.out.println("卡车漂移...不作不死...");}}
package design.pattern.factory1;/*** 公交车:实现车类的具体车类* <br>类名:Bus<br>* 作者: mht<br>* 日期: 2018年3月21日-上午8:24:19<br>*/
public class Bus implements Car{@Overridepublic void run() {System.out.println("公交车跑...");}@Overridepublic void dift() {System.out.println("公交车漂移...不作不死!");}}
package design.pattern.factory1;/*** 轿车:实现骑车类的具体车类* <br>类名:Sedan<br>* 作者: mht<br>* 日期: 2018年3月21日-上午8:24:55<br>*/
public class Sedan implements Car{@Overridepublic void run() {System.out.println("轿车跑...");}@Overridepublic void dift() {System.out.println("轿车漂移...更轻松...");}}

第三步:创建工厂类

这里注意,有些人会单独创建一个工厂接口,然后再创建具体的工厂实现类,每个具体工厂都会有一个用于返回具体产品的方法,在命名上也与具体产品类保持一致,比如:工厂A(实现工厂接口)——(生产)产品A;工厂B——产品B  ......这种方法本人觉得实现起来过于别扭,而工厂类属于中间类,大可不必与产品各个配套,这样反而使得在产生新产品的同时使项目中类的数量成对增加。以下是工厂类的另一种比较方便的实现方式:

package design.pattern.factory1;public class CarFactory {/*** 获得汽车方法 <br>* 作者: mht<br>* 时间:2018年3月20日-下午11:52:54<br>*/public static Car getCar(Class c) {if (c == null)return null;try {/*** 通过newInstance()方法,可以避免工厂类的抽象,将生产过程通过产品的类信息而<br>* 使工厂类达到"一般化"的效果。单独抽象工厂类,然后在生产产品的时候用new的原始方式,<br>* 需要额外扩展对应具体产品的工厂类,而这种newInstance()方式,实际上简化了这种复杂性,<br>* 却同样解决了新增产品需要修改工厂类逻辑的问题。*/Car car = (Car) c.newInstance();return car;} catch (Exception e) {e.printStackTrace();}return null;}
}

以上三步已经达到了工厂方法模式的实现,我们通过一个main方法简单的测试来看一下效果:

package design.pattern.factory1;public class testFactoryPattern {public static void main(String[] args) {Car bus = CarFactory.getCar(Bus.class);bus.run();bus.dift();Car truck = CarFactory.getCar(Truck.class);truck.run();truck.dift();Car sedan = CarFactory.getCar(Sedan.class);sedan.run();sedan.dift();}
}

运行结果:

公交车跑...
公交车漂移...不作不死!
卡车跑...
卡车漂移...不作不死...
轿车跑...
轿车漂移...更轻松...

对工厂模式的理解:

工厂模式充分利用了Java语言中继承和多态的特性。通过分析产品A与产品B或产品C之间存在的共性,抽象出一个可以涵盖这些产品特性的适当超类,然后通过这个超类的具体子类决定具体生产哪种产品而达到多态的目的。多态的意义就是“一个接口,多种实现”,而这里的“接口”不仅仅是表示Interface关键字修饰的抽象类,应该是更广义上的接口或抽象类,上面的代码实际上也可以通过将Car设计成abstract class 通过extends的方式来达到目的。

而更广义上的“工厂模式”实际上是包括了简单工厂、工厂方法、抽象工厂三种从简单到复杂的设计模式。

在有名的OOD的设计原则中有一个叫做里氏代换原则(Liskov Substitution Principle, LSP)。它的实质也就是讲向上转型。它的内容是:任何接收父类型的地方,都应当能够接收子类型,换句话说如果使用的是一个基类的话,那么一定适用于其子类,而且程序察觉不出基类对象和子类对象的区别。LSP是继承复用的基石,只有当派生类可以替换掉基类,软件的功能不受到影响时,基类才能真正被复用。 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/559032.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JavaScript新手入门教程大全~~~

JavaScript新手入门教程大全~~~一。 js教程介绍&#xff1a;JavaScript是一种运行在浏览器中的解释型的编程语言。 那么问题来了&#xff0c;为什么我们要学JavaScript&#xff1f;因为你没有选择。在Web世界里&#xff0c;只有JavaScript能跨平台、跨浏览器驱动网页&#xff0…

Java常用设计模式————抽象工厂模式

简介 每一个具体工厂类只负责创建抽象产品的某一个具体子类的实例。 与工厂方法模式的区别 工厂方法模式针对的是一个产品等级结构&#xff0c;而抽象工厂模式针对的是多个产品等级结构&#xff0c;因此抽象工厂模式在结构上要比工厂方法模式更加复杂和抽象&#xff0c;也更…

CSS新手入门教程~~~~

CSS新手入门教程~~~~CSS简介&#xff1a;什么是 CSS? CSS 指层叠样式表 (Cascading Style Sheets)样式定义如何显示 HTML 元素样式通常存储在样式表中把样式添加到 HTML 4.0 中&#xff0c;是为了解决内容与表现分离的问题外部样式表可以极大提高工作效率外部样式表通常存储在…

Docker必备知识整理

Docker简介 Docker是一个开源的应用容器引擎&#xff0c;让开发者可以打包他们的应用以及依赖包到一个可移植的容器中&#xff0c;然后发布到任何流行的Linux机器上&#xff0c;也可以实现虚拟化。容器是完全使用沙箱机制&#xff0c;相互之间不会有任何接口。 Docker是用Go语言…

Exception和Error深入分析~~~

Exception和Error深入分析~~~Exception 和 Error 都是继承了 Throwable 类&#xff0c;在 Java 中只有 Throwable 类型的实例才可以被抛出&#xff08;throw&#xff09;或者捕获&#xff08;catch&#xff09;&#xff0c;它是异常处理机制的基本组成类型。 Exception 和 Erro…

Java常用设计模式————原型模式(一)

介绍 原型模式&#xff08;Prototype Pattern&#xff09;&#xff1a;用原型实例指定创建对象的种类&#xff0c;并通过拷贝这些原型创建新的对象。 原型模式用于创建重复的对象&#xff0c;同时又能保证性能。当直接创建对象的代价比较大时&#xff0c;则采用这种模式。&…

解决eclipse刚启动卡死的问题~~~亲测有效~~

解决eclipse刚启动卡死的问题~~~亲测有效~~ 重启了eclipse三次&#xff0c;还是卡死了。最后找到一下方法&#xff1a; 建议大家在删除先备份一下文件&#xff0c;以免丢失项目&#xff01; 关于 eclipse启动卡死的问题&#xff08;eclipse上一次没有正确关闭&#xff0c;导致…

Java常用设计模式————原型模式(二)之深拷贝与浅拷贝

引言 clone顾名思义就是复制&#xff0c; 在Java语言中&#xff0c; clone方法被对象调用&#xff0c;所以会复制对象。所谓的复制对象&#xff0c;首先要分配一个和源对象同样大小的空间&#xff0c;在这个空间中创建一个新的对象。那么在java语言中&#xff0c;有几种方式可…

Java控制台输入教程~~~~

Java控制台输入教程~~~~当通过new Scanner&#xff08;System.in&#xff09;创建一个Scanner&#xff0c;控制台会一直等待输入&#xff0c;直到敲回车键结束&#xff0c;把所有输入的内容传给Scanner&#xff0c;作为扫描对象。如果要获取输入的内容&#xff0c;则只需要调用…

Java面试宝典————基础篇

参考原文&#xff1a;《Java面试题全集&#xff08;上&#xff09;》 1.Java中的基本数据类型有哪些&#xff1f; 类型&#xff1a;byte short int long float double boolean char 字节&#xff1a;1 2 4 8 4 8 1 2 2.面向…

Git初学札记(零)————EGIT完成Eclipse到GitHub一条龙

eclipse安装Egit插件 首先我们要找到所需的egit插件的url更新地址。百度一大堆&#xff0c;但是我还是希望自己去寻找。 打开Eclipse Downloads官网&#xff0c;在页面底部直接输入“egit”关键字&#xff0c;并直接点击第一条搜索到的结果。然后点击Downloads标签页&#xff0…

如何使用echo指令向文件写入内容

如何使用echo指令向文件写入内容0.前言本文总结如何使用echo命令向文件中写入内容&#xff0c;例如使用echo指令覆盖文件内容&#xff0c;使用echo指令向文件追加内容&#xff0c;使用echo指令往文件中追加制表符。echo向文件中输出内容的基本方法是使用IO重定向指令——“>…

Eclipse生成SSH传输密钥并实现GitHub的SSH代码提交

生成公私密钥 打开eclipse首选项完成如下操作&#xff1a;保存密钥&#xff1a;这里注意&#xff0c;博主之前已经生成过密钥了&#xff0c;因此这里只是演示截图&#xff0c;如果此时点击保存&#xff0c;会弹出“是否覆盖”提示框。 其中&#xff0c;id_rsa代表非对称加密算法…

Java实现链表结构

Java实现链表结构按链表的组织形式分有ArrayList和LinkList两种。ArrayList内部其实是用数组的形式实现链表&#xff0c;比较适合链表大小确定或较少对链表进行增删操作的情况&#xff0c;同时对每个链表节点的访问时间都是constant&#xff1b;而LinkList内部以一个List实现链…

SpringBoot————快速搭建springboot项目

完成项目的创建信息 浏览器打开SPRING INITIALIZR网址&#xff1a; http://start.spring.io/ 如下图所示完成配置&#xff1a; 1.完成基础项目配置 2.相关名称 3.依赖jar包&#xff0c;如果是web项目&#xff0c;那么这里选择的Web依赖已经包含了开发web项目所必须的服务器…

史上最容易理解————GET和POST两种基本请求方法的区别

GET和POST两种基本请求方法的区别GET和POST是HTTP请求的两种基本方法&#xff0c;要说它们的区别&#xff0c;接触过WEB开发的人都能说出一二。最直观的区别就是GET把参数包含在URL中&#xff0c;POST通过request body传递参数。你可能自己写过无数个GET和POST请求&#xff0c;…

SpringBoot————JPA快速使用

本篇博客源码地址&#xff1a;https://github.com/DragonWatcher/ease-run 概述 Hibernate与JPA 本篇博客中的web项目选用Hibernate作为持久层框架。在Spring Boot中&#xff0c;我们需要了解另一个概念&#xff1a;JPA 上一句话可能有些歧义&#xff0c;并不是说JPA就是Sp…

MySQL优化建议汇总~~~

MySQL优化建议汇总~~~1、将经常要用到的字段&#xff08;比如经常要用这些字段来排序&#xff0c;或者用来做搜索&#xff09;&#xff0c;则最好将这些字段设为索引 2、字段的种类尽可能用int或者tiny int类型。另外字段尽可能用not null 3、当然无可避免某些字段会用到text&a…

Java泛型初探————泛型通配

T ? K V E?——表示不确定的Java类型 T——表示Java类型 K、V——分别代表键-值中的Key-Value&#xff0c;例如Map<K,V>&#xff0c;put(K key, V value) E——代表Element&#xff0c;例如List<E>&#xff0c;add(E e)java.lang.ClassClass类的实例…

谈谈 final、finally、 finalize 有什么不同?

谈谈 final、finally、 finalize 有什么不同&#xff1f;final 可以用来修饰类、方法、变量&#xff0c;分别有不同的意义&#xff0c;final 修饰的 class 代表不可以继承扩展&#xff0c;final 的变量是不可以修改的&#xff0c;而 final 的方法也是不可以重写的&#xff08;o…