【design pattern】工厂方法模式和抽象工厂模式

前言

设计模式分为三大类:

创建型模式:工厂方法模式抽象工厂模式、单例模式、建造者模式、原型模式;

结构型模式:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式;

行为型模式:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式;

简单工厂

首先要明确的是,简单工厂模式不属于23种设计模式,它引入了创建者的概念,将实例化的代码从应用代码中抽离,在工厂类的静态方法中只处理被创建的对象,如果业

务需要变更则需要在工厂类中添加具体的实现类,因此维护性较差。以"工厂创建咖啡"为例说明,如下:

1. 物品标识类Coffee和已有的类

package com.oxygen.bean;/*** * 咖啡则作为一种抽象概念:拿铁、美式咖啡、卡布奇诺等均为咖啡家族的一种产品* @author Oxygen**/
public abstract class Coffee {public abstract String desc(); //获取coffee名称

}class Americano extends Coffee { // 美式咖啡
@Overridepublic String desc() {return "美式咖啡";}}class Cappuccino extends Coffee { //卡布奇诺
@Overridepublic String desc() {return "卡布奇诺";}}class Latte extends Coffee { //拿铁
@Overridepublic String desc() {return "拿铁";}}
View Code

2. 简单工厂

package com.oxygen.bean;/*** 创建材料的工厂类* @author Oxygen *    @date 2018年10月16日*/
public class SimpleFactory {/*** * @param type 材料类型* @return*/public static Coffee createInstance(String type) {if ("Americano".equals(type)) {return new Americano();} else if ("Cappuccino".equals(type)) {return new Cappuccino();} else if ("Latte".equals(type)) {return new Latte();} else {throw new RuntimeException("type[" + type + "]类型不可识别,没有匹配到可实例化的对象!");}}public static void main(String[] args) {System.out.println(SimpleFactory.createInstance("Americano").desc());System.out.println(SimpleFactory.createInstance("Cappuccino").desc());System.out.println(SimpleFactory.createInstance("Latte").desc());}
}
View Code

3. 输出结果

美式咖啡
卡布奇诺
拿铁

工厂方法

 工厂方法模式其定义了一个创建对象的接口,由子类决定要实例化的类是哪一个,工厂方法让类把实例化推迟到了子类,也就是说一个工厂只能生成特定的Coffee

1. 工厂类

package com.oxygen.bean;/*** Coffee工厂* @author Oxygen *    @date 2018年10月16日*/
public abstract interface CoffeeFactory {public abstract Coffee[] createCoffee();public static void main(String[] args) {CoffeeFactory chinaCoffeeFactory = new ChinaCoffeeFactory();Coffee[] chinaCoffees = chinaCoffeeFactory.createCoffee();System.out.print("中国咖啡工厂可以生产的咖啡有:");print(chinaCoffees);CoffeeFactory americaCoffeeFactory = new AmericaCoffeeFactory();Coffee[] americaCoffees = americaCoffeeFactory.createCoffee();System.out.print("美国咖啡工厂可以生产的咖啡有:");print(americaCoffees);}public static void print(Coffee[] c) {for (Coffee coffee : c) {System.out.print(coffee.desc() + " ");}System.out.println();}
}class ChinaCoffeeFactory implements CoffeeFactory { //中国咖啡工厂
@Overridepublic Coffee[] createCoffee() {return new Coffee[] { new Cappuccino(), new Latte() };}}class AmericaCoffeeFactory implements CoffeeFactory { //美国咖啡工厂
@Overridepublic Coffee[] createCoffee() {return new Coffee[] { new Americano(), new Latte() };}}
View Code

2. 输出结果

中国咖啡工厂可以生产的咖啡有:卡布奇诺 拿铁 
美国咖啡工厂可以生产的咖啡有:美式咖啡 拿铁 

抽象工厂

提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类,在上述的场景上继续延伸:咖啡工厂做大做强,引入了新的饮品种类:茶、 碳酸饮

料。中国工厂只能制造咖啡和茶,美国工厂只能制造咖啡和碳酸饮料,如果继续使用上述工厂方法方式,除去对应的产品实体类还需要新增2个抽象工厂(茶制造

工厂、碳酸饮料制造工厂),4个具体工厂实现。

随着产品的增多,会导致类爆炸,这显然是不能接受的。所以这里引出一个概念产品家族,在此例子中,不同的饮品就组成我们的饮品家族, 饮品家族开始承担

创建者的责任,负责制造不同的产品。如下:

