JAVA设计模式之工厂模式—Factory Pattern
1.工厂模式简介
工厂模式用于对象的创建,使得客户从具体的产品对象中被解耦。
2.工厂模式分类
这里以制造coffee的例子开始工厂模式设计之旅。
我们知道coffee只是一种泛举,在点购咖啡时需要指定具体的咖啡种类:美式咖啡、卡布奇诺、拿铁等等。
/**
*
* 拿铁、美式咖啡、卡布奇诺等均为咖啡家族的一种产品
* 咖啡则作为一种抽象概念
* @author Lsj
*
*/
public abstract class Coffee { /**
* 获取coffee名称
* @return
*/
public abstract String getName(); } /**
* 美式咖啡
* @author Lsj
*
*/
public class Americano extends Coffee { @Override
public String getName() {
return "美式咖啡";
} } /**
* 卡布奇诺
* @author Lsj
*
*/
public class Cappuccino extends Coffee { @Override
public String getName() {
return "卡布奇诺";
} } /**
* 拿铁
* @author Lsj
*
*/
public class Latte extends Coffee { @Override
public String getName() {
return "拿铁";
} }
2.1 简单工厂
简单工厂实际不能算作一种设计模式,它引入了创建者的概念,将实例化的代码从应用代码中抽离,在创建者类的静态方法中只处理创建对象的细节,后续创建的实例如需改变,只需改造创建者类即可,
但由于使用静态方法来获取对象,使其不能在运行期间通过不同方式去动态改变创建行为,因此存在一定局限性。
/**
* 简单工厂--用于创建不同类型的咖啡实例
* @author Lsj
*
*/
public class SimpleFactory { /**
* 通过类型获取Coffee实例对象
* @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) {
Coffee latte = SimpleFactory.createInstance("latte");
System.out.println("创建的咖啡实例为:" + latte.getName());
Coffee cappuccino = SimpleFactory.createInstance("cappuccino");
System.out.println("创建的咖啡实例为:" + cappuccino.getName());
} }
2.2 工厂方法模式
定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个,工厂方法让类把实例化推迟到了子类。
场景延伸:不同地区咖啡工厂受制于环境、原料等因素的影响,制造出的咖啡种类有限。中国咖啡工厂仅能制造卡布奇诺、拿铁,而美国咖啡工厂仅能制造美式咖啡、拿铁。
/**
* 定义一个抽象的咖啡工厂
* @author Lsj
*/
public abstract class CoffeeFactory { /**
* 生产可制造的咖啡
* @return
*/
public abstract Coffee[] createCoffee(); } /**
* 中国咖啡工厂
* @author Lsj
*
*/
public class ChinaCoffeeFactory extends CoffeeFactory { @Override
public Coffee[] createCoffee() {
// TODO Auto-generated method stub
return new Coffee[]{new Cappuccino(), new Latte()};
} } /**
* 美国咖啡工厂
* @author Lsj
*
*/
public class AmericaCoffeeFactory extends CoffeeFactory { @Override
public Coffee[] createCoffee() {
// TODO Auto-generated method stub
return new Coffee[]{new Americano(), new Latte()};
} } /**
* 工厂方法测试
* @author Lsj
*
*/
public class FactoryMethodTest { static void print(Coffee[] c){
for (Coffee coffee : c) {
System.out.println(coffee.getName());
}
} public static void main(String[] args) {
CoffeeFactory chinaCoffeeFactory = new ChinaCoffeeFactory();
Coffee[] chinaCoffees = chinaCoffeeFactory.createCoffee();
System.out.println("中国咖啡工厂可以生产的咖啡有:");
print(chinaCoffees);
CoffeeFactory americaCoffeeFactory = new AmericaCoffeeFactory();
Coffee[] americaCoffees = americaCoffeeFactory.createCoffee();
System.out.println("美国咖啡工厂可以生产的咖啡有:");
print(americaCoffees);
}
}

2.3 抽象工厂
提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。
在上述的场景上继续延伸:咖啡工厂做大做强,引入了新的饮品种类:茶、 碳酸饮料。中国工厂只能制造咖啡和茶,美国工厂只能制造咖啡和碳酸饮料。
如果用上述工厂方法方式,除去对应的产品实体类还需要新增2个抽象工厂(茶制造工厂、碳酸饮料制造工厂),4个具体工厂实现。随着产品的增多,会导致类爆炸。
所以这里引出一个概念产品家族,在此例子中,不同的饮品就组成我们的饮品家族, 饮品家族开始承担创建者的责任,负责制造不同的产品。
/**
* 抽象的饮料产品家族制造工厂
* @author Lsj
*
*/
public interface AbstractDrinksFactory { /**
* 制造咖啡
* @return
*/
Coffee createCoffee(); /**
* 制造茶
* @return
*/
Tea createTea(); /**
* 制造碳酸饮料
* @return
*/
Sodas createSodas();
} /**
* 中国饮品工厂
* 制造咖啡与茶
* @author Lsj
*
*/
public class ChinaDrinksFactory implements AbstractDrinksFactory { @Override
public Coffee createCoffee() {
// TODO Auto-generated method stub
return new Latte();
} @Override
public Tea createTea() {
// TODO Auto-generated method stub
return new MilkTea();
} @Override
public Sodas createSodas() {
// TODO Auto-generated method stub
return null;
} } /**
* 美国饮品制造工厂
* 制造咖啡和碳酸饮料
* @author Lsj
*
*/
public class AmericaDrinksFactory implements AbstractDrinksFactory { @Override
public Coffee createCoffee() {
// TODO Auto-generated method stub
return new Latte();
} @Override
public Tea createTea() {
// TODO Auto-generated method stub
return null;
} @Override
public Sodas createSodas() {
// TODO Auto-generated method stub
return new CocaCola();
} } /**
* 抽象工厂测试类
* @author Lsj
*
*/
public class AbstractFactoryTest { static void print(Drink drink){
if(drink == null){
System.out.println("产品:--" );
}else{
System.out.println("产品:" + drink.getName());
}
} public static void main(String[] args) {
AbstractDrinksFactory chinaDrinksFactory = new ChinaDrinksFactory();
Coffee coffee = chinaDrinksFactory.createCoffee();
Tea tea = chinaDrinksFactory.createTea();
Sodas sodas = chinaDrinksFactory.createSodas();
System.out.println("中国饮品工厂有如下产品:");
print(coffee);
print(tea);
print(sodas); AbstractDrinksFactory americaDrinksFactory = new AmericaDrinksFactory();
coffee = americaDrinksFactory.createCoffee();
tea = americaDrinksFactory.createTea();
sodas = americaDrinksFactory.createSodas();
System.out.println("美国饮品工厂有如下产品:");
print(coffee);
print(tea);
print(sodas);
} }

3.总结
简单工厂:不能算是真正意义上的设计模式,但可以将客户程序从具体类解耦。
工厂方法:使用继承,把对象的创建委托给子类,由子类来实现创建方法,可以看作是抽象工厂模式中只有单一产品的情况。
抽象工厂:使对象的创建被实现在工厂接口所暴露出来的方法中。
工厂模式可以帮助我们针对抽象/接口编程,而不是针对具体类编程,在不同的场景下按具体情况来使用。
参考书籍:
《HeadFirst 设计模式》
JAVA设计模式之工厂模式—Factory Pattern的更多相关文章
- python 设计模式之工厂模式 Factory Pattern (简单工厂模式,工厂方法模式,抽象工厂模式)
十一回了趟老家,十一前工作一大堆忙成了狗,十一回来后又积累了一大堆又 忙成了狗,今天刚好抽了一点空开始写工厂方法模式 我看了<Head First 设计模式>P109--P133 这25页 ...
- 【设计模式】工厂模式 Factory Pattern
1)简单工厂(不是模式) 简单工厂只是一种变成习惯,并非23种设计模式之一. 简单工厂提供将实例话那种类型留给运行时判断,而非编译时指定.简单工厂模式就是由一个工厂类根据传入的参数决定创建出哪一个类的 ...
- java设计模式之 工厂模式Factory
好比某种套路,经过不断实践,证明对项目结构非常有利 如果需要获取某种对象,如同获取不同的产品 需要由工厂来提供,工厂模式 可能的类或者对象:工厂类 产品:Cat Dog Fish ... //动 ...
- Java设计模式之工厂模式(Factory模式)介绍(转载)
原文见:http://www.jb51.net/article/62068.htm 这篇文章主要介绍了Java设计模式之工厂模式(Factory模式)介绍,本文讲解了为何使用工厂模式.工厂方法.抽象工 ...
- 设计模式 - 工厂模式(factory pattern) 具体解释
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/u012515223/article/details/27081511 工厂模式(factory pa ...
- 浅析JAVA设计模式之工厂模式(一)
1 工厂模式简单介绍 工厂模式的定义:简单地说,用来实例化对象,取代new操作. 工厂模式专门负责将大量有共同接口的类实例化.工作模式能够动态决定将哪一个类实例化.不用先知道每次要实例化哪一个类. 工 ...
- 浅析JAVA设计模式之工厂模式(二)
1 工厂方法模式简单介绍 工厂方法 (Factroy Method)模式:又称多态性工厂模式(Polymorphic Factory),在这样的模式中,核心工厂不再是一个详细的类.而是一个抽象工厂,提 ...
- Java 设计模式之工厂模式(二)
原文地址:Java 设计模式之工厂模式(二) 博客地址:http://www.extlight.com 一.背景 本篇内容是 Java 设计模式创建型模式的第二篇.上一篇主题为 <Java 设计 ...
- java设计模式2————工厂模式
1.工厂模式介绍: 1.1.实现了创建者与调用者的分离 1.2.详细分类: 简单工厂模式 工厂方法模式 抽象工厂模式 1.3.所遵循的OOP原则: 开闭原则:对扩展开放,对修改关闭 依赖倒转原则:面向 ...
随机推荐
- 【翻译】Flink Table Api & SQL — 配置
本文翻译自官网:Configuration https://ci.apache.org/projects/flink/flink-docs-release-1.9/dev/table/config.h ...
- CVI中调用VC动态库
1.在VC环境中建立新工程,创建32位动态库(Win32 Dynamic-Link Library) -> A simple DLL project 2.在工程中可加入别的动态库,在工程菜单中 ...
- springboot踩坑记
1. @ConditionalOnProperty 根据配置加载不同的 bean 场景:对 redis 配置进行封装,实现自动化配置,能兼容哨兵模式和集群模式.想到在 redis 配置中加一个 red ...
- php提供一维数组模糊查询
2019年9月30日14:36:15 提供一维数组模糊查询,只支持utf-8 内部处理是Unicode 编码特殊编码格式的可能会出错 if (!function_exists('arrayFuzzyQ ...
- idea修改maven项目名
1.修改pom.xml中相关 <artifactId>seal-hn</artifactId><name>seal-hn</name><descr ...
- Gerrit - 代码评审工具Gerrit简介与安装
1 - 前言 Code Review 代码评审是指在软件开发过程中,对源代码的系统性检查,改进代码质量,查找系统缺陷,保证软件总体质量和提高开发者自身水平. 简单的说,Code Review是用来确认 ...
- 工具分享:excel2json,将Excel表格转换为JSON
此次分享的是github上的一个开源小工具:excel2json,用于把Excel表转换成json对象,并保存到一个文本文件. 项目地址:https://github.com/neil3d/excel ...
- 查看linux操作系统
cd /etc ll *release -rw-r--r-- 1 root root 38 Oct 8 2018 centos-release -rw-r--r-- 1 root root 393 O ...
- eclipse项目有红色感叹号
1.依赖有问题 找到build path 点击configure build path 点击libraries 找到有红叉的包,然后选中移除 2.引用的包有问题 利用maven引用的包出现问题,有的包 ...
- Spring AOP的常用方法
转 https://blog.csdn.net/u014745069/article/details/84887765