简单工厂模式&工厂方法模式&抽象工厂模式的区别
工厂模式是java设计模式中比较简单的一个设计模式,但很多地方都用到了工厂模式,(如解析xml中,jdbc连接数据库等)利用好工厂模式对程序的设计很有用处。工厂模式在一些设计模式的书中分为简单工厂模式,工厂方法模式和抽象工厂模式三类。也有把工厂方法模式划分到抽象工厂模式的,认为工厂方法是抽象工厂模式的特例的一种,就是只有一个要实现的产品接口。下面结合例子分析三者的区别。
首先是简单工厂模式,这里以工厂生产产品为例。
产品类的共同接口
1 1 package factory; 2 2 /** 3 3 * 4 4 * @author CIACs 5 5 * 6 6 */ 7 7 public interface Product { 8 8 //声明类所需继承的共同接口,也可以是抽象类 9 9 }
产品A
1 package factory; 2 /** 3 * 4 * @author CIACs 5 * 6 */ 7 public class ProductA implements Product { 8 public ProductA() { 9 System.out.println("ProductA"); 10 } 11 }
产品B
1 package factory; 2 /** 3 * 4 * @author CIACs 5 * 6 */ 7 public class ProductB implements Product { 8 public ProductB() { 9 System.out.println("ProductB"); 10 } 11 }
工厂类
1 package factory; 2 /** 3 * 4 * @author CIACs 5 * 6 */ 7 public class Factory { 8 //可以在工厂类中添加任何你所需要的逻辑 9 public static Product create(String str) 10 { 11 //生成ProductA 12 if(str.equalsIgnoreCase("ProductA")) 13 { 14 return new ProductA(); 15 } 16 else 17 //生成ProductB 18 if(str.equalsIgnoreCase("ProductB")) 19 { 20 return new ProductB(); 21 } 22 return null; 23 } 24 25 }
客户端
1 package factory; 2 /** 3 * 4 * @author CIACs 5 * 6 */ 7 public class Client { 8 public static void main(String[] args) { 9 //调用Factory的静态方法生成所要的类 10 Factory.create("productA"); 11 Factory.create("ProductB"); 12 } 13 }
控制台输出结果:
简单工厂模式实现了生成产品类的代码跟客户端代码分离,在工厂类中你可以添加所需的生成产品的逻辑代码,但是问题来了,优秀的java代码是符合“开放-封闭”原则的,也就是说对扩展开发,对修改关闭,如果你要加一个产品类C,你就要修改工厂类里面的生成产品的代码,在这里你就要增加if-else判断。对于这个问题,我们的工厂方法模式就可以解决这个问题。
接下来是工厂方法模式
产品类中增加了ProductC(其他产品类的代码是可以重用上面的,只要把包名更改了就行)。
1 package factoryMehtod; 2 /** 3 * 4 * @author CIACs 5 * 6 */ 7 8 public class ProductC implements Product { 9 public ProductC() { 10 System.out.println("productC"); 11 } 12 }
声明工厂接口
1 package factoryMehtod; 2 /** 3 * 4 * @author CIACs 5 * 6 */ 7 public interface Factory { 8 //声明产生产品类的方法 9 public Product createProduct(); 10 }
产生ProductA的FactoryA
1 package factoryMehtod; 2 /** 3 * 4 * @author CIACs 5 * 6 */ 7 public class FactoryA implements Factory { 8 //实现工厂类的方法生成产品类A 9 public Product createProduct() 10 { 11 return new ProductA(); 12 } 13 14 }
产生ProductB的FactoryB
1 package factoryMehtod; 2 /** 3 * 4 * @author CIACs 5 * 6 */ 7 public class FactoryB implements Factory { 8 //实现工厂类的方法生成产品类B 9 public Product createProduct() 10 { 11 return new ProductB(); 12 } 13 }
产生ProductC的FactoryC
1 package factoryMehtod; 2 /** 3 * 4 * @author CIACs 5 * 6 */ 7 public class FactoryC implements Factory { 8 //实现工厂类的方法生成产品类C 9 public Product createProduct() 10 { 11 return new ProductC(); 12 } 13 }
客户端
1 package factoryMehtod; 2 /** 3 * 4 * @author CIACs 5 * 6 */ 7 public class Client { 8 public static void main(String[] args) { 9 Factory factory; 10 factory = new FactoryA(); 11 factory.createProduct(); 12 factory = new FactoryB(); 13 factory.createProduct(); 14 factory = new FactoryC(); 15 factory.createProduct(); 16 } 17 }
控制台输出结果:
工厂方法模式中我们把生成产品类的时间延迟,就是通过对应的工厂类来生成对应的产品类,在这里我们就可以实现“开发-封闭”原则,无论加多少产品类,我们都不用修改原来类中的代码,而是通过增加工厂类来实现。但是这还是有缺点的,如果产品类过多,我们就要生成很多的工厂类。假如我们要实现的产品接口不止一个,也就是有多个产品接口,不同产品接口有对应的产品族。什么是产品族呢?简单的理解就是,不同牌子产的车里面会有跑车类型,家庭类型,商用类型等的车,不同牌子的车的跑车类型的车可以组成一个产品族。对于这种情况我们可以采用抽象工厂模式。
最后是抽象工厂模式,在这里我们为不同产品附加上对应的礼物,就是说ProductA中会有GiftA。
增加的Gift接口
1 package abstractFactory; 2 /** 3 * 4 * @author CIACs 5 * 6 */ 7 public interface Gift { 8 //声明产品赠品的接口,当然也可以是抽象类,同样为了简单就不声明方法了 9 }
GiftA类
1 package abstractFactory; 2 /** 3 * 4 * @author CIACs 5 * 6 */ 7 public class GiftA implements Gift { 8 public GiftA() 9 { 10 System.out.println("GiftA"); 11 } 12 }
GiftB类
1 package abstractFactory; 2 /** 3 * 4 * @author CIACs 5 * 6 */ 7 public class GiftB implements Gift { 8 public GiftB() 9 { 10 System.out.println("GiftB"); 11 } 12 }
Factory接口
1 package abstractFactory; 2 /** 3 * 4 * @author CIACs 5 *声明Product类工厂和Gift类工厂的工同工厂接口 6 */ 7 public interface Factory { 8 public Product createProduct(); 9 public Gift createGift(); 10 11 }
生成ProductA和GiftA的FactoryA
1 package abstractFactory; 2 /** 3 * 4 * @author CIACs 5 *FactoryA可以生成ProductA和GiftA 6 */ 7 public class FactoryA implements Factory { 8 @Override 9 public Product createProduct() 10 { 11 return new ProductA(); 12 } 13 @Override 14 public Gift createGift() 15 { 16 return new GiftA(); 17 } 18 }
生成ProductB和GiftB的FactoryB
1 package abstractFactory; 2 /** 3 * 4 * @author CIACs 5 *FactoryB可以生成ProductB和GiftB 6 */ 7 public class FactoryB implements Factory { 8 @Override 9 public Product createProduct() { 10 return new ProductB(); 11 } 12 @Override 13 public Gift createGift() { 14 return new GiftB(); 15 } 16 17 }
客户端
1 package abstractFactory; 2 /** 3 * 4 * @author CIACs 5 * 6 */ 7 public class Client { 8 public static void main(String[] args) { 9 Factory factory; 10 factory = new FactoryA(); 11 factory.createProduct(); 12 factory.createGift(); 13 factory = new FactoryB(); 14 factory.createProduct(); 15 factory.createGift(); 16 } 17 }
控制台输出结果:
抽象工厂模式中我们可以定义实现不止一个接口,一个工厂也可以生成不止一个产品类,抽象工厂模式较好的实现了“开放-封闭”原则,是三个模式中较为抽象,并具一般性的模式。我们在使用中要注意使用抽象工厂模式的条件。
原文地址:https://www.cnblogs.com/jxxblogs/p/12209662.html
- Android 命名规范 (提高代码可以读性)
- Msdn 杂志 asp.net ajax 文章汇集
- 分布式监控系统Zabbix-3.0.3-完整安装记录-新报微信报警(企业微信)
- 测试网站页面网速的一个简单Python脚本
- 框架页面尽可以这么用(后置代码中控制框架)
- 微信小程序「学科排名」发布了
- Nginx 负载均衡的Cache缓存批量清理的操作记录
- DotNet软件开发框架
- Nginx通过https方式反向代理的简单实现
- 再论IBatisNet + Castle进行项目的开发
- 利用xml轻松读取web.config中的用户自定义节
- 分布式监控系统Zabbix-3.0.3-完整安装记录(3)-监控nginx,php,memcache,Low-level discovery磁盘IO
- python报错问题解决:'ascii' codec can't encode character
- 利用message queue实现aspx与winform通信, 并附完整示例
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- RestPack Java实现Html转PDF文件
- 六、垃圾回收_判断对象是否存活算法_引用计数法详解
- webpack + express 实现文件精确缓存
- python提取视频中的音频
- Vue3 响应式原理
- vue-mergeable-table 动态生成的可合并行列的表格
- 【GOFLY】基于GO语言gin框架和websocket实现的全开源WEB客服即时通讯管理系统
- edgeXFoundry中modbus通信部署和测试(待续)
- C++面向对象学习之运算符重载(1)
- PAT (Basic Level) Practice (中文)1045 快速排序 (25 分)
- PAT (Advanced Level) Practice 1028 List Sorting (25分)
- CNS图表复现06—根据CellMarker网站进行人工校验免疫细胞亚群
- 【Java】03 流程控制语句
- Artwork (Gym - 102346A)【DFS、连通块】
- PAT (Basic Level) Practice (中文)1046 划拳 (15 分)