工厂模式

                                                                                                    个人博客:www.xiaobeigua.icu


1.1 概述

 需求:设计一个咖啡店点餐系统。

设计一个咖啡类(Coffee),并定义其两个子类(美式咖啡【AmericanCoffee】和拿铁咖啡 【LatteCoffee】);再设计一个咖啡店类(CoffeeStore),咖啡店具有点咖啡的功能。

具体类的设计如下:

在java中,万物皆对象,这些对象都需要创建,如果创建的时候直接new该对象,就会对该对象耦合严重,假如我们要更换对象,所有new对象的地方都需要修改一遍,这显然违背了软件设计的开闭原则。

如果我们使用工厂来生产对象,我们就只和工厂打交道就可以了,彻底和对象解耦,如果要更换对象, 直接在工厂里更换该对象即可,达到了与对象解耦的目的;所以说,工厂模式最大的优点就是:解耦。

本次博客将介绍我们常用的3种工厂模式的使用

  • 简单工厂模式(不属于GOF的23种经典设计模式
  • 工厂方法模式
  • 抽象工厂模式

1.2 简单工厂模式

其实简单工厂不是一种设计模式,也不能说不是设计模式,只是它这种模式不包括在23种设计模式中,更像是一种编程习惯。

1.2.1 结构

简单工厂包含如下角色:

  • 抽象产品 :定义了产品的规范,描述了产品的主要特性和功能。
  • 具体产品 :实现或者继承抽象产品的子类
  • 具体工厂 :提供了创建产品的方法,调用者通过该方法来获取产品。

1.2.2  实现

实现现在使用简单工厂对上面案例进行改进,类图如下:

 咖啡工厂类代码:

public class SimpleCoffeeFactory {public Coffee createCoffee(String type) {Coffee coffee = null;if("americano".equals(type)) {coffee = new AmericanoCoffee();} else if("latte".equals(type)) {coffee = new LatteCoffee();}return coffee;}
}

工厂(factory)处理创建对象的细节,一旦有了SimpleCoffeeFactory,CoffeeStore类中的 orderCoffee()就变成此对象的客户,后期如果需要Coffee对象直接从工厂中获取即可。这样也就 解除了和Coffee实现类的耦合,同时又产生了新的耦合,CoffeeStore对象和 SimpleCoffeeFactory工厂对象的耦合,工厂对象和商品对象的耦合。

后期如果再加新品种的咖啡,我们势必要需求修改SimpleCoffeeFactory的代码,违反了开闭原 则。工厂类的客户端可能有很多,比如创建美团外卖等,这样只需要修改工厂类的代码,省去其他的修改操作。

1.2.3 优缺点

优点:

封装了创建对象的过程,可以通过参数直接获取对象。把对象的创建和业务逻辑层分开,这样以后就避免了修改客户代码,如果要实现新产品直接修改工厂类,而不需要在客户原代码中修改,这样就降低了客户代码修改的可能性,更加容易扩展。

缺点:

增加新产品时还是需要修改工厂类的代码,违背了“开闭原则”。


1.3 工厂方法模式

针对上例中的缺点,使用工厂方法模式就可以完美的解决,完全遵循开闭原则。

1.3.1 概念

定义一个用于创建对象的接口,让子类决定实例化哪个产品类对象。工厂方法使一个产品类的实例化延 迟到其工厂的子类。

1.3.2 结构

工厂方法模式的主要角色:

  • 抽象工厂(Abstract Factory):提供了创建产品的接口,调用者通过它访问具体工厂的工厂 方法来创建产品。
  • 具体工厂(ConcreteFactory):主要是实现抽象工厂中的抽象方法,完成具体产品的创建。
  • 抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能。
  • 具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来创建,它同 具体工厂之间一一对应。

1.3.3 实现

使用工厂方法模式对上例进行改进,类图如下:

抽象工厂:

public interface CoffeeFactory {Coffee createCoffee();
}

具体工厂:

public class LatteCoffeeFactory implements CoffeeFactory {public Coffee createCoffee() {return new LatteCoffee();}
}public class AmericanCoffeeFactory implements CoffeeFactory {public Coffee createCoffee() {return new AmericanCoffee();}
}

咖啡店:

public class CoffeeStore {//面向接口编程 定义咖啡工厂类private CoffeeFactory factory;//有参构造方法 用于初始化咖啡工厂类public CoffeeStore(CoffeeFactory factory) {this.factory = factory;}//生产咖啡public Coffee orderCoffee(String type) {Coffee coffee = factory.createCoffee();coffee.addMilk();coffee.addsugar();return coffee;}
}

从以上的编写的代码可以看到,要增加产品类时也要相应地增加工厂类,不需要修改工厂类的代码了, 这样就解决了简单工厂模式的缺点。

工厂方法模式是简单工厂模式的进一步抽象。由于使用了多态性,工厂方法模式保持了简单工厂模式的优点,而且克服了它的缺点。

1.3.4 优缺点

优点:

         用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程。

在系统增加新的产品时只需要添加具体产品类和对应的具体工厂类,无须对原工厂进行任何修改, 满足开闭原则。

缺点:

每增加一个产品就要增加一个具体产品类和一个对应的具体工厂类,这增加了系统的复杂度。


1.4 抽象工厂模式

前面介绍的工厂方法模式中考虑的是一类产品的生产,如畜牧场只养动物、电视机厂只生产电视机、软件工程只培养计算机软件专业的学生等。

  这些工厂只生产同种类产品,同种类产品称为同等级产品,也就是说:工厂方法模式只考虑生产同等级的产品,但是在现实生活中许多工厂是综合型的工厂,能生产多等级(种类)的产品,如电器厂既生 产电视机又生产洗衣机或空调,大学既有软件专业又有生物专业等。

抽象工厂模式将考虑多等级产品的生产,将同一个具体工厂所生产的位于不同等级的一组 产品称为一个产品族,下图所示横轴是产品等级,也就是同一类产品;纵轴是产品族,也就是同一品牌 的产品,同一品牌的产品产自同一个工厂。

可以理解为数学上的二维坐标轴X, Y分别表示产品等级产品族,X坐标相等的就是在同一级别中,Y也是同理

1.4.1 概念

是一种为访问类提供一个创建一组相关或相互依赖对象的接口,且访问类无须指定所要产品的具体类就 能得到同族的不同等级的产品的模式结构。 抽象工厂模式是工厂方法模式的升级版本,工厂方法模式只生产一个等级的产品,而抽象工厂模式可生 产多个等级的产品。

1.4.2 结构

抽象工厂模式的主要角色如下:

  • 抽象工厂(Abstract Factory):提供了创建产品的接口,它包含多个创建产品的方法,可以 创建多个不同等级的产品。
  • 具体工厂(Concrete Factory):主要是实现抽象工厂中的多个抽象方法,完成具体产品的创建。
  • 抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能,抽象工厂模式有多个抽象产品。
  • 具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来创建,它 同具体工厂之间是多对一的关系。

1.4.3 实现

现咖啡店业务发生改变,不仅要生产咖啡还要生产甜点,如提拉米苏、抹茶慕斯等,要是按照工厂方法模式,需要定义提拉米苏类、抹茶慕斯类、提拉米苏工厂、抹茶慕斯工厂、甜点工厂类,很容易发生类爆炸情况。其中拿铁咖啡、美式咖啡是一个产品等级,都是咖啡提拉米苏、抹茶慕斯也是一个产品等级拿铁咖啡和提拉米苏是同一产品族(也就是都属于意大利风味)美式咖啡和抹茶慕斯是同一产品族(也就是都属于美式风味)

所以这个案例可以使用抽象工厂模式实现。

类图如下:

代码: 

 抽象工厂:

public interface DessertFactory {Coffee createCoffee();Dessert createDessert();
}

 具体工厂:

//美式风味工厂
public class AmericanDessertFactory implements DessertFactory {public Coffee createCoffee() {return new AmericanCoffee();}public Dessert createDessert() {return new MatchaMousse();}}//意大利风味工厂
public class ItalyDessertFactory implements DessertFactory {public Coffee createCoffee() {return new LatteCoffee();}public Dessert createDessert() {return new Tiramisu();}
}

如果要加同一个产品族的话,只需要再加一个对应的工厂类即可,不需要修改其他的类。

1.4.4 优缺点

优点

当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。

缺点:

当产品族中需要增加一个新的产品时,所有的工厂类都需要进行修改。

1.4.5 使用场景

  1. 当需要创建的对象是一系列相互关联或相互依赖的产品族时,如电器工厂中的电视机、洗衣机、空调等。
  2. 系统中有多个产品族,但每次只使用其中的某一族产品。如有人只喜欢穿某一个品牌的衣服和鞋。或者每次使用不同族的不同商品时,如有人喜欢不同牌子的穿搭方式
  3. 系统中提供了产品的类库,且所有产品的接口相同,客户端不依赖产品实例的创建细节和内部结构。

1.5 JDK源码解析  Conlletion.iterator方法

代码:

public class Demo {public static void main(String[] args) {List<String> list = new ArrayList<>();list.add("令狐冲");list.add("风清扬");list.add("任我行");//获取迭代器对象Iterator<String> it = list.iterator();//使用迭代器遍历while(it.hasNext()) {String ele = it.next();System.out.println(ele);}}
}

对上面的代码大家应该很熟,使用迭代器遍历集合,获取集合中的元素。而单列集合获取迭代器的方法 就使用到了工厂方法模式。

类图结构:

   Collection接口是抽象工厂类,ArrayList是具体的工厂类;Iterator接口是抽象商品类, ArrayList类中的Iter内部类是具体的商品类。在具体的工厂类中iterator()方法创建具体的商品 类的对象。

设计模式-05 (工厂模式)相关推荐

  1. 设计模式之工厂模式05

    获取继承该接口的所有类#设计模式之工厂模式05 目标 女娲补天的故事大家都听说过吧,今天不说这个,说女娲创造人的故事,可不是"造人"的工作,这个词被现代人滥用了.这个故事是说,女娲 ...

  2. Java设计模式(工厂模式>抽象工厂模式和原型模式)

    Java设计模式Ⅱ 1.工厂模式 1.1 简单工厂模式 1.2 工厂方法模式 2.抽象工厂模式 3.总结 4.原型模式 4.1 原型模式 4.2 浅拷贝 4.3 深拷贝 5.建造者模式 1.工厂模式 ...

  3. JavaScript设计模式--简单工厂模式例子---XHR工厂

    JavaScript设计模式--简单工厂模式例子---XHR工厂 第一步,Ajax操作接口(目的是起一个接口检测作用) (1)引入接口文件 //定义一个静态方法来实现接口与实现类的直接检验 //静态方 ...

  4. 三角形圆形创建与擦除java_设计模式---------------简单工厂模式

    设计模式---------------简单工厂模式 一.题目(Question) 使用简单工厂模式设计一个可以创建不同几何形状(如圆形.方形和三角形等)的绘图工具,每个几何图形都要有绘制draw()和 ...

  5. 策略模式和工厂模式的区别_设计模式之工厂模式-工厂方法模式

    设计模式之工厂模式-工厂方法模式 大家好,欢迎来到污污弹公司,今天司小司又接到了一个新活-披萨项目. 来源:凯哥Java(kaigejava) 需求: 披萨项目: 要方便披萨品种的扩展.要便于维护.要 ...

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

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

  7. 设计模式之工厂模式(三)

    上一次我们已经通过代码,简单的认识了工厂方法模式,具体的思路请移步到设计模式之工厂模式(二),进行查看.这次,让我们通过设计模式的思想,来好好认识下工厂方法模式. 创建者和产品 所有工厂模式都用来封装 ...

  8. php工厂模式和单例模式,php 设计模式之工厂模式、单例模式、注册树模式

    php 设计模式之工厂模式.单例模式.注册树模式 在软件工程中,创建型设计模式承担着对象创建的职责,尝试创建适合程序上下文的对象,对象创建设计模式的产生是由于软件工程设计的问题,具体说是向设计中增加复 ...

  9. 教你如何一篇博客读懂设计模式之—--工厂模式

    一篇博客读懂设计模式之-工厂模式 工厂模式在我们日常开发的时候经常用到,相信大家都有了一定的了解,工厂模式是一种创建对象的设计模式,它提供一种创建对象的最佳方式. 主要过程是: 定义一个创建对象的接口 ...

最新文章

  1. 一次 JVM 调优的笔记
  2. 限制Apache日志access.log、error.log文件大小
  3. git diff old mode 100644 new mode 100755
  4. Laravel Eloquent关联模型查询设置查询条件与指定字段
  5. 繁体字_学认繁体字?你可能是低估了汉字的难度
  6. multipartfile 获取文件路径_Excel工作表中的20个信息函数,获取文件路径,单元格格式等!...
  7. cocos2d-js 开发常用方法
  8. 低通滤波器的设计与DSP实现
  9. 9小时速返地球!刚刚,神舟十三号返回舱平安降落,三位航天员“感觉良好”...
  10. 数字贸易标准体系框架
  11. 十年经验教你如何学习嵌入式系统
  12. mysql 校对规则_MySQL:校对规则
  13. 开关电源的开关管一般用MOS管而不是三极管原因
  14. 磁滞回线如何用计算机画图,利用Origin8.5软件简化磁滞回线数据处理
  15. 微信小程序实战篇-下拉刷新与加载更多
  16. cmake时添加-fPIC编译选项
  17. 字符数组的初始化及字符串的使用
  18. 汉诺塔问题及时间复杂度推导
  19. 多因子选股Alpha策略
  20. JAVA——多线程【线程终止、中断、插队】

热门文章

  1. 第一篇:mybatis源码入门
  2. 大厂设计师都在“抄”的作品集网站
  3. Python—selenium实现自动打开360浏览器并自动登录社保网站
  4. SD-WAN设备白盒刷机
  5. 面试直通车之网络部分
  6. java serializable_Java基础之Serializable接口
  7. mitmproxy使用详解
  8. Zabbix和agent端部署、图示Zabbix Web端搭建以及添加设备的4种方法、Zabbix API
  9. 如何下载安装oracle可视化工具PL/SQL Developer
  10. DBSCAN原理及实现