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的更多相关文章

  1. python 设计模式之工厂模式 Factory Pattern (简单工厂模式,工厂方法模式,抽象工厂模式)

    十一回了趟老家,十一前工作一大堆忙成了狗,十一回来后又积累了一大堆又 忙成了狗,今天刚好抽了一点空开始写工厂方法模式 我看了<Head First 设计模式>P109--P133 这25页 ...

  2. 【设计模式】工厂模式 Factory Pattern

    1)简单工厂(不是模式) 简单工厂只是一种变成习惯,并非23种设计模式之一. 简单工厂提供将实例话那种类型留给运行时判断,而非编译时指定.简单工厂模式就是由一个工厂类根据传入的参数决定创建出哪一个类的 ...

  3. java设计模式之 工厂模式Factory

    好比某种套路,经过不断实践,证明对项目结构非常有利 如果需要获取某种对象,如同获取不同的产品 需要由工厂来提供,工厂模式 可能的类或者对象:工厂类  产品:Cat  Dog  Fish ... //动 ...

  4. Java设计模式之工厂模式(Factory模式)介绍(转载)

    原文见:http://www.jb51.net/article/62068.htm 这篇文章主要介绍了Java设计模式之工厂模式(Factory模式)介绍,本文讲解了为何使用工厂模式.工厂方法.抽象工 ...

  5. 设计模式 - 工厂模式(factory pattern) 具体解释

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/u012515223/article/details/27081511 工厂模式(factory pa ...

  6. 浅析JAVA设计模式之工厂模式(一)

    1 工厂模式简单介绍 工厂模式的定义:简单地说,用来实例化对象,取代new操作. 工厂模式专门负责将大量有共同接口的类实例化.工作模式能够动态决定将哪一个类实例化.不用先知道每次要实例化哪一个类. 工 ...

  7. 浅析JAVA设计模式之工厂模式(二)

    1 工厂方法模式简单介绍 工厂方法 (Factroy Method)模式:又称多态性工厂模式(Polymorphic Factory),在这样的模式中,核心工厂不再是一个详细的类.而是一个抽象工厂,提 ...

  8. Java 设计模式之工厂模式(二)

    原文地址:Java 设计模式之工厂模式(二) 博客地址:http://www.extlight.com 一.背景 本篇内容是 Java 设计模式创建型模式的第二篇.上一篇主题为 <Java 设计 ...

  9. java设计模式2————工厂模式

    1.工厂模式介绍: 1.1.实现了创建者与调用者的分离 1.2.详细分类: 简单工厂模式 工厂方法模式 抽象工厂模式 1.3.所遵循的OOP原则: 开闭原则:对扩展开放,对修改关闭 依赖倒转原则:面向 ...

随机推荐

  1. 【翻译】Flink Table Api & SQL — Hive —— 读写 Hive 表

    本文翻译自官网:Reading & Writing Hive Tables  https://ci.apache.org/projects/flink/flink-docs-release-1 ...

  2. Houdini Mac 添加external editor

     我的尝试: 1. 找到houdini.env文件 2. 修改env文件,添加 EDITOR = ""/Applications/Sublime Text.app/Contents ...

  3. Ubuntu上使用Docker打包镜像

    关于这个一开始会有点懵,直白一点就是,把本地路径下的代码放到docker里面去,然后在docker这个隔离环境中运行调用我们的程序.专业解释请自行检索学习. 第一步:创建容器 docker run - ...

  4. 【Linux基础】vim如何显示文件名称

    前言 使用vim的时候有时候需要查看文件路径或者名称,本文对此进行记录. 操作过程 一般模式下 method1: :f method2: 快捷键CTRL+g/G(大小写均可); method3: 查看 ...

  5. lnmp+discuz使用redis缓存(待进一步研究)

    一直说Redis.Redis缓存.一直不清楚怎么用.于是花点时间研究了一下,但是还没搞懂.先把大概内容记录一下,待后续继续学习 1.首先部署lnmp环境,这个我的博客有些,请自行搜索 2.给php添加 ...

  6. Centos7中rc.local设置springboot项目开机自启动

    在Centos7下,rc.local文件,开机默认是不执行的 1.进入rc.local中 路径如下图

  7. Linux 中的-rwxr-xr-x权限代表什么意思

    Linux 中的权限 这里我拿一个tomcat目录举例说明.首先我们在linux系统中执行命令:ls -l 我们拿出其中一个说明-rwxr-xr-x,在Linux 系统中权限是区分用户的,即用户.组用 ...

  8. Java分布式:分布式锁之Zookeeper

    Java分布式:分布式锁之Zookeeper 分布式锁系列教程重点分享锁实现原理 引入ZooKeeper ZooKeeper是什么呢? ZooKeeper 是一个开源的分布式协调服务,它可以在分布式系 ...

  9. CSS选择符、伪类、层叠

    主题,架子(时间架子,空间架子,三角架),素材. CSS 三种方式 行内样式 嵌入样式 链接样式 上下文选择符 祖父 孙 p em {color:red;} 父 子 p > em {color: ...

  10. 实现一个java锁

    AQS是实现java锁的核心,但是实现起来还是仅仅只需继承该类重写它的几个主要方法即可. 1.首先,定义一个同步类,继承AQS. //这里要有个Sync内部类,实现锁需要继承AQSprivate st ...