package com.oxygen.bean;public interface AbstractDrinksFactory {Coffee createCoffee(); //制造咖啡
Tea createTea(); //制造茶
Sodas createSodas();//制造碳酸饮料
}/*** 中国饮品工厂:制造咖啡与茶*/
class ChinaDrinksFactory implements AbstractDrinksFactory {@Overridepublic Coffee createCoffee() {return new Latte();}@Overridepublic Tea createTea() {return new MilkTea();}@Overridepublic Sodas createSodas() {// TODO Auto-generated method stubreturn null;}
}/*** 美国饮品制造工厂:制造咖啡和碳酸饮料*/
class AmericaDrinksFactory implements AbstractDrinksFactory {@Overridepublic Coffee createCoffee() {// TODO Auto-generated method stubreturn new Latte();}@Overridepublic Tea createTea() {// TODO Auto-generated method stubreturn null;}@Overridepublic Sodas createSodas() {// TODO Auto-generated method stubreturn new CocaCola();}}
View Code

总结

工厂模式可以帮助我们针对抽象接口编程,而不是针对具体类编程,在不同的场景下按具体情况来

1. 简单工厂:不能算是真正意义上的设计模式,但可以将客户程序从具体类解耦;

2. 工厂方法:使用继承,把对象的创建委托给子类,由子类来实现创建方法,可以看作是抽象工厂模式中只有单一产品的情况;

3. 抽象工厂:使对象的创建被实现在工厂接口所暴露出来的方法中;

转载于:https://www.cnblogs.com/oxygenG/p/9797254.html

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

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

相关文章

弹簧触摸开关原理图_10年老电工经验之谈:常见的开关电源那些事儿

随着电控系统中对控制回路安全性要求提高,控制回路的工作电压是越来越趋于直流低压化。由此,控制回路内各种使用直流电源的传感器、中小微型直流继电器等电器装置是日益增多。也正因如此,电控系统内不同品牌的开关电源也相应地多了起来。因牵…

erlang mysql连接超时_Erlang数据库-(一)Erlang与Mysql的连接

下载:http://download.csdn.net/detail/hjhjava/7088277把该文件的东西全部编译好,然后根据下面的解释就可以操作Mysql的。很简单~-record(row,{a1 0, a20}).%% 第一个参数是该链接的名字(根据它来操作Mysql),第二参数是本机号(ip地址)%% &a…

管理活动目录域服务实训_管理学院学生党支部开展实践教育基地服务活动

红星E校有态度 有温度 可关注为进一步加强党的建设,深化管理学院学生党支部与实践基地的互动性,2020年9月11至12日,管理学院学生党支部协助白鹤村村委实践基地完成第七次人口普查相关工作,共计6名预备党员参与。工作开始前的培训会…

mysql 汉编码 的选_peewee连接mysql汉语言数据编码_mysql

peewee连接mysql中文数据编码系统是win7 x64python 2.7.6的site.py里面编码设定为 utf-8py文件首行指定 #coding:utf-8mysql 5.5.38安装时指定代码为utf-8peewee的连接数据库代码为:db MySQLDatabase(host 127.0.0.1, user root, passwd 1, database mz, chars…

配置windows失败,还原更新,请勿关机

最近给同事装系统,偶尔会出现如下问题: 如果是这种情况,只能耐心等待了,因为关机也没用! 转载于:https://www.cnblogs.com/lijy/p/5327844.html

使用uicollectionView时需要注意的问题

1.UICollectionView使用流水布局——UICollectionViewFlowLayout时,需要满足条件: 每个item(即cell)的大小是一样的,不仅是宽度,还有高度。这样,当collectionview的宽度发生变化时,item能将其动态填充。ite…

swift 从手机选照片_19元起!定制专属手机壳!还可免费打印照片...

△剧透:文末有福利现在的年轻人体内涌动的都是追求有趣有特色的灵魂希望自己是这条gai最独一无二的仔撞衫撞包撞手机壳可以说是当代年轻人三大时尚忌讳尤其是手机壳极为重要毕竟换壳≈换机只需要几十元买新壳就可以拥有换新机般的仪式感不过作为手机壳老手都知道在某…

新手也能学会本地调试微信,natapp 官网映射

本地调试微信的新手指引~ 照着配置,一定可以配置成功,实现本地调试微信,公司好几个同事按照我写的步骤,都独立配成功了。 1.首选在natapp注册一个账号,申请免费隧道或者购买隧道,我买了一个月9元的付费隧道…

c实现三角形角度大于一个值_初中数学三角形知识点小结

▊ 三角形两边定理:三角形两边的和大于第三边。推论:三角形两边的差小于第三边。▊ 三角形中位线定理三角形的中位线平行于第三边,并且等于它的一半。▊ 三角形的重心三角形的重心到顶点的距离是它到对边中点距离的2倍。在三角形中&#x…

【Spring】使用Spring和AMQP发送接收消息(下)

为什么80%的码农都做不了架构师?>>> 上篇讲了RabbitMQ连接工厂的作用是用来创建RabbitMQ的连接,本篇就来讲讲RabbitMQ的发送消息。通过RabbitMQ发送消息最简单的方式就是将connectionFactory Bean注入到服务层类中,并使用它创建C…

微软u盘安装工具_使用微软Winget工具安装软件教程

对于系统管理员来说,一款好用的软件包管理工具可以大大提高安装、部署、管理软件的效率。可之前只有 MscOS 和 Linux 官方才有软件包管理工具,微软官方现在终于为Windows系统发布了一款名为Winget的软件包管理工具,MS酋长下面就来为大家演示一…

RandomForestClassifier(随机森林检测每个特征的重要性及每个样例属于哪个类的概率)...

#In the next recipe, well look at how to tune the random forest classifier. #Lets start by importing datasets:from sklearn import datasets X, y datasets.make_classification(1000)# X(1000,20) #y(1000) 取值范围【0,1】from sklearn.ensemble import RandomFores…

单因素方差分析_基于R语言开展方差分析(一)——单因素方差分析

基本原理方差分析(Analysis of variance, ANOVA)是用于两个或两个以上样本均数比较的方法,还可以分析两个或多个研究因素的交互交互作用以及回归方程的线性假设检验等。其基本思想是将全部观察值间的变异——总变异按设计和需要分解成两个或多个组成部分&#xff0c…

mysql增数据语句_Mysql 数据增删改查语句

插入数据 insert#1. 插入完整数据(顺序插入)#语法一:insert into 表名(字段1,字段2,字段3…字段n) values (值1,值2,值3…值n);#语法二:insert into 表名 values (值1,值2,值3…值n);#2. 指定字段插入数据#语法:insert into 表名(字段1,字段2…

Python+Flask.0010.FLASK即插视图之自定义视图类及修饰器

2019独角兽企业重金招聘Python工程师标准>>> 即插视图; 说明: FLASK的视图灵感来自于DJANGO的基于类而非基于函数的通用视图,主要目的是为了解决多个视图函数之间已经实现的部分,通过类继承的方式继承到其它视图,总之为了一点,就是少写代码,然后通过add_url_rule让我…

InputStream和Reader,FileInputStream和 FileReader的区别

一、InputStream和Reader的区别 InputStream和Reader都可以用来读数据(从文件中读取数据或从Socket中读取数据),最主要的区别如下: InputStream用来读取二进制数(字节流),而 Reader用来读取文本数据,即 Unicode字符。那么二进制数与文本数据有…

NGUI之输入文本框的使用

ToolBar中的两个红圈 另,代码如下:只需要定义一个变量即可,然后将控件drag到那里,真的是灰常方便呀 还有一个就是保存了(OK的响应),可以简单地理解为存档或读档 转载于:https://www.cnblogs.com/YTYMblog/p…

tensorrt轻松部署高性能dnn推理_实战教程:TensorRT中递归神经网络的介绍(中文字幕)...

NVIDIA TensorRT是一个高性能的深度学习推理优化器和运行时,它提供低延迟和高吞吐量。TensorRT可以从每个深度学习框架导入经过训练的模型,从而轻松地创建可以集成到大型应用程序和服务中的高效推理引擎。这个视频的五个关键点:1.TensorRT支持RNNv2, Mat…

w怎么接显示 树莓派zero_纯干货!一根线玩转树莓派ZeroW(图文教程,亲测有效)...

#一、写在前面本文旨在介绍如何用最少的外设(成本)完成树莓派Zero W最基础最重要的功能。注意:本文原始发表时官方镜像版本是2017-04-10的,在2019年5月10日有网友提出本方案已经不完全适用最新的镜像了,所以如果只是想按照本文所提出的步骤一…

十进制小数转换二进制的问题

2019独角兽企业重金招聘Python工程师标准>>> 整数和小数分别转换。 整数除以2,商继续除以2,得到0为止,将余数逆序排列。 22 / 2 11 余0 11/2 5 余 1 5 /2 2 余 1 2 /2 1 余 0 1 /2 0 余 1 所以22的二进制